Elasticsearch索引的分片分配Recovery使用讲解
作者:Zhangkai's 发布时间:2022-03-25 18:00:18
什么是recovery?
在elasticsearch中,recovery指的是一个索引的分片分配到另外一个节点的过程,一般在快照恢复、索引复制分片的变更、节点故障或重启时发生,由于master节点保存整个集群相关的状态信息,因此可以判断哪些分片需要再分配及分配到哪个节点,例如:
如果某个主分片在,而复制分片所在的节点挂掉了,那么master需要另行选择一个可用节点,将这个主分片的复制分片分配到可用节点上,然后进行主从分片的数据复制。
如果某个主分片所在的节点挂掉了,复制分片还在,那么master会主导将复制分片升级为主分片,然后再做主从分片数据复制。如果某个分片的主副分片都挂掉了,则暂时无法恢复,而是要等持有相关数据的节点重新加入集群后,master才能主持数据恢复相关操作。
但是,recovery过程要消耗额外的资源,CPU、内存、节点间的网络带宽等。可能导致集群的服务性能下降,甚至部分功能暂时无法使用,所以,有必要了解在recovery的过程和其相关的配置,来减少不必要的消耗和问题。
减少集群full restart造成的数据来回拷贝
有时候,可能会遇到es集群整体重启的情况,比如硬件升级、不可抗力的意外等,那么再次重启集群会带来一个问题:某些节点优先起来,并优先选举出了主节点,有了主节点,该主节点会立刻主持recovery的过程。
但此时,这个集群数据还不完整(还有其他的节点没有起来),例如A节点的主分片对应的复制分片所在的B节点还没起来,但主节点会将A节点的几个没有复制分片的主分片重新拷贝到可用的C节点上。而当B节点成功起来了,自检时发现在自己节点存储的A节点主分片对应的复制分片已经在C节点上出现了,就会直接删除自己节点中“失效”的数据(A节点的那几个复制分片),这种情况很可能频繁出现在有多个节点的集群中。
而当整个集群恢复后,其各个节点的数据分布,显然是不均衡的(先启动的节点把数据恢复了,后起来的节点内删除了无效的数据),这时,master就会触发Rebalance的过程,将数据在各个节点之间挪动,这个过程又消耗了大量的网络流量。所以,我们需要合理的设置recovery相关参数来优化recovery过程。
在集群启动过程中,一旦有了多少个节点成功启动,就执行recovery过程,这个命令将master节点(有master资格的节点)和data节点都算在内。
gateway.expected_nodes: 3
有几个master节点启动成功,就执行recovery的过程。
gateway.expected_master_nodes: 3
有几个data节点启动成功,就执行recovery的过程。
gateway.expected_data_nodes: 3
当集群在期待的节点数条件满足之前,recovery过程会等待gateway.recover_after_time指定的时间,一旦等待超时,则会根据以下条件判断是否执行recovery的过程:
gateway.recover_after_nodes: 3 # 3个节点(master和data节点都算)启动成功
gateway.recover_after_master_nodes: 3 # 3个有master资格的节点启动成功
gateway.recover_after_data_nodes: 3 # 3个有data资格的节点启动成功
上面三个配置满足一个就会执行recovery的过程。
如果有以下配置的集群:
gateway.expected_data_nodes: 10
gateway.recover_after_time: 5m
gateway.recover_after_data_nodes: 8
此时的集群在5分钟内,有10个data节点都加入集群,或者5分钟后有8个以上的data节点加入集群,都会启动recovery的过程。
减少主副本之间的数据复制
如果不是full restart,而是重启单个节点,也会造成不同节点之间来复制,为了避免这个问题,可以在重启之前,关闭集群的shard allocation。
PUT _cluster/settings
{
"transient": {
"cluster.routing.allocation.enable":"none"
}
}
当节点重启后,再重新打开:
PUT _cluster/settings
{
"transient": {
"cluster.routing.allocation.enable":"all"
}
}
这样,节点重启后,尽可能的从本节点直接恢复数据。但是在es1.6版本之前,既使做了以上措施,仍然会出现大量主副分片之间的数据拷贝,从面上看,这点让人很不理解,主副分片数据是完全一致的,在节点重启后,直接从本节点的副本重恢复数据就好了呀,为什么还要再从主分片再复制一遍呢?原因是在于recovery是简单的对比主副分片的segment file(分段文件)来判断哪些数据一致是可以本地恢复,哪些不一致的需要重新拷贝的。而不同节点的segment file是完全独立运行的,这可能导致主副本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过程瞬间完成:
暂停数据写入
关闭集群的shard allocation
手动执行 POST /_flush/synced
重启节点
重新开启集群的shard allocation
等待recovery完成,当集群的health status是green后
重新开启数据写入
特大热索引为何恢复慢
对于冷索引,由于数据不再更新(对于elasticsearch来说,5分钟,很久了),利用synced flush可以快速的从本地恢复数据,而对于热索引,特别是shard很大的热索引,除了synced flush派不上用场,从而需要大量跨节点拷贝segment file以外,translog recovery可能是导致慢的更重要的原因。
我们来研究下这个translog recovery是什么鬼!
当节点重启后,从主分片恢复数据到复制分片需要经历3个阶段:
第一阶段,对于主分片上的segment file做一个快照,然后拷贝到复制分片所在的节点,在数据拷贝期间,不会阻塞索引请求,新增的索引操作会记录到translog中(理解为于临时文件)。
第二阶段,对于translog做一个快照,此快照包含第一阶段新增的索引请求,然后重放快照里的索引操作,这个阶段仍然不会阻塞索引请求,新增索引操作记录到translog中。
第三阶段,为了能达到主副分片完全同步,阻塞新索引请求,然后重放上一阶段新增的translog操作。
由此可见,在recovery过程完成之前,translog是不能被清除掉的。如果shard比较大,第一阶段会耗时很长,会导致此阶段产生的translog很大,重放translog要比简单的文件拷贝耗时更长,因此第二阶段的translog耗时也显著的增加了。等到了第三阶段,需要重放的translog可能会比第二阶段更多。要命的是,第三阶段是会阻塞新索引(写入)请求的,在对写入实时性要求很高的场合,这就会导致性能下降,非常影响用户体验。因此,要加快特大热索引恢复速度,最好是参照上一节中的方式:
暂停数据写入。
手动synced flush。
等待数据恢复完成后。
重新恢复数据写入。
这样就会把数据延迟影响降到最低。
欢迎斧正,that's all see also:[本文主要参考:Elasticsearch Recovery详解]
(https://blog.csdn.net/u012450329/article/details/52881045) | [cat recovery]
(https://www.elastic.co/guide/en/elasticsearch/reference/current/cat-recovery.html) | [Indices Recovery]
(https://www.elastic.co/guide/en/elasticsearch/reference/current/recovery.html)
来源:https://www.cnblogs.com/Neeo/articles/10843759.html
猜你喜欢
- 本文实例讲述了彻底删除thinkphp3.1案例blog标签的方法。分享给大家供大家参考。具体方法如下:thinkphp3.1框架中的案例b
- 本文实例讲述了Python高阶函数、常用内置函数用法。分享给大家供大家参考,具体如下:高阶函数:允许将函数作为参数传入另一个函数;允许返回一
- NumPy是一个关于矩阵运算的库,熟悉Matlab的都应该清楚,这个库就是让python能够进行矩阵话的操作,而不用去写循环操作。下面对nu
- 一、random模块简介Python标准库中的random函数,可以生成随机浮点数、整数、字符串,甚至帮助你随机选择列表序列中的一个元素,打
- 已经下载了wampserver,以后有时间试下在本地运行ThinkPHP。在app/lib/Action/文件夹下可以为每一个模块定义控制器
- 多模块引用由此引发的相对路径混乱当不同层级的 Python 模块相互调用时,我们会发现原本在一个模块中写死的相对路径会导致找不到文件的报错。
- 你搜索这个,你会发现好多都是np.zeros(5,2),嗯都是复制的一个国外的帖子,然而没有翻译人家的话。然后你愤怒的关闭页面。这简直就是文
- Oracle存储过程基本语法 存储过程 1 CREATE OR REPLACE PROCEDURE 存储过程名 2 IS 3 BEGIN 4
- 刚才运行了一段代码,来查看Request.ServerVariables里面有多少值,看了一下,共50个!代码<%=Request.S
- 如何通过PHP实现Des加密算法代码实例注:php7以上不支持了,因为php7去掉了某些函数, 另外变量的{}要改为[]<?phpcl
- asp之家注:学习asp网页编程的朋友一定用过ACCESS数据库,access的简单方便,大大降低了asp初学者学习asp的门槛,对于学习a
- 一、背景介绍在 Python 项目开发过程中,根据不同的项目场景,需要切换不同的 Python 版本。因此,我们经常会对不同的项目,创建特定
- 客户用的数据库是mysql,而研发好的产品支持oracle,为了让客户掏腰包,我们必须把数据库环境从oracle转向mysql。我们在转换的
- 在实际的工作中会经常会用到to_char()、to_date()函数来对时间、日期进行处理。1、to_char()函数的用法1.1、将时间日
- 知识点requestsparselreos环境 python3.8pycharm2021目标网址:https://mm.enter
- 很早之前就在PJ的blog上看到可以用VS2005调试ASP程序,但是没有写出具体的步骤,后来一次偶尔也让我找到了方法,但是一直没把它写出来
- 背景测试工具箱写到一半,今天遇到了一个前后端数据交互的问题,就一起做一下整理。环境-----------------------------
- 用类和对象实现一个银行账户的资金交易管理, 包括存款、取款和打印交易详情, 交易详情中包含每次交易的时间、存款或者取款的金额、每次交易后的余
- 再看继承真正的大餐来之前,还是来点儿开胃菜!回顾一下关于类的继承的知识:我们先看上面的代码,这是一个简单的类继承,我们可以看到父类Base和
- 如何只取数据库的前3条记录?怎么控制只取得前3行数据 这要看是什么类型的数据库了,对于Access和SQ