
2.4 Elasticsearch-故障转移实验:kill -9 节点后数据还能读吗?
上一章我们把 3 节点集群跑了起来,也验证了 shard 在节点间的分布。现在把“优雅”二字撕掉,直接拔电源——用 kill -9 模拟最暴力的节点宕机,看看 Elasticsearch 到底能不能把数据救回来,客户端还能不能读。
实验目标
- 验证主分片所在节点被强杀后,集群多久完成主分片重选(unassigned → active)。
- 验证副本分片能否无缝顶上来,查询零丢数。
- 观察客户端报错窗口与自动恢复时间。
- 给出生产环境减少“读不可用窗口”的调优点。
实验环境
与 2.3 节同一套 Docker Compose 环境,额外准备
- rally 压测容器:持续执行
geonames查询 track,qps≈200,并发 8。 - 自定义脚本:每 500 ms 轮询
GET /_cat/shards?v&s=index,把状态落盘,方便画时间线。 - 集群配置要点:
discovery.zen.minimum_master_nodes: 2 # 防止脑裂 gateway.recover_after_nodes: 2 # 至少见 2 个节点才恢复 cluster.routing.allocation.awareness.attributes: rack_id
实验步骤
Step 1 写入 300 GB geonames 数据,每个索引 3 主 1 副,共 6 个索引。
Step 2 启动 rally 持续查询,指标每 5 s 输出一次。
Step 3 找到承载索引 geonames-1 的主分片 0 的节点(假设为 es03)。
Step 4 在宿主机上对 es03 容器执行
docker exec -it es03 pkill -9 java
等价于直接拔电源,JVM 没机会写磁盘,也来不及清理 lock 文件。
Step 5 立即观察
- master 日志(es01)出现
failing shard routing entry ... primary failed GET /_cluster/health返回status=yellow,unassigned_shards=1- rally 侧出现少量
NoShardAvailableActionException,qps 掉 0 持续 3.8 s
Step 6 6.2 s 后,副本分片在 es02 被提升为 primary,cluster恢复 green。
Step 7 rally 的 qps 回到基线,校验 100 k 次随机 doc_id 读取,与 Step 1 的基准比对,0 丢失。
时间线复盘(ms 级)
t0 kill -9
t0+300 master 探测到 es03 失联,publish cluster state v162
t0+800 allocation service 开始选副本:选择 es02 分片,校验 sync_id 与 global checkpoint
t0+1200 es02 本地 shard 目录无写损坏,直接重用,标记为 active
t0+6200 旧主分片在 es03 被标记为 stale,allocation decider 清除,集群 green
结论
- 副本分片完整情况下,kill -9 单节点不会丢数据;主分片重建耗时 < 7 s。
- 读取侧可见 3~4 s 的“尖刺”异常,应用层需重试或熔断。
- 若副本分片为 0,则主分片丢失后集群直接 red,数据无法自动恢复,必须走快照还原或 reindex。
生产调优 checklist
- 副本数 ≥1 是硬底线,对重要索引设 2 副本,可容忍双节点同时挂。
- 使用
index.unassigned.node_left.delayed_timeout: 2m把 reallocation 延后,防止节点只是短暂 GC 重启就被踢。 - 开启
allocation.max_retries: 3与enable开关,避免人工介入前反复重试。 - 客户端配置
sniffing+retry_on_failure: 3,把 502/503 自动重定向到新主。 - 监控
es_allocation_stuck_seconds指标,超过 5 min 未恢复即告警。 - 对超热索引,把主副分片分布在不同机架(awareness),降低批量掉电风险。
一句话总结
Elasticsearch 的副本机制不是“备胎”,而是“随时待命的正胎”;只要副本在,kill -9 也杀不掉你的数据,但应用层必须做好秒级重试,才能把短暂的“黄灯”消化在用户无感知的范围内。
更多技术文章见公众号: 大城市小农民
2490

被折叠的 条评论
为什么被折叠?



