赞
踩
客户端连接到任意服务端,发送事务请求,事务请求总会被转发到leader上,leader使用类似二阶段提交的步骤,先向follower发送事务请求,待接到过半follower的ack后,leader自身提交事务,再发送提交这个事务的请求,再次收到过半follower的ack后,完成这个事务的操作。
和二阶段提交的差别,是只需要过半数节点确认,就可进入下一个阶段,阻塞时间变短了;此外取消了follower返回否定回应,失败回滚的环节,leader可能和follower状态不一致,无法解决leader突然挂掉带来的数据不一致,所以需要崩溃恢复阶段来重新选主,解决数据不一致。
ZAB通过事务ID,区别不同的纪元,事务ID共64位,前32位在一个纪元中相同。
leader挂掉后,follower进入looking状态,开始选主,这个时候,各follower会发送包含自己最后一条事务id、纪元的消息用于选举投票,拥有最大纪元,和最大事务Id的follower成为准leader,它会:
1. 更新纪元epoch,分发更新纪元请求给其他follower
2. 获取其他节点的历史事务集合,从中将自己的事务更新为最新版本(ZAB协议原理是有这一步,但是因为准leader选举出来的节点,本身就有最大事务id和最大纪元,所以本身日志是最新的)
3. 将自身的所有事务和事务的状态同步给其他所有follower,并让follower提交掉
完成这两步之后,准leader称为leader,开始对外提供服务。
从选主策略中可以看出一个问题,如果leader挂掉的时候,正好发送过一条事务提交请求,并且只有少量follower回复ack了,这个时候选主,不是会选上从集群角度上讲拥有未提交事务记录的节点(节点本身看,事务为已提交),然后未提交的事务,还会同步给follower,摇身一变,称为已提交的了么?
是的,ZAB协议是这样,故障恢复的时候,ZAB协议会把未提交事务当作已提交的执行处理,没有收到事务的follower,在同步之后,会提交事务。
ZAB协议,只有当过半节点提交了事务,才会给客户端事务提交的回应,是一个类似二阶段提交的方式,重新选主后,特别有一个同步日志的阶段;而Raft协议,leader提交了事务,并且收到过半follower对准备完成事务的ack后,自身节点提交事务,至于过半数节点提交事务这件事,是在之后通信过程中渐渐完成的,重新选主后,没有单独日志同步的阶段。
这导致了一个问题,Raft中如果给客户端回应完,leader挂掉了,如何保证一致性。保证在集群中处理过的事务,不会被抹去?关于这点,Raft在选主阶段,提出了和ZAB类似的策略来解决:选择日志更多的服务器做leader,并给了更多选主的限制,以leader的日志为标准,同步日志。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。