一、数据一致性
1、背景
随着业务的不断增大,单点系统不足以支撑业务的不断壮大,此时就引出了分布式服务,分布式服务就是把原本的单点系统进行拆分,拆分又分为水平拆分和垂直拆分,水平拆分按照分层模式来拆分,比如表示层和业务逻辑层进行拆分,分别部署到不同的机器上,每一层还可以进行集群搭建,垂直拆分就是把一个系统进行模块化拆分,比如电商系统中的用户模块、购物车模块、订单模块等,每个模块单独部署,所以通过服务拆分,集群部署等多种技术提高了原来系统的可用性。
在分布式环境中节点故障、网络的不可靠性等因素,给构建高性能、高可用的分布式系统带来了挑战。尤其是数据一致性,在集群服务中如果客户端对某个节点值进行了修改,此时因为一些原因导致进群中部分节点值没有同步修改,此时另一个客户端读取到了没有被同步修改的节点的值,这就导致数据的不一致性。
2、算法
为了解决一致性问题,出现了很多经典的算法(2PC,3PC,paxos算法等)
2PC:又称为二阶提交协议,准备阶段和提交阶段,其中涉及到参与者和协调者两个概念,准备阶段,协调者向所有参与者发送准备消息,参与者收到消息后执行本地事务(或直接返回失败),但不提交,然后向协调者返回成功或者失败,如果协调者收到了参与者的失败消息(或者超时),则给每个参与者发送回滚信息,否则提交,参与者根据协调者信息,执行提交或者回滚操作,释放资源。试想,如果协调者在向参与者发送提交信息的时候,此时部分机器收到了提交操作,其余的因为网络原因没有收到当前提交操作,那么此时集群中就会存在数据的不一致性。
3PC:又称为三阶提交协议,这是对2PC的一个改进,3PC中引入了超时机制,以及在准备阶段和提交阶段中插入了一个新的阶段。也就是can、pre、do。can阶段,和2PC类似,协调者向参与者发送提交请求,询问当前参与者是否可以执行提交操作。当参与者都返回成功,进入到pre阶段,否则协调者向参与者发送中断请求,pre阶段,协调者向参与者发送预提交请求,参与者接收到预提交请求后,执行本地事务,但不提交,反馈给协调者,协调者收到失败或者超时,向参与者发送中断请求,否则发送提交请求,进入do阶段。在do阶段中,参与者如果没有收到协调者的响应信息,那么会执行提交或者回滚操作,如果参与者收到了pre信息,表名当前所有节点已经可以提交,所以参与者在do阶段没有收到协调者的信息也可以相信当前是可以提交的。在do阶段,部分参与者如果不能接收到协调者中断响应,那么执行了提交操作,其它则执行了回滚操作,这样也会存在数据不一致问题。
Paxos:Paxos算法是就分布式系统中的某个值达成一致意见,Paxos算法中有三种角色,Proposer、Acceptor、Learners,Proposer发起提案、Acceptor负责对该提案进行表决(过半同意),当Acceptor同意了该提案,表示当前值被选定,Acceptor就会告诉Learners当前值被选定并保存当前值,Learners不做表决一般只保存表决结果,也就表明当前值是被系统选定认可的。就不进行算法的具体展开。
二、ZAB协议
ZAB全称Zookeeper Atomic Broadcast(ZooKeeper 原子广播),ZooKeeper通过ZAB协议来实现一致性,以及支持崩溃恢复和原子广播,ZooKeeper集群中有三种角色Leader、Follower、Observer,其中Follower和Observer又统称为Learner。
1、 Leader:集群中只有一个,负责处理写请求,Follower收到的写请求会转发给Leader,Leader再发起投票,过半同意、再通知Follower写入当前请求,当集群崩溃时,负责恢复数据,并同步数据到Follower,保持与Learner心跳检测;
2、 Follower:转发写请求给Leader,当Leader崩溃之后,重新投票选举Leader,处理读请求,保持与Leader心跳检测;
3、 Observer:不参与投票,转发写请求给Leader,同步来自Leader中的数据,目的是为了提高读性能;
客户端会随机向集群中的某个节点发起请求,读请求直接返回,写请求且当前节点不是Leader节点,则会向Leader节点提交事务,Leader收到后,会广播当前事务到Observer节点,只有超过半数的节点通过,则该写入才会成功。
ZooKeeper中只有一个Leader节点,当Leader节点崩溃之后,整个集群没法处理写请求,此时需要快速选举新的Leader节点,当新的Leader产生之后如何保证数据的一致性,这些都是需要ZAB协议的支持。
ZAB协议中有两种模式,奔溃恢复和原子广播。
奔溃恢复:也就是Leader选举,ZooKeeper采用FastLeaderElection算法进行快速的Leader选举过程,Leader选举,会保证选举产生的新Leader中的数据是最新数据。
原子广播:当Leader选举完成,所有Follower与Leader完成了状态同步,那么就进入了原子广播,当客户端发起写请求,Leader会生成一个事务提案,并发送给所有的Follower机器,Follower收到提案就会写入当前日志,但不提交并响应给Leader,Leader收到过半同意之后,发送commit命令,Follower收到之后提交当前的事务。
三、总结
本文只是简单介绍了ZAB协议,具体怎么实现以及具体实现逻辑我们将从源码的角度去做分析。
以上,有任何不对的地方,请留言指正,敬请谅解。