ES recovery、主副分片复制会有一段时间block写入?

简介: ES在主副本分片复制时候不会block写入(version > 2.x)ES在recovery主分片时候会有一段时间block写入

背景:

ES recovery、主副分片复制会有一段时间block写入?

先说结论:

1.ES在主副本分片复制时候不会block写入(version > 2.x)

2.ES在recovery主分片时候会有一段时间block写入

主副分片同步(新增副本分片)(该部分来自于:参考2)

1.在ES 2.0 版本之前,副本recovery要经历三个阶段:需要block写一段时间(这也是最容易实现一致性的流程)(此时translog还是只有一个大文件)

流程:
phase1:主分片的lucene做快照,发送到target节点。期间不阻塞写操作,在此拷贝期间新增的数据会写到主分片的translog中。
phase2:将主分片translog做快照,发送到target节点进行重放,重放期间不会阻塞写操作。
phase3:为主分片加写锁,此时会block写入,将剩余的translog发送到target节点。由于此时数据量很小,写入过程的阻塞时间很短。

从phase1开始,就要阻止lucene执行commit操作,避免translog被刷盘后清除。
后续版本去掉了phase3的这个过程,也就意味着不再需要block写入;

2.ES2.x及之后版本
translog被重构,允许多个文件,在translog允许多文件的场景下,也就意味着允许recovery保留所需的文件,同时允许engine执行flush,以及执行lucene的commit(这将创建一个新的translog文件);
引入了translog.view概念,view是一个引用,包含了包括所有当前未提交的translog文件,以及所有未来新创建的translog文件,直到view关闭;因此可以通过该view做operations的遍历操作;
不再需要block写入的阶段,通过将拷贝期间的写入操作同时转发到正在建立的副本分片(多写)来避免copy translog过程中的实时写入数据不能被副本获取的情况,从而保证主副一致;

流程:
创建一个Translog.view,用来重放operations;
phase1:将主分片的lucene做快照,发送到target。期间允许索引操作和flush操作。发送完毕后,告知target启动engine,engine启动(副本的lucene)后,即phase1即将结束(phase2开始之前),新的索引操作都会转发副分片正常执行
phase2:将主分片的translog做快照,发送到target去重放;

完整性:
phase2对translog的快照包含了从phase1开始的新增操作。而phase1即将结束、phase2开始之前,副分片已经可以正常处理写操作,只要把phase2的translog重放(主要是为了恢复phase1中target的engine未启动之前主分片写入的数据),就可以保证副分片不丢数据;

image.png

一致性:
由于没有了阻塞写操作的第三阶段,接下来的问题就是解决phase1和phase2之间的写操作,与phase2重放操作之间的时序和冲突问题。在phase1执行完毕后,副分片已经可以正常处理写请求,副分片的新增写操作和 translog重放的写操作是并行执行的。如果translog重放慢,又把他写回老数据怎么办(translog的数据覆盖掉新写入/更新的数据)?
es现在的机制是在写操作(新增、更新、删除)中做异常处理。新增不存在冲突,只需要判断update、delete操作的版本号是否小于lucene中doc的版本号,大于才能操作;
注:Index,Delete,都继承自Operation,每个Operation都有一个版本号,这个版本号就是lucene中doc版本号;

ES在recovery

1.recovery副本分片
副本分片从node1,move到node2的流程:
1.master节点将该副本分片标记成relocating状态,此时从主分片开始拷贝lucene文件到node2(拷贝完成之后启动node2副本分片的lucene引擎),然后走主副本分片同步数据的逻辑(如上描述);
2.完成后该副本被标记为started,然后node1中的副本分片进行删除,完成此次recovery。
注:copy过程中写入是会写到3个分片上(主、副本、recovery后的副本),‘recovery后的副本’是在阶段2(阶段1的文件拷贝完成、lucene启动后)才接受写入。
recovery副本分片的场景:相当于直接增加一个副本分片,然后再下掉老的副本分片;

image.png

此过程不会block写入;

2.recovery主分片
primary分片从node0,move到node1的过程:
1.master节点下发状态,将该主分片标记relocating,更新routing_table和routing_nodes;
2.target分片会开始复制primary的lucene文件块;此时写入请求到达source节点时,会正常写入到source主分片中(不会同时写到target)。
注意:在分片的整个relocating过程中,对target节点的请求都会被转发到source节点,直到target节点应用了master下发的分片变为STARTED的集群状态
3.lucene文件拷贝完成后进入下一阶段。该阶段主要是target分片复制translog,并重放translog
该阶段收到的写入请求后复制给target节点(将target分片加入到 replication group)(即source分片写入、target分片也写入)。
4.tranlog复制并重放完成意味着数据已经对齐,进入下一阶段(handoff阻塞阶段)。该阶段是为了完成主分片状态的转移,该阶段对收到的写入请求放到队列(delayedOperations)中,写入流程结束,但是不会返回响应给client,待主分片状态转移完成后继续执行,最多阻塞30分钟。delayedOperations中的操作会在本阶段的阻塞过程结束后处理
注:该阶段时间很短,只是修改一个状态,使写入进入阻塞;
5.最后一个阶段是执行失败重试的逻辑,该阶段主要是target分片向master节点发送变更状态为started请求,并等待master下发状态变更;
上一步的阻塞阶段虽然时间很短,但是依然会有写入,delayedOperations中的数据在进入该阶段的时候处理;与该阶段的写入请求是统一的处理逻辑。
处理逻辑:
该阶段的写入请求和delayedOperations中的请求都会执行失败,抛出 ShardNotInPrimaryModeException异常,并捕获该异常,等待1分钟后重试写入,再次失败则退出;
如果1分钟内收到了新的集群状态,也会重试写入,然后写入成功。

补充解释:阻塞和失败重试阶段时间都比较短,但是完成了很多事情,阻塞阶段刚开始是primary分片开始阻塞写入,并告诉target分片可以开始变更分片状态了,此时的写入全部进入队列;
target分片响应了(primary分片接受响应)之后,开始进入“失败重试阶段”;
注:primary接受handoff响应做了什么事情?取消阻塞状态,将primary是主分片的标记清除(也就是说ES不再认为该分片是主分片)
primary开始向target发送recovery结束的消息,target分片接受到消息之后,认为自己可以成为主分片了,所以开始向master节点请求将分片标记为started状态;
master节点收到请求之后立刻下发状态变更命令,target分片状态变更完成之后,整个流程结束;
在此期间的写入请求会因为source(primary)分片已经不是主分片状态了,全部报错(但是不返回客户端),等待一分钟后重试;

图片来自参考1:
image.png

参考:
1.https://blog.51cto.com/u_15162069/2883927
2.https://www.easyice.cn/archives/231#i-2

相关文章
|
存储 缓存 算法
ES写入过程和写入原理调优及如何保证数据的写一致性(上)
ES写入过程和写入原理调优及如何保证数据的写一致性
ES写入过程和写入原理调优及如何保证数据的写一致性(上)
|
架构师 NoSQL Java
【案例实战】SpringBoot3.x自定义封装starter实战
【案例实战】SpringBoot3.x自定义封装starter实战
【案例实战】SpringBoot3.x自定义封装starter实战
|
NoSQL Redis
如何查看yum 安装的软件路径(不要再忘了)
如何查看yum 安装的软件路径 今天使用yum 安装了一个软件,后来没有找到路径 1、首先安装一个redis [root@iZbp1eem925ojwyx17ao9kZ ~]# yum install redis 2...
2684 0
|
监控 Java 索引
ES 生产中10个常见参数阈值(默认最大值)操作及优化解决方案
ES 生产中10个常见参数阈值(默认最大值)操作及优化解决方案
ES 生产中10个常见参数阈值(默认最大值)操作及优化解决方案
|
Java Spring
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
`@RequiredArgsConstructor(onConstructor = @__(@Autowired))` 是一个注解,通常用于在类中生成一个包含所有`final`和`@NonNull`注解的字段的构造函数,并且对这些字段进行自动注入(使用Spring框架的`@Autowired`注解)。让我们详细解释一下: 1. **`@RequiredArgsConstructor` 注解:** - **作用:** Lombok 提供的注解,用于自动生成类的构造函数。 - **生成的构造函数:** 生成一个包含所有`final`字段的构造函数,同时也包括被`@NonNull`注解
1794 1
|
5月前
|
机器学习/深度学习 人工智能 自然语言处理
多模态大模型:跨越感官边界的智能革命
多模态大模型能同时处理文本、图像、音频等信息,实现跨模态理解与生成。它如同“全科博士”,综合多源数据进行推理,在人机交互、内容创作等领域展现强大能力,推动AI迈向更通用的智能新纪元。
|
机器学习/深度学习 存储 人工智能
Qlib:华尔街颤抖!微软开源金融AI量化投资神器,助力智能投研
Qlib是微软亚洲研究院推出的开源AI量化投资平台,提供从数据处理、模型训练到组合管理的全流程支持,内置高性能数据基础设施和多种机器学习模型。
4808 87
Qlib:华尔街颤抖!微软开源金融AI量化投资神器,助力智能投研
|
监控 API 索引
Elasticsearch集群健康检查
【11月更文挑战第4天】
567 3
|
消息中间件 算法 调度
分布式系统学习10:分布式事务
本文是小卷关于分布式系统架构学习系列的第13篇,重点探讨了分布式事务的相关知识。随着业务增长,单体架构拆分为微服务后,传统的本地事务无法满足需求,因此需要引入分布式事务来保证数据一致性。文中详细介绍了分布式事务的必要性、实现方案及其优缺点,包括刚性事务(如2PC、3PC)和柔性事务(如TCC、Saga、本地消息表、MQ事务、最大努力通知)。同时,还介绍了Seata框架作为开源的分布式事务解决方案,提供了多种事务模式,简化了分布式事务的实现。
650 5
|
存储 监控 测试技术
Agent Workflow
【6月更文挑战第25天】
1198 3

热门文章

最新文章