> For the complete documentation index, see [llms.txt](https://yangsx95.gitbook.io/notes/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://yangsx95.gitbook.io/notes/distributed/yi-zhi-xing/gong-shi-suan-fa/zab.md).

# ZAB

ZAB是Paxos的精简版，他称作 Zookeeper 原子广播协议。

* 原子：同时成功、同时失败
* 广播：分布式多节点广播，过半判定成功

最终一致性写入的流程如下：

![image-20220324164820373](https://2351062869-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F7b2CdwBN9liniVJpfEAc%2Fuploads%2Fgit-blob-1a8c0412a552e80f811306ebb9ffc313589b959c%2Fimage-20220324164820373.png?alt=media)

1. 客户端发送create命令到左侧Follower
2. 因为是写请求，将会将请求转发给Leader处理
3. Leader接收到create请求后，首先创建一个事务id：`Zxid`
4. Leader紧接着对集群中的所有Follower进行广播
   1. 在每个Follower与Leader连接在Leader内部都有一个相应的发送队列，所有对Follower的请求都会放入到这个队列中，用于保证命令的顺序的、异步的执行
   2. Leader会先向所有的Follower发送写磁盘日志的命令，而不是先向内存写入节点
   3. 如果Follower正常接受到Leader的命令并且处理正常，将会回复Leader一个ok响应
   4. Leader判断Follower的相应是由有过半，如果过半，就判定通过
   5. Leader紧接着推送所有Follower写请求（`create ooxx`），通过放入队列的方式，Follower会慢慢消费队列中的数据，所以称zk是最终一致性的
5. Leader下发完所有write命令之后，Leader返回ok给目标Follower，Follower再返回给Client

特点：

1. 不同于Paxos，Paxos的所有节点都可以写，而Zookeeper是主从模型，只有Leader可以进行写操作
2. 图中右侧Client可能得到过时的数据，这是因为右侧的Follower还未消费完队列中的指令；客户端可以通过增加指令`sync`获取实时的最新的数据

选举的条件和前提：

1. 每一台Server都有自己的myid，标识他在集群中的唯一编号
2. 拥有最全的数据的Server具有Leader选举权，如果Server的Zxid的值最大，说明他的数据最全
3. Zxid是已经通过投票过半的数据操作，是不可被怀疑的
4. 如果多个Server之间的数据相同，论资排辈，谁的myid大谁就有优先选举权

选举场景1，第一次启动集群：

![image-20220327111233077](https://2351062869-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F7b2CdwBN9liniVJpfEAc%2Fuploads%2Fgit-blob-48994a0b74141c5c65945a0f9bc591ea58d0946d%2Fimage-20220327111233077.png?alt=media)

1. 如果按照node01、node02、node04、node03的顺序启动集群
2. 当启动数量达到3台时，才会触发选举，两台不会触发
3. 因为是集群的第一次启动，所有Zxid都是初始值0
4. Zxid相同，所以会论资排辈，前三台启动的Server中，node04的myid最大，所以会选择node04作为集群中的Leader

![image-20220327112150820](https://2351062869-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F7b2CdwBN9liniVJpfEAc%2Fuploads%2Fgit-blob-947af9b34009c4aed62b1a2214829c422f307b46%2Fimage-20220327112150820.png?alt=media)

如果在运行中node04这个Leader挂掉：

![image-20220327113227461](https://2351062869-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F7b2CdwBN9liniVJpfEAc%2Fuploads%2Fgit-blob-c06bf1f44995c15f5e898cd83b4a77145e33517c%2Fimage-20220327113227461.png?alt=media)

1. 选举的流程全程都在3888端口进行
2. node04挂掉，node04将会与其他Server失去连接；node01、node02、node03任何一方都有可能先发现Leader宕机
3. 假设node03先发现Leader宕机，node03会首先推选自己作为Leader。他将自己的myid以及zxid发送给其他Server。
4. 其他Server收到node03的票后，先比较Zxid，发现Zxid比较小，将会直接淘汰node03的票，然后推选自己作为作为Leader，将自己的zxid以及myid发送给其他Server。
5. 假设node02先推选自己，node03接收后比较zxid比自己大，获取一票；node01接受到后比较zxid相同，然后比较myid，发现myid比较自己的大，node01也会推选node02，node02获取三票。
6. 此时node02的票数早已经过半，node02将会开启2888端口连接其他Server作为他的从节点。
