为什么需要recovery?对于主分片来说,可能有一些数据没来得及
刷盘;对于副分片来说,一是没刷盘,二是主分片写完了,副分片还没
来得及写,主副分片数据不一致。
1. 主分片recovery
由于每次写操作都会记录事务日志(translog),事务日志中记录
了哪种操作,以及相关的数据。因此将最后一次提交(Lucene 的一次提
交就是一次 fsync 刷盘的过程)之后的 translog中进行重放,建立Lucene
索引,如此完成主分片的recovery。
2. 副分片recovery
副分片的恢复是比较复杂的,在ES的版本迭代中,副分片恢复策略
有过不少调整。
副分片需要恢复成与主分片一致,同时,恢复期间允许新的索引操
作。在目前的6.0版本中,恢复分成两阶段执行。
· phase1:在主分片所在节点,获取translog保留锁,从获取保留锁
开始,会保留translog不受其刷盘清空的影响。然后调用Lucene接口把
shard做快照,这是已经刷磁盘中的分片数据。把这些shard数据复制到
副本节点。在phase1完毕前,会向副分片节点发送告知对方启动
engine,在phase2开始之前,副分片就可以正常处理写请求了。
· phase2:对translog做快照,这个快照里包含从phase1开始,到执
行translog快照期间的新增索引。将这些translog发送到副分片所在节点
进行重放。
由于需要支持恢复期间的新增写操作(让ES的可用性更强),这两
个阶段中需要重点关注以下几个问题。
分片数据完整性:如何做到副分片不丢数据?第二阶段的 translog
快照包括第一阶段所有的新增操作。那么第一阶段执行期间如果发
生“Lucene commit”(将文件系统写缓冲中的数据刷盘,并清空
translog),清除translog怎么办?在ES 2.0之前,是阻止了刷新操作,以
此让translog都保留下来。从2.0版本开始,为了避免这种做法产生过大
的translog,引入了translog.view的概念,创建 view 可以获取后续的所有
操作。从6.0版本开始,translog.view 被移除。引入
TranslogDeletionPolicy的概念,它将translog做一个快照来保持translog不
被清理。这样实现了在第一阶段允许Lucene commit。