# 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作为他的从节点。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://yangsx95.gitbook.io/notes/distributed/yi-zhi-xing/gong-shi-suan-fa/zab.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
