介绍
索引recovery是指索引数据恢复,包含以下几种类型
- EMPTY_STORE, 索引没有数据,一般是新建索引的情况,不用恢复数据
- EXISTING_STORE, 从本地存储的数据恢复,例如集群重启primary shard进行数据恢复
- PEER, 从另一个节点恢复数据,例如集群重启replica从primary恢复数据;primary进行relocate到另一个节点
- SNAPSHOT, 从SNAPSHOT中恢复数据
- LOCAL_SHARDS,从本节点的其他shard恢复数据,例如shrink操作
recovery过程包含以下几个阶段
- INIT 初始化阶段,还没开始恢复数据
- INDEX 恢复Lucene文件,要么复用本地的文件,要么从其他节点复制文件
- VERIFY_INDEX 对分片(Lucene index)进行检查是否损坏
- TRANSLOG 启动index engine,重放translog
- FINALIZE 当translog重放完成后,执行最后的任务
- DONE recovery结束
今天我们介绍下 从本地存储的数据恢复的recovery流程,后面我会另写一篇博客介绍从另一个节点恢复数据的过程。
primary shard重启具体流程
master node
- 完成EXISTING_STORE的分片分配,具体流程可见我的另一个博客,广播新的cluster state
data node (updateTask threadpool)
- 触发IndicesClusterStateService.applyClusterState,应用集群状态
- 触发recovery,状态为init
- 标记分片状态为RECOVERING,在generic线程池执行recoverFromStore
data node (generic threadpool)
- 更新recovery状态为index,获取最后一个提交点(commit point)的提交的segment info(segment的元数据)。如果有说明索引文件都存在,没有则抛出异常
- 用segment info填充recovery state中的lucene index数据,例如cat api就需要这个数据,观测recovery进度。如果是EMPTY_STORE的情况,将在目录下创建Index, translog相关的文件
- 进入VERIFY_INDEX阶段。如果开启index.shard.check_on_startup,则检查索引文件(默认关闭),会进行检查checksum或检查文件的每个字节,取决于这个配置
- 进入TRANSLOG阶段。打开新的engine,关闭GcDeletes(因为recovery时允许执行doc的CRUD,所以需要保证delete operation不会被丢失,因为delete操作执行后将没有记录。gc_delete详见https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-delete.html)
- 生成translog快照,遍历从local checkpoint到最后的每条数据进行回放,回放重走Lucene写入流程
- 执行flush来commit新写入的数据,清除translog
- 进入FINALIZE阶段。执行refresh,将缓冲数据写入segment,使数据可读;打开GcDeletes
- 如果整体流程成功,发送shard started请求给master;失败则发送shard failure
总结
- 总流程比较简单,主要是读取本地索引文件的元数据和从translog恢复数据,基于cluster state变更的时间触发,完成时在触发shard started的更新集群状态的请求
- ES利用recovery流程完成了新建分片的相关物理文件的创建工作