文章目录
1 写
1.1 写入请求直接发送到Leader节点
- Client 向Leader发送写入请求
- Leader 将数据读取到本地 ,然后发送到所有的Follower
- 当有一半的节点写入完毕(ACK) , 就返回写入成功的消息给Client
1.2 写入请求发送到Follower
- Client 向Follower发送写请求
- Follower将请求转发给Leader
- Leader将数据读取到本节点
…同上 - 当有半数的节点都写入完毕(包括Ledaer自己) , Leader写入完成信息--------> Follower ---------> Client
2 读
Client 向Zookeeper 发出读请求之后,无论请求的是Leader 还是 Follower , 都将会直接返回结果。
ZK并不保证读取的为最新数据
有可能读取到的是旧数据
当有三个Zookeeper节点,进行写入操作 , 如果有两个已经写入成功,Zookeeper就会认为本次写入请求成功。
假如此时读取的正好为 未写入完成的1 那么就会出现读到的未旧数据
Zookeeper官方解释
3 ZK一致性的保证
- 集群在半数以下节点宕机的情况下,能够正常对外提供服务
- Client写入请求全部交给Leader处理,Leader同步给Follower observer
- Leader 宕机或者整个集群重启,为了尽快恢复, Leader上已经提交的事务最终被集群都提交,只在Leader提交的事务舍弃
3.1 Zab一致性协议
Zookeeper Atomic Broadcast, ZK原子广播协议
Zookeeper 能够保证数据一致性主要依赖于ZAB协议的消息广播、崩溃恢复、数据同步三个过程
基于Zab协议实现了一种主备模式的系统架构来保持集群中各个副本之间的数据一致性
Client的请求都是写入到Leader进程当中,由Leader同步到其他节点。如果出现节点奔溃或者Leader进程崩溃, Zab协议用以下过程实现一致性
3.1.1 消息广播阶段
- 一个事务请求(Write)进来后,Leader会将写请求包装成Proposal 事务,并添加一个全局唯一的64位递增事务ID 也就是ZXID,消息的先后顺序也就是通过比较ZXID
- Leader节点会向集群中的其他节点广播Proposal事务
Leader节点和Follower节点都是解耦的,通信都会通过一个FIFO的消息队列,
Leader会为每一个Follower节点分配一个单独的FIFO队列,然后把Proposal发送到队列中 - Follower节点收到对应的Proposal之后会把它持久化到磁盘上,写入完成 返回ACK给Leader
- Leader节点收过超过半数的ACK后 (Quorum机制) ,提交本地机器上的事务,同时广播commit ,Follower收到commit止呕,完成各自事务的提交
ZAB协议针对事务请求的处理过程类似于一个两阶段提交过程
1.广播事务阶段
2.广播提交操作
这两阶段提交模型如下,无法因为Leader宕机带来数据不一致,比如
+ Leader发起一个事务 Proposal1 后就宕机,Follower都没有Proposal1
+ Leader 收到半数ACK 宕机,没来得及向Follower发送Commit
ZAB引入了崩溃恢复模式
3.1.2崩溃恢复阶段(选主 + 数据同步)
选主
Leader选举是ZK中最重要的技术,也是保证分布式数据一致性的关键
当集群出现
+ 服务器初始化启动
+ 服务器运行期间无法于Leader保持链接
就会出现选举机制,选举阶段 集群间互传的消息成为投票,Vote主要包换两个维度信息 : ID 、ZXID
+ ID:被推举的leader的服务器ID,集群中每个zk节点启动前就要配置好这个全局唯一的ID
+ ZXID : 被推举的leader的事务ID,该值是从机器DataTree内存中取的,即事务已经在机器中被Commit过了
1 选举过程如下
-
节点设置状态为Looking , 初始化 内部投票Vote(id,zxid)数据到内存,广播到其他节点。
节点每次投票都选举自己为Leader,将自身ID、处理最近一个事务请求的ZXID 广播出去,然后进入循环等待其他节点投票信息的流程当中。 -
循环等待过程中,节点每收到一个外部的Vote信息(A),都需要将其与自己内存Vote信息进行PK,ZXID大的胜,若ZXID相等,则ID大的投票。若外部投票(A)胜选,节点将 外部票覆盖自己的票发出(A),
统计是否由过半数的赞成者与新的票一致,没有就继续接受另一个外部票(B) 直到过半
出现过半 ,判断 Leader是否为赞成者选举结果出炉,Leader-------LEADING Folloewer ------- > following observer-------->observing
算法细节
FastLeaderElection.lookForLeader(),主要三个线程在工作
-
选举线程(主动调用LookForLeader方法的线程 ,通过阻塞队列senqueue及recvqueue与其他两个线程协作)
-
WorkerReceiver线程()
2 选举后的数据同步
选主算法中的zxid是从内存的数据库中取的最新事务id,事务操作是分两个阶段的 (提出阶段 、提交阶段) , Leader生成提议并广播给follower,收到半数以上的ACK后
3.1.3 数据同步
崩溃恢复完成选举以后,开始数据同步
Leader是ZXID最大的节点,同步就是利用Leader前一阶段获得的最新Proposal历史同步到所有节点
Paxos算法
背景
在常见的分布式系统中,总会发生 机器宕机 网络异常 等情况
Paxos算法需要解决的问题就是如何在一个科恩那个发生上述异常的分布式系统中,快速正确的在集群内部对某个数据值达成一致,并且保证不论发生任何异常,都不会破会啊整个系统的一致性。
Paxos算法是基于消息传递且具有高读容错特性的一致性算法,目前公认的解决分布式一致性问题最有效的算法
Paxos算法相关概念
在Paxos算法中,有三种角色
- Proposer 提案人
- Acceptor
- Learners
具体实现中,一个进程可能同时充当多种角色。比如一个进程可同时是Proposer、Acceptor、Learners
提案,最终达到一致value就在提案里
暂且认为 提案 = value , 提案只包含value。
暂且认为Proposer可以直接提出提案。
Proposer可以提出提案,
Acceptor可以接受提案
如果某个提案被选定,那么该提案里面的value就被选定了
对某个数据达成一致,指的是Proposer、Acceptor、Learner都被认为同一个value被选定(Chosen)。Proposer、 Acceptor、Learner分别在以下请跨管辖才能被认为某个value被选定
- Proposer:Proposer发出的提案被半数Acceptor接受
- 只要Acceptor接受,Acceptor提交的任务的value就被锁定了
- Learner : Acceptor告诉Leadrner哪个value被选定,Learner就认为value被选定。
Paxos问题描述
假设有一组可以提出(Propose)value (value在天Proposal里)的进程集合。一个一致性算法需要保证提出的这么多value中只有一个value被选中(chosen) ,所有进程都开始learn整个被选中的value,safaty 要求如下:
- 只有被提出的value才能被选中
- 只有一个value能被选中
- 进程认为某个value被选中,value需要真的被选中
Paxos算法推导
单Acceptor
可以多个Proposer , 只要Acceotor接受他收到的第一个提案,value就被锁定
假设Acceptor宕机,无法工作
多个Acceptors
上图存在的话 只能是所有Proposer提出的是同一个value
假如每个Proposer分别提出不同的value,发送给不同的Acceptor
算法演示
repare请求,Acceptor 没有过半 则error
相应过半 1.领ResN=N
收到半数的Pok,繁出Accept(N,V) 若相应中有天,则V=相应中最大的AcceptN对应的AcceptV;
未过半,重新获取N
Accept请求,同样需要过半
AOK过半,确定V被选中