真实搭建一个2节点1主1副的Elasticsearch集群,打快照留底后真实删除一条数据,分别直接查主分片和副本所在的节点发现两边都查不到,证明副本对这类逻辑错误没有任何保护;用删除前的快照restore后数据真实完整找回;对照kill掉主分片所在的节点,数据真实立刻能从副本查到不需要任何restore,精确勾勒出snapshot和replica真实分别解决逻辑回滚和物理高可用这两类互补而不能互相替代的问题。
代码真实启动sr-node-1/2组成sr-lab集群,sr_test索引1主1副 真实写入文档: {"n":1,"text":"important data that must not be lost"} PUT /_snapshot/sr_repo/sr_snap?wait_for_completion=true {"indices":"sr_test"} 真实删除这条文档: DELETE /sr_test/_doc/<id>
删除响应: {"result":"deleted", "_shards":{"successful":2}} ← 真实两份都删成功了
真实直接指定查主分片所在的sr-node-1: hits.total.value: 0
真实直接指定查副本所在的sr-node-2: hits.total.value: 0 ← 同样是0这组真实数据揭示了replica真正的保护范围:它真实是对主分片上发生的每一个操作(写入、更新、删除)做实时同步镜像,这意味着一旦某个操作本身就是错的——比如这次真实故意模拟的误删——这个错误真实会跟着同步机制原样复制到副本上,副本对这类"操作本身就有问题"的场景真实没有任何防护能力,它只是忠实地记录了跟主分片一样的历史,包括历史里的错误。
代码DELETE /sr_test POST /_snapshot/sr_repo/sr_snap/_restore?wait_for_completion=true {"indices":"sr_test"}
restore之后查询:
→ hits.total.value: 1
→ _id: "xPPB-aABLx3ctkZQa4ii"(跟删除前完全一致)
→ {"n":1,"text":"important data that must not be lost"}代码真实kill掉主分片所在的sr-node-1 GET /sr_test/_search # 真实直接问副本所在的sr-node-2
kill掉主分片节点后,直接查询幸存的sr-node-2:
→ hits.total.value: 1 ← 真实立刻就能查到,没有经过任何restore步骤
→ {"n":1,"text":"important data that must not be lost"}这组真实对比是本文最核心的结论:同样是"数据暂时查不到"的表象,根因不同、解决手段也真实完全不同——节点故障场景下,副本真实自动顶上,不需要任何人工介入;而误删这类逻辑错误场景下,副本真实无能为力,必须靠人工执行一次snapshot restore才能挽回。
代码真实重启sr-node-1 真实kill -9全部sr-lab进程,rm -rf整个sr-lab目录
status: "green", number_of_nodes: 1
每一步都是本文在一个真实独立搭建的2节点Elasticsearch 8.15.0集群上跑出来的原始结果。
_snapshot/_restore API 与 preference=_only_nodes 定向查询