Elasticsearch Recovery 详细介绍


Posted in Java/Android onApril 19, 2022

基础知识点

在Eleasticsearch中recovery指的就是一个索引的分片分配到另外一个节点的过程;一般在快照恢复、索引副本数变更、节点故障、节点重启时发生。由于master保存整个集群的状态信息,因此可以判断出哪些shard需要做再分配,以及分配到哪个结点,例如:

如果某个shard主分片在,副分片所在结点挂了,那么选择另外一个可用结点,将副分片分配(allocate)上去,然后进行主从分片的复制。

如果某个shard的主分片所在结点挂了,副分片还在,那么将副分片升级为主分片,然后做主从分片复制。

如果某个shard的主副分片所在结点都挂了,则暂时无法恢复,等待持有相关数据的结点重新加入集群后,从该结点上恢复主分片,再选择另外的结点复制副分片。  

正常情况下,我们可以通过ES的health的API接口,查看整个集群的健康状态和整个集群数据的完整性:

Elasticsearch Recovery 详细介绍

状态及含义如下:

green: 所有的shard主副分片都是正常的;

yellow: 所有shard的主分片都完好,部分副分片没有或者不完整,数据完整性依然完好;

red: 某些shard的主副分片都没有了,对应的索引数据不完整。  

recovery过程要消耗额外的资源,CPU、内存、结点之间的网络带宽等等。 这些额外的资源消耗,有可能会导致集群的服务性能下降,或者一部分功能暂时不可用。了解一些recovery的过程和相关的配置参数,对于减小recovery带来的资源消耗,加快集群恢复过程都是很有帮助的。

减少集群Full Restart造成的数据来回拷贝

ES集群可能会有整体重启的情况,比如需要升级硬件、升级操作系统或者升级ES大版本。重启所有结点可能带来的一个问题: 某些结点可能先于其他结点加入集群, 先加入集群的结点可能已经可以选举好master,并立即启动了recovery的过程,由于这个时候整个集群数据还不完整,master会指示一些结点之间相互开始复制数据。 那些晚到的结点,一旦发现本地的数据已经被复制到其他结点,则直接删除掉本地“失效”的数据。 当整个集群恢复完毕后,数据分布不均衡,显然是不均衡的,master会触发rebalance过程,将数据在节点之间挪动。整个过程无谓消耗了大量的网络流量;合理设置recovery相关参数则可以防范这种问题的发生。

gateway.expected_nodes
gateway.expected_master_nodes
gateway.expected_data_nodes

以上三个参数是说集群里一旦有多少个节点就立即开始recovery过程。 不同之处在于,第一个参数指的是master或者data都算在内,而后面两个参数则分指master和data node。

在期待的节点数条件满足之前, recovery过程会等待gateway.recover_after_time (默认5分钟) 这么长时间,一旦等待超时,则会根据以下条件判断是否启动:

gateway.expected_nodes
gateway.expected_master_nodes
gateway.expected_data_nodes

举例来说,对于一个有10个data node的集群,如果有以下的设置:

gateway.expected_data_nodes: 10
gateway.recover_after_time: 5m
gateway.recover_after_data_nodes: 8

那么集群5分钟以内10个data node都加入了,或者5分钟以后8个以上的data node加入了,都会立即启动recovery过程。

减少主副本之间的数据复制

如果不是full restart,而是重启单个data node,仍然会造成数据在不同结点之间来回复制。为避免这个问题,可以在重启之前,先关闭集群的shard allocation:

Elasticsearch Recovery 详细介绍

然后在节点重启完成加入集群后,再重新打开:

Elasticsearch Recovery 详细介绍

这样在节点重启完成后,尽量多的从本地直接恢复数据。

但是在ES1.6版本之前,即使做了以上措施,仍然会发现有大量主副本之间的数据拷贝。从表面去看,这点很让人不能理解。

主副本数据完全一致,ES应该直接从副本本地恢复数据就好了,为什么要重新从主片再复制一遍呢? 原因在于recovery是简单对比主副本的segment file来判断哪些数据一致可以本地恢复,哪些不一致需要远端拷贝的。

而不同节点的segment merge是完全独立运行的,可能导致主副本merge的深度不完全一样,从而造成即使文档集完全一样,产生的segment file却不完全一样。

为了解决这个问题,ES1.6版本以后加入了synced flush的新特性。 对于5分钟没有更新过的shard,会自动synced flush一下,实质是为对应的shard加了一个synced flush ID。这样当重启节点的时候,先对比一下shard的synced flush ID,就可以知道两个shard是否完全相同,避免了不必要的segment file拷贝,极大加快了冷索引的恢复速度。

需要注意的是synced flush只对冷索引有效,对于热索引(5分钟内有更新的索引)没有作用。 如果重启的结点包含有热索引,那么还是免不了大量的文件拷贝

。因此在重启一个结点之前,最好按照以下步骤执行,recovery几乎可以瞬间完成:

  1. 暂停数据写入程序
  2. 关闭集群shard allocation
  3. 手动执行POST /_flush/synced
  4. 重启节点
  5. 重新开启集群shard allocation 
  6. 等待recovery完成,集群health status变成green
  7. 重新开启数据写入程序  

特大热索引为何恢复慢

对于冷索引,由于数据不再更新,利用synced flush特性,可以快速直接从本地恢复数据。 而对于热索引,特别是shard很大的热索引,;除了synced flush派不上用场需要大量跨节点拷贝segment file以外,translog recovery是导致慢的更重要的原因。

从主片恢复数据到副片需要经历3个阶段:

  1. 对主片上的segment file做一个快照,然后拷贝到复制片分配到的结点。数据拷贝期间,不会阻塞索引请求,新增索引操作记录到translog里。
  2. 对translog做一个快照,此快照包含第一阶段新增的索引请求,然后重放快照里的索引操作。此阶段仍然不阻塞索引请求,新增索引操作记录到translog里。
  3. 为了能达到主副片完全同步,阻塞掉新索引请求,然后重放阶段二新增的translog操作。  

可见,在recovery完成之前,translog是不能够被清除掉的(禁用掉正常运作期间后台的flush操作)。

如果shard比较大,第一阶段耗时很长,会导致此阶段产生的translog很大。重放translog比起简单的文件拷贝耗时要长得多,因此第二阶段的translog耗时也会显著增加。

等到第三阶段,需要重放的translog可能会比第二阶段还要多。 而第三阶段是会阻塞新索引写入的,在对写入实时性要求很高的场合,就会非常影响用户体验。

因此,要加快大的热索引恢复速度,最好的方式是遵从上一节提到的方法: 暂停新数据写入,手动sync flush,等待数据恢复完成后,重新开启数据写入,这样可以将数据延迟影响可以降到最低。

万一遇到Recovery慢,想知道进度怎么办呢? CAT Recovery API可以显示详细的recovery各个阶段的状态。 这个API怎么用就不在这里赘述了,参考:  CAT Recovery。

其他Recovery相关的专家级设置

还有其他一些专家级的设置(参见:   recovery)可以影响recovery的速度,但提升速度的代价是更多的资源消耗,因此在生产集群上调整这些参数需要结合实际情况谨慎调整,一旦影响应用要立即调整回来。

对于搜索并发量要求高,延迟要求低的场合,默认设置一般就不要去动了。

对于日志实时分析类对于搜索延迟要求不高,但对于数据写入延迟期望比较低的场合,可以适当调大indices.recovery.max_bytes_per_sec,提升recovery速度,减少数据写入被阻塞的时长。

最后要说的一点是ES的版本迭代很快,对于Recovery的机制也在不断的优化中。 其中有一些版本甚至引入了一些bug,比如在ES1.4.x有严重的translog recovery bug,导致大的索引trans log recovery几乎无法完成 。

因此实际使用中如果遇到问题,最好在Github的issue list里搜索一下,看是否使用的版本有其他人反映同样的问题。

以上就是Elasticsearch Recovery索引分片分配详解的详细内容!

Java/Android 相关文章推荐
新手入门Jvm-- JVM对象创建与内存分配机制
Jun 18 Java/Android
java中重写父类方法加不加@Override详解
Jun 21 Java/Android
分析JVM源码之Thread.interrupt系统级别线程打断
Jun 29 Java/Android
SpringBoot工程下使用OpenFeign的坑及解决
Jul 02 Java/Android
java基础——多线程
Jul 03 Java/Android
swagger如何返回map字段注释
Jul 03 Java/Android
解决Jenkins集成SonarQube遇到的报错问题
Jul 15 Java/Android
java设计模式--七大原则详解
Jul 21 Java/Android
java代码实现空间切割
Jan 18 Java/Android
Spring Security使用单点登录的权限功能
Apr 03 Java/Android
MyBatis配置文件解析与MyBatis实例演示
Apr 07 Java/Android
Java8利用Stream对列表进行去除重复的方法详解
Apr 14 Java/Android
Elasticsearch 配置详解
Apr 19 #Java/Android
引用计数法和root搜索算法以及JVM中判定对象需要回收的方法
解决springboot druid数据库连接失败后一直重连的方法
Apr 19 #Java/Android
Android自定义双向滑动控件
Apr 19 #Java/Android
java高级用法JNA强大的Memory和Pointer
Apr 19 #Java/Android
Java后端 Dubbo retries 超时重试机制的解决方案
Apr 14 #Java/Android
Java数组详细介绍及相关工具类
Apr 14 #Java/Android
You might like
PHP文章按日期(月日)SQL归档语句
2012/11/29 PHP
PHP cURL初始化和执行方法入门级代码
2015/05/28 PHP
php安全配置记录和常见错误梳理(总结)
2017/03/28 PHP
javascript 尚未实现错误解决办法
2008/11/27 Javascript
jquery ajax请求实例深入解析
2012/11/26 Javascript
关于JavaScript中string 的replace
2013/04/12 Javascript
关闭时刷新父窗口两种方法
2014/05/07 Javascript
jQuery 动态云标签插件
2014/11/11 Javascript
js实现刷新页面后回到记录时滚动条的位置【两种方案可选】
2016/12/12 Javascript
修改UA在PC中访问只能在微信中打开的链接方法
2017/11/27 Javascript
jQuery实现右侧抽屉式在线客服功能
2017/12/25 jQuery
Vue2.0中集成UEditor富文本编辑器的方法
2018/03/03 Javascript
JS中原始值和引用值的储存方式示例详解
2018/03/23 Javascript
jquery.onoff实现简单的开关按钮功能(推荐)
2018/05/24 jQuery
详解ES6中的三种异步解决方案
2018/06/28 Javascript
详解vue使用$http服务端收不到参数
2019/04/19 Javascript
微信小程序实现Session功能及无法获取session问题的解决方法
2019/05/07 Javascript
详解element-ui表格中勾选checkbox,高亮当前行
2019/09/02 Javascript
手把手15分钟搭一个企业级脚手架
2019/09/16 Javascript
VUE Elemen-ui之穿梭框使用方法详解
2021/01/19 Javascript
Python3中的2to3转换工具使用示例
2015/06/12 Python
Python批量更改文件名的实现方法
2017/10/29 Python
数据清洗--DataFrame中的空值处理方法
2018/07/03 Python
没编程基础可以学python吗
2020/06/17 Python
TensorFlow2.0使用keras训练模型的实现
2021/02/20 Python
利用CSS3伪元素实现逐渐发光的方格边框
2017/05/07 HTML / CSS
哥伦比亚最大的网上商店:Linio哥伦比亚
2016/09/25 全球购物
GUESS西班牙官方网上商城:美国服饰品牌
2017/03/15 全球购物
G-Form护具官方网站:美国运动保护装备
2019/09/04 全球购物
GWT的应用有哪两种部署模式
2012/12/21 面试题
手工社团活动方案
2014/02/17 职场文书
《第一朵杏花》教学反思
2014/04/16 职场文书
鲁滨孙漂流记读书笔记
2015/06/30 职场文书
2015年公司国庆放假通知
2015/07/30 职场文书
职场新人刚入职工作总结该怎么写?
2019/05/15 职场文书
springboot中rabbitmq实现消息可靠性机制详解
2021/09/25 Java/Android