1. 为什么单点ES不是“入门”,而是“踩坑起点”
很多人看到“安装Elasticsearch”这六个字,第一反应是:不就是下载、解压、启动一个服务吗?我试过三次,每次都在同一个地方卡住——不是端口被占,就是JVM内存爆掉,更常见的是Kibana连不上ES,页面一直转圈,控制台报错Unable to connect to Elasticsearch at http://localhost:9200。后来我才明白,这不是配置问题,而是认知偏差:把ES当普通Web服务装,就等于用螺丝刀拧火箭发动机的固定螺栓——工具对了,场景全错。
Elasticsearch本质是一个分布式搜索引擎,它的设计哲学从第一天起就拒绝“单点思维”。哪怕你只部署一个节点,它内部仍按集群模式初始化:自动生成cluster.name、分配node.id、启动transport和http两个通信通道、尝试发现其他节点……这些行为在单点环境下看似冗余,实则埋下了大量隐性故障点。比如默认配置里discovery.type: single-node是7.0之后才加的补丁,而6.x版本必须手动关闭多播发现、禁用master选举逻辑,否则节点会反复进入“等待集群形成”状态,导致HTTP服务迟迟不响应。
更关键的是,单点部署不是简化,而是隔离。IK分词器这类插件,必须和ES进程同生命周期加载;Kibana作为独立服务,其索引管理、可视化配置又高度依赖ES的API稳定性。三者表面独立,实则构成一个脆弱的三角依赖链:ES启动慢1秒,Kibana健康检查就失败;IK加载失败,ES日志里只有一行failed to load plugin [analysis-ik],但根本不会告诉你缺了哪个jar包或配置文件权限不对。
我见过最典型的误操作,是某开发者在CentOS上用root用户解压ES,然后切到普通用户启动——结果因为plugins/analysis-ik/config目录权限为755(root所有),普通用户无法读取IKAnalyzer.cfg.xml,ES静默跳过插件加载,后续所有中文搜索都返回空结果。这种问题不会报错,只会让你花三天时间怀疑业务代码逻辑。
所以这篇内容不叫“ES安装教程”,而叫“ES服务化部署实战”。它要解决的不是“怎么让9200端口通”,而是“如何让ES、Kibana、IK三者稳定共存,且具备向集群平滑演进的能力”。接下来每一环节的设计,都围绕这个目标展开:配置项为什么选这个值?命令为什么加这个参数?目录结构为什么这样组织?——所有答案,都来自某次凌晨三点重启失败后翻看的378行ES日志。
2. 单点ES部署:从解压到可写索引的七步闭环
单点ES部署常被简化为“下载→解压→启动”三步,但实际生产级单点环境需要七步闭环验证。少任何一环,后续Kibana连接或IK分词都会出现不可预测的异常。下面以Elasticsearch 8.12.2(当前LTS版本)为例,完整还原真实操作链。
2.1 环境预检:绕过90%的启动失败
ES对运行环境极其敏感,必须前置验证三项核心指标:
JVM版本与内存策略:ES 8.x强制要求JDK 17+,且禁止使用G1GC以外的垃圾回收器。执行
java -version确认输出含17.0.x字样;通过java -XX:+PrintGCDetails -version 2>&1 | grep -i g1验证G1GC已启用。若系统默认JDK非17,需在/etc/profile中显式设置JAVA_HOME=/path/to/jdk-17,并确保PATH中$JAVA_HOME/bin排在系统java前。Linux内核参数调优:ES要求
vm.max_map_count≥262144。执行sysctl vm.max_map_count查看当前值,若低于此数,临时生效用sudo sysctl -w vm.max_map_count=262144,永久生效则编辑/etc/sysctl.conf追加vm.max_map_count=262144。注意:Docker容器内需在docker run时加--sysctl vm.max_map_count=262144参数,宿主机设置对容器无效。文件描述符限制:ES进程需打开大量文件句柄。检查
ulimit -n,标准值应≥65536。若不足,修改/etc/security/limits.conf,添加两行:* soft nofile 65536 * hard nofile 65536并确保
/etc/pam.d/common-session包含session required pam_limits.so。重启终端或执行ulimit -n 65536临时生效。
提示:以上三项任一未达标,ES启动日志中会出现
max file descriptors [4096] for elasticsearch process is too low或max virtual memory areas vm.max_map_count [65530] is too low等明确提示。但新手常忽略日志首屏,直接看最后几行started就以为成功,实则服务处于半死状态。
2.2 解压与目录结构标准化
下载官方tar.gz包(如elasticsearch-8.12.2-linux-x86_64.tar.gz)后,禁止直接解压到/opt或/usr/local根目录下。正确做法是创建版本隔离目录:
mkdir -p /data/es/8.12.2 tar -xzf elasticsearch-8.12.2-linux-x86_64.tar.gz -C /data/es/8.12.2 --strip-components=1--strip-components=1参数至关重要——它剥离顶层目录名(如elasticsearch-8.12.2),使解压后路径为/data/es/8.12.2/bin而非/data/es/8.12.2/elasticsearch-8.12.2/bin。这样做的好处是:未来升级时只需替换/data/es/8.12.2目录,再软链接/data/es/current → /data/es/8.12.2,所有脚本路径保持不变。
接着建立符号链接统一入口:
ln -sf /data/es/8.12.2 /data/es/current2.3 配置文件精简改造:只保留必要字段
ES 8.x默认启用安全特性,首次启动会自动生成证书和密码。但单点开发环境无需此复杂度,需在/data/es/current/config/elasticsearch.yml中做最小化配置:
# 基础标识 cluster.name: my-es-cluster node.name: node-1 node.roles: [ data, ingest, ml, remote_cluster_client ] # 网络绑定(关键!) network.host: 0.0.0.0 http.port: 9200 transport.port: 9300 # 单点专用配置(ES 8.x必须显式声明) discovery.type: single-node # JVM内存(根据物理内存设定,非默认值) # 编辑 /data/es/current/config/jvm.options # -Xms4g # -Xmx4g # 安全关闭(开发环境可禁用) xpack.security.enabled: false xpack.monitoring.collection.enabled: false特别注意network.host: 0.0.0.0:ES 8.x默认绑定127.0.0.1,导致Kibana(若运行在另一容器或远程机器)无法访问。此处必须放开,但需配合防火墙策略(如ufw allow 9200)保障安全。
2.4 启动验证:从进程到API的四层检测
启动命令必须指定用户(禁止root):
# 创建es用户 useradd -m -u 1001 -g 0 -d /data/es es chown -R es:0 /data/es # 切换用户启动 sudo -u es /data/es/current/bin/elasticsearch -d -p /data/es/current/es.pid验证不能只看ps aux | grep elasticsearch,需逐层确认:
- 进程层:
cat /data/es/current/es.pid获取PID,kill -0 $(cat /data/es/current/es.pid)检测进程存活; - 端口层:
ss -tlnp | grep :9200确认9200端口监听,且State为LISTEN; - HTTP层:
curl -v http://localhost:9200,应返回200及JSON响应体,含"version":{"number":"8.12.2"}; - 功能层:
curl -XPUT "http://localhost:9200/test-index?pretty" -H 'Content-Type: application/json' -d'{"settings":{"number_of_shards":1}}',再curl "http://localhost:9200/test-index/_search?pretty"验证索引可写可查。
注意:第4步必须执行!很多教程止步于curl返回200,但ES可能因磁盘空间不足(
/data/es所在分区剩余<5%)而拒绝创建索引,此时_search返回index_not_found_exception。提前验证写入能力,能避免后续Kibana创建索引模式时的诡异报错。
2.5 日志分析:读懂ES启动时的“潜台词”
ES日志位于/data/es/current/logs/,主日志文件名为my-es-cluster.log。启动成功的关键标志不是started,而是以下三行连续出现:
[INFO ][o.e.n.Node ] [] version[8.12.2], pid[12345], build[...], OS[Linux/5.15.0-91-generic/amd64], JVM[Oracle Corporation/OpenJDK 64-Bit Server VM/17.0.9] [INFO ][o.e.h.AbstractHttpServerTransport] [node-1] publish_address {192.168.1.100:9200}, bound_addresses {[::]:9200} [INFO ][o.e.n.Node ] [node-1] started其中第二行publish_address显示的实际IP地址,必须与Kibana配置中的elasticsearch.hosts完全一致。若显示127.0.0.1:9200,说明network.host未生效,需检查配置文件缩进(YAML对空格敏感)或是否被elasticsearch.yml同目录下的.yml.swp临时文件干扰。
2.6 权限加固:避免“权限地狱”的终极方案
ES要求数据目录(/data/es/current/data)和日志目录(/data/es/current/logs)由启动用户独有。执行:
chown -R es:0 /data/es/current/{data,logs,config} chmod 750 /data/es/current/{data,logs,config}特别注意config目录:若elasticsearch.yml权限为644但属主为root,ES会拒绝启动并报错config directory [/data/es/current/config] is not writable。这是ES 7.x后新增的安全校验,防止配置被恶意篡改。
2.7 故障快照:保存可复现的诊断包
每次部署成功后,立即生成诊断快照:
# 打包关键配置与状态 tar -czf es-deploy-snapshot-$(date +%Y%m%d).tar.gz \ /data/es/current/config/elasticsearch.yml \ /data/es/current/config/jvm.options \ /data/es/current/logs/my-es-cluster.log \ <(curl -s http://localhost:9200/_cat/nodes?v) \ <(curl -s http://localhost:9200/_cat/indices?v)该压缩包包含:配置原文、JVM参数、启动日志、节点状态、索引列表。当后续出现问题时,对比快照即可快速定位变更点——比如某次更新后_cat/nodes显示role列从di变为nil,说明node.roles配置失效。
3. Kibana部署:解耦ES依赖与前端路由陷阱
Kibana不是ES的“图形界面”,而是一个独立的数据分析平台,它与ES的关系类似浏览器与网站:Kibana通过HTTP API消费ES数据,自身不存储业务数据。因此,Kibana部署的核心矛盾是——如何让前端资源加载不被ES网络策略阻断。
3.1 版本锁死:为什么Kibana 8.12.2必须配ES 8.12.2
ES与Kibana的API协议并非完全向后兼容。例如ES 8.10引入的_search?track_total_hits=false参数,在Kibana 8.9中解析失败会导致仪表板空白。官方文档明确要求“Kibana版本号必须与ES主版本号一致”,即8.x配8.x。验证方法:启动Kibana后访问http://kibana-host:5601/api/status,响应中elasticsearch.version字段必须与ES的/接口返回值完全相同。
下载Kibana tar.gz包后,同样采用版本隔离目录:
mkdir -p /data/kibana/8.12.2 tar -xzf kibana-8.12.2-linux-x86_64.tar.gz -C /data/kibana/8.12.2 --strip-components=1 ln -sf /data/kibana/8.12.2 /data/kibana/current3.2 配置文件重构:绕过CORS与反向代理的双重迷宫
Kibana 8.x默认启用安全认证,但开发环境需关闭。关键配置在/data/kibana/current/config/kibana.yml:
# 服务绑定 server.host: "0.0.0.0" server.port: 5601 server.publicBaseUrl: "http://localhost:5601" # ES连接(必须与ES的publish_address一致) elasticsearch.hosts: ["http://192.168.1.100:9200"] # 注意:这里填ES日志中publish_address的IP! # 安全关闭 elasticsearch.ssl.verificationMode: none elasticsearch.username: "kibana_system" elasticsearch.password: "changeme" # ES 8.x首次启动生成的密码,见ES日志中"password for the kibana_system user is" xpack.security.enabled: false # 关键:禁用强制HTTPS重定向(否则HTTP访问自动跳转HTTPS失败) server.ssl.enabled: false此处elasticsearch.hosts的IP必须与ES日志中publish_address完全一致。若ES日志显示{192.168.1.100:9200},此处绝不能写localhost或127.0.0.1——因为Kibana进程发起HTTP请求时,localhost指向自身,而非ES所在机器。
3.3 启动与健康检查:识别“假成功”状态
启动Kibana:
sudo -u kibana /data/kibana/current/bin/kibana --allow-root &验证不能只看curl http://localhost:5601返回HTML,需检查三个深层状态:
Kibana日志健康线:
tail -f /data/kibana/current/logs/kibana.log,成功标志是连续出现:[info][savedobjects-service] Waiting until all Elasticsearch nodes are compatible [info][savedobjects-service] Starting saved objects migrations [info][plugins-system] Setting up [105] plugins [info][http.server.Preboot] http server running at http://localhost:5601ES连接确认:
curl -s http://localhost:5601/api/status | jq '.status.overall.state',返回"green"才算真正连通。若返回"red",检查ES是否运行、网络是否通畅、密码是否正确。前端资源加载:打开浏览器开发者工具,切换到Network标签,刷新Kibana页面。观察
/api/status请求的Response Headers中是否有x-elastic-product: kibana,且所有/built_assets/开头的JS/CSS请求返回200。若出现404,说明Kibana未正确解析server.publicBaseUrl,需检查配置中是否漏掉末尾斜杠。
注意:Kibana 8.x前端资源路径硬编码为
/built_assets/,若通过Nginx反向代理,必须配置location /built_assets/代理到Kibana,否则页面白屏。这是新手最常踩的坑——以为代理了/就万事大吉,实则静态资源路径被截断。
3.4 索引模式创建:从“无数据”到“可分析”的临界点
Kibana首次登录后,需手动创建索引模式才能查询数据。流程如下:
- 访问
http://localhost:5601/app/home#/tutorial_directory/sampleData,点击Add sample data加载示例数据(自动生成kibana_sample_data_ecommerce索引); - 进入
Stack Management → Index Patterns → Create index pattern; - 输入
kibana_sample_data_ecommerce,点击Next step; - 在
Time field下拉框选择@timestamp(示例数据中存在该字段),点击Create index pattern。
此时若页面报错Could not locate that index-pattern-field (id: @timestamp),说明ES中该索引无@timestamp字段。解决方案:删除索引重建,或在创建索引模式时勾选Index contains time-based events并手动指定时间字段。
3.5 插件管理:为什么Kibana插件必须与ES插件分离
Kibana本身支持插件(如kibana-prometheus-exporter),但IK分词器是ES插件,与Kibana无关。常见误区是试图在Kibana中安装IK,这会导致Kibana启动失败。正确逻辑是:IK处理文本分词,ES返回分词结果,Kibana仅负责展示。因此,Kibana配置中无需任何IK相关设置。
验证IK是否生效:在Kibana的Dev Tools → Console中执行:
POST /test-index/_analyze { "analyzer": "ik_max_word", "text": "中华人民共和国" }若返回["中华人民共和国","中华人民","中华","华人","人民","共和国"],说明IK已正确加载;若报错analyzer [ik_max_word] not found,则问题出在ES端,与Kibana无关。
3.6 性能调优:前端卡顿的真相是ES查询超时
Kibana仪表板卡顿,90%原因不在前端,而在ES查询超时。默认ES查询超时为1m,但Kibana的search:timeout配置为30000(30秒)。当ES查询耗时35秒时,Kibana前端会显示Request Timeout,但ES日志中无错误——因为ES认为查询仍在执行。
解决方案:在kibana.yml中增加:
# 延长Kibana查询超时,匹配ES设置 elasticsearch.requestTimeout: 60000 # 降低Kibana自身缓存压力 savedObjects.maxImportExportSize: 10000同时在ES的elasticsearch.yml中设置:
# 全局查询超时 indices.query.bool.max_clause_count: 1024 # 搜索超时(影响Kibana) search.default_search_timeout: 60s3.7 故障隔离:当Kibana崩溃时,如何保全ES数据
Kibana崩溃不会影响ES数据,但会丢失Kibana自身的Saved Objects(仪表板、索引模式等)。这些数据默认存储在ES的.kibana索引中。为防意外,需定期导出:
# 导出所有Saved Objects curl -XPOST "http://localhost:5601/api/saved_objects/_export?excludeExportDetails=true" \ -H 'kbn-xsrf: true' \ -H 'Content-Type: application/json' \ -d '{"type":["dashboard","visualization","search","index-pattern"],"includeReferencesDeep":true}' \ > kibana-backup-$(date +%Y%m%d).ndjson该命令生成NDJSON格式备份,可随时用_importAPI恢复。注意:导出时需携带kbn-xsrf: true头,否则403拒绝。
4. IK分词器安装:从源码编译到热更新的全链路
IK分词器不是简单复制jar包就能用的“开箱即用”插件。它的安装过程暴露了ES插件机制的核心约束:插件必须与ES版本严格匹配,且加载时机决定分词效果。
4.1 版本映射:为什么IK 8.12.2不能用IK 8.11.0的包
IK分词器每个版本对应特定ES版本,因为其底层依赖ES的AnalysisModule类结构。ES 8.12.2的AnalysisModule新增了addCharFilter方法,而IK 8.11.0的代码未实现该方法,导致ES启动时抛出NoSuchMethodError。官方GitHub Release页明确标注Compatible with Elasticsearch 8.12.2。
下载地址必须从IK官方仓库获取:https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v8.12.2/elasticsearch-analysis-ik-8.12.2.zip。严禁使用第三方打包的“全版本合集”,那些zip包常混入不同ES版本的jar,导致类加载冲突。
4.2 安装路径与权限:插件目录的“隐形契约”
ES插件必须安装到/data/es/current/plugins/analysis-ik/目录,且该目录结构有严格约定:
analysis-ik/ ├── config/ │ ├── IKAnalyzer.cfg.xml │ └── custom/ ├── elasticsearch-analysis-ik-8.12.2.jar └── httpcomponents-core-4.4.14.jar # IK依赖的HTTP库安装命令:
# 进入ES插件目录 cd /data/es/current/plugins # 创建ik目录 mkdir analysis-ik # 解压IK zip包到analysis-ik目录 unzip elasticsearch-analysis-ik-8.12.2.zip -d analysis-ik/ # 修复权限(关键!) chown -R es:0 analysis-ik chmod -R 750 analysis-ik若config目录权限非750,ES启动时会静默跳过IK加载,日志中仅有一行[WARN ][o.e.p.PluginsService] [node-1] could not find plugin descriptor for plugin [analysis-ik],但不会终止启动。
4.3 配置文件深度定制:从停用词到扩展词典
IK默认词典位于config/main.dic,但生产环境需定制。IKAnalyzer.cfg.xml是核心配置文件:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties> <comment>IK Analyzer 扩展配置</comment> <!-- 用户可以在这里配置自己的扩展字典 --> <entry key="ext_dict">custom/my_words.dic</entry> <!-- 用户可以在这里配置自己的扩展停止词字典 --> <entry key="ext_stopwords">custom/my_stopwords.dic</entry> <!-- 用户可以在这里配置远程扩展字典 --> <!-- <entry key="remote_ext_dict">location</entry> --> </properties>创建扩展词典:
# 创建custom目录 mkdir -p /data/es/current/plugins/analysis-ik/config/custom # 添加自定义词汇(每行一个词,UTF-8编码) echo "人工智能" > /data/es/current/plugins/analysis-ik/config/custom/my_words.dic echo "大模型" >> /data/es/current/plugins/analysis-ik/config/custom/my_words.dic # 添加停用词 echo "的" > /data/es/current/plugins/analysis-ik/config/custom/my_stopwords.dic echo "了" >> /data/es/current/plugins/analysis-ik/config/custom/my_stopwords.dic注意:词典文件必须为UTF-8无BOM格式。Windows记事本保存的文件常带BOM,会导致IK加载失败。用
file -i my_words.dic检查编码,应显示charset=utf-8;若为charset=utf-8-with-bom,用iconv -f utf-8 -t utf-8//IGNORE my_words.dic > fixed.dic转换。
4.4 分词器验证:用ES原生API测试而非Kibana
Kibana的Dev Tools对中文分词支持有限,必须用ES的_analyzeAPI验证:
# 测试默认分词器 curl -XPOST "http://localhost:9200/_analyze" \ -H 'Content-Type: application/json' \ -d'{ "analyzer": "ik_max_word", "text": "人工智能大模型技术" }' # 测试自定义词典效果 curl -XPOST "http://localhost:9200/_analyze" \ -H 'Content-Type: application/json' \ -d'{ "analyzer": "ik_smart", "text": "人工智能大模型技术" }'ik_max_word应返回["人工智能","大模型","技术"](将“人工智能”和“大模型”作为整体切分);ik_smart应返回["人工智能","大模型","技术"](更粗粒度)。若返回["人工","智能","大","模型","技术"],说明自定义词典未生效,需检查config目录路径是否正确、文件编码是否UTF-8、ES是否重启。
4.5 热更新词典:不用重启ES的动态加载
IK支持远程词典热更新,避免频繁重启ES。在IKAnalyzer.cfg.xml中取消注释:
<entry key="remote_ext_dict">http://your-server.com/dict/my_words.dic</entry>ES会每隔60秒(可配置)请求该URL。为保障稳定性,需满足:
- URL必须返回HTTP 200,且
Content-Type为text/plain; charset=utf-8; - 服务器需支持
If-Modified-Since头,实现条件请求; - 词典文件更新后,ES日志中会出现
[INFO][o.a.i.d.RemoteExtDictionary] [node-1] Remote dictionary http://... updated。
本地测试可用Python快速启动HTTP服务:
# 将my_words.dic放在当前目录 python3 -m http.server 8000 # 配置IK指向 http://localhost:8000/my_words.dic4.6 故障排查:分词失效的五大根因
当_analyze返回不符合预期的分词结果时,按以下顺序排查:
| 排查层级 | 检查项 | 验证命令 | 典型现象 |
|---|---|---|---|
| 插件加载 | IK是否被ES识别 | curl http://localhost:9200/_cat/plugins?v | 输出无analysis-ik行 |
| 配置路径 | config目录位置 | ls -l /data/es/current/plugins/analysis-ik/config/ | config目录不存在或权限错误 |
| 词典编码 | 词典文件编码 | file -i /data/es/current/plugins/analysis-ik/config/custom/my_words.dic | 显示charset=utf-8-with-bom |
| 分词器名称 | analyzer名称拼写 | curl http://localhost:9200/_cat/analyzers?v | 返回空或ik_max_word不在列表中 |
| 索引映射 | 字段是否绑定IK | curl http://localhost:9200/test-index/_mapping?pretty | properties.text.analyzer未设为ik_max_word |
经验:80%的分词失败源于索引映射未绑定分词器。创建索引时必须显式指定:
PUT /test-index { "mappings": { "properties": { "content": { "type": "text", "analyzer": "ik_max_word", "search_analyzer": "ik_smart" } } } }
5. ES集群部署:从单点到三节点的拓扑演进
单点ES只是学习起点,真实业务必然走向集群。但集群不是“多启几个节点”,而是重新设计数据流、故障域和扩容路径。下面以三节点集群(1 master-eligible + 2 data)为例,揭示从单点平滑演进的关键决策点。
5.1 节点角色划分:为什么不能“全角色合一”
ES 7.x后废弃node.master/node.data旧配置,改用node.roles数组。三节点集群的标准角色分配:
| 节点 | node.roles | 说明 |
|---|---|---|
| node-1 | [master, ingest] | 专职协调,不存数据,避免数据节点压力影响集群管理 |
| node-2 | [data, remote_cluster_client] | 主数据节点,承载索引分片 |
| node-3 | [data, remote_cluster_client] | 备份数据节点,与node-2组成高可用 |
若所有节点都设[master, data, ingest],会导致:
- Master节点CPU飙升时,无法及时处理心跳,触发集群脑裂;
- Data节点磁盘满时,Master无法感知,继续分配分片导致雪崩。
配置示例(node-1的elasticsearch.yml):
cluster.name: my-es-cluster node.name: node-1 node.roles: [master, ingest] network.host: 192.168.1.101 http.port: 9200 transport.port: 9300 discovery.seed_hosts: ["192.168.1.101:9300", "192.168.1.102:9300", "192.168.1.103:9300"] cluster.initial_master_nodes: ["node-1", "node-2", "node-3"]5.2 发现机制:从单播到集群握手的三次握手
ES集群发现依赖discovery.seed_hosts和cluster.initial_master_nodes。前者是节点启动时主动连接的候选Master列表,后者是首次启动时参与Master选举的节点集合。
关键规则:
discovery.seed_hosts必须包含所有节点的transport.port地址(非http.port);cluster.initial_master_nodes必须是node.name列表,且与discovery.seed_hosts中的节点一一对应;- 首次启动集群时,必须按顺序启动:先启
node-1,待其日志出现master node changed后再启node-2,最后启node-3。若同时启动,可能因网络延迟导致多个节点自认Master,触发脑裂。
验证集群状态:
# 查看节点列表 curl "http://localhost:9200/_cat/nodes?v" # 查看集群健康 curl "http://localhost:9200/_cluster/health?pretty" # 查看分片分配 curl "http://localhost:9200/_cat/shards?v"健康状态为green且shards列表中state列全为STARTED,表示集群就绪。
5.3 索引分片策略:副本数与节点数的黄金比例
单点ES设number_of_replicas: 0合理,但集群必须设1。因为ES要求“每个分片的主副本不能在同一节点”,三节点集群设replicas: 1时,每个主分片自动分配一个副本到其他节点,实现故障转移。
计算公式:最大容错节点数 = replicas。即replicas: 1可容忍1个节点宕机,replicas: 2可容忍2个节点宕机。
但副本数非越多越好。replicas: 2会使存储成本翻三倍(1主+2副=3份),且写入性能下降。生产环境推荐:
- 日志类索引:
replicas: 1(平衡成本与可靠性); - 业务核心索引:
replicas: 2(容忍双节点故障); - 测试索引:
replicas: 0(节省资源)。
创建索引时指定:
PUT /logs-index { "settings": { "number_of_shards": 3, "number_of_replicas": 1 } }5.4 集群扩容:从三节点到五节点的无感升级
向现有集群添加新节点(node-4, node-5)时,无需重启任何节点。步骤如下:
在新机器部署ES,配置
elasticsearch.yml:cluster.name: my-es-cluster node.name: node-4 node.roles: [data, remote_cluster_client] network.host: 192.168.1.104 discovery.seed_hosts: ["192.168.1.101:9300", "192.168.1.102:9300", "192.168.1.103:9300"] # 注意:不配置 cluster.initial_master_nodes!启动新节点,ES自动加入集群;
观察分片再平衡:`curl "http://localhost:9200/_cat/shards