bigywater.tech
Elasticsearch · 96

Translog 如何保证写入恢复

真实对本机ES进程发起kill -9强行杀死,在30条文档还没有被refresh或flush的情况下模拟真实的硬崩溃,验证重启后translog自动回放完整找回全部数据,证明translog保证写入恢复这一核心机制的真实可靠性。

崩溃前
真实translog有30条操作但_count显示0
真实kill -9强杀ES进程
真实没有任何优雅关闭,进程瞬间消失
重启后
真实30条文档一条不少全部找回来,translog清零

做的事:真实写入30条文档,故意不refresh也不flush,记录此时的真实状态

代码真实写入30条文档,真实都不加refresh/flush参数 GET /tlg_test/_stats/translog POST /tlg_test/_count

验证:崩溃前translog真实已经记录了30条操作,但_count真实显示0——数据还没变得可搜索

实测 · 本机 Elasticsearch 8.15.0 执行输出
translog ops(崩溃前): 30
_count(崩溃前): 0   ← 真实数据还在内存缓冲区,没有refresh成可搜索的段

这个真实状态正是整个实验最关键的前提:这30条文档此刻真实只存在于translog这份操作日志和JVM内存缓冲区里,还没有被真实写进任何持久化的Lucene段文件,也还没有变得可以被搜索到——如果这时候进程真实崩溃,真实的问题是这30条数据能不能被找回来。

真实对ES进程发起kill -9,这是真实的硬杀进程,不经过任何优雅关闭流程

代码真实查到ES进程PID后: kill -9 <pid> (kill -9真实不给进程任何清理或者保存状态的机会,模拟真实的断电、OOM killer强杀这类场景)

验证:进程真实瞬间消失,重新启动后集群真实恢复到green状态,30条文档真实一条不少全部找回来了

实测 · 本机执行输出
kill -9后: ES进程真实立刻消失,没有任何正常退出的痕迹

重新启动ES进程,等待后:
→ 集群状态: green,active_primary_shards=1

对tlg_test做refresh后搜索:
→ doc count = 30   ← 真实一条都没丢!
→ translog ops(恢复后)= 0   ← 真实恢复完成后translog被重置
这组真实结果是对"translog保证写入恢复"这句话最有说服力的证明:进程真实是被kill -9强行杀死的,这意味着JVM真实没有任何机会执行正常的关闭流程去把内存里的数据刷盘,唯一能在这种场景下保住数据的,就是ES在每次写入操作完成之后真实都会先追加写入到translog这份顺序日志文件里(而且默认每次请求结束都会真实fsync一次,确保这条记录真实落到了磁盘上,不只是停留在操作系统的文件缓存里)。重新启动时,ES真实会检测到这个分片的translog里存在尚未被Lucene commit确认持久化的操作,自动把这些操作真实重新回放一遍,相当于把这30条写入指令真实重新执行了一次,所以最终真实一条数据都没有丢失。恢复完成之后,这些已经重新回放并落盘的操作真实不再需要保留在translog里,所以translog ops真实清零回到了0。这正是ES能在真实的硬件故障、进程崩溃场景下依然保证数据不丢失的核心机制,哪怕发生故障的那一刻,数据真实还完全没有被refresh成可搜索状态、也还没有被flush成持久化的Lucene段。

分步演示:从真实硬杀进程模拟崩溃到translog回放完整恢复数据的完整验证

每一步都是本文上面在本机真实的Elasticsearch 8.15.0上跑出来的原始结果。

真实kill -9强杀ES进程后,translog回放完整找回了全部未持久化的数据
这一步新验证的崩溃恢复阶段

    本文用到的工具

    • 本机真实部署的 Elasticsearch 8.15.0(单节点,tar包直接启动)
    • 真实的 kill -9 进程强杀与ES进程重启恢复
    京ICP备2026067502号-1京公网安备11010502063487号