ZAB协议是Paxos一致性协议的一个精简版
有关于Paxos的文章可以参考 Zookeeper全解析—Paxos作为灵魂
在一切开始之前先要了解Zk通信模型
我在虚拟机上创建了四个节点,分别是
server.1=192.168.91.129:2888:3888
server.2=192.168.91.130:2888:3888
server.3=192.168.91.131:2888:3888
server.4=192.168.91.132:2888:3888
依次启动129 130 131 132,毫无疑问,最终Leader一定是131(选举过半通过)下面是每台机器的tcp连接情况
【129】
【130】
【131-Leader】
【132】
可以看到
- node1 监听3888端口,连接了leader节点的2888,被node2 node3 node4连接了自己的3888
- node2 监听3888端口,连接了leader节点的2888,连接了node1的3888被node3 node4连接了自己的3888
- node4 监听3888端口,连接了leader节点的2888,连接了node1,node2,node3的3888
- // leader节点 node3
监听3888和2888端口,连接了node1和node2的3888端口,被所有节点连接了自己的2888
ZAB(原子广播协议)
ZooKeeper 的几个特性
- 顺序一致性 - 客户端的更新将按照发送顺序应用
- 原子性 - 更新成功或者失败没有中间结果
- 统一视图 - 无论客户端连接到哪个服务器,客户端看到相同的服务视图
- 可靠性 - 一旦应用进行了更新,它将从那时起持续到客户端覆盖
- 及时性 - 系统的客户视图保证在特定时间范围内是最新的
Zookeeper实现可靠性用的是ZAB这种原子广播协议
场景描述 : 现在有一个Zk集群,集群中有三台机器,客户端对应Follower发起了一个写操作
ZAB实现过程
三台机器半数 = (3/2+1) = 2
- Follower把客户端写操作通知给Leader
- Leader接受到消息之后自己先投出一票,当前票数1
- Leader分别给两个Follower队列中发送写日志操作(第一阶段)
- 左侧Follower接受到写log操作后,把log信息(包含事务ID版本ID等)写在自己的本地,然后给Leader 返回
log-ok并投出自己的一票(当前票数2) - 此时右侧的Follower可能还没有接受到写日志的消息,他也没有投票,但是Leader接收到左侧log-ok并且票数等于2这个消息的时候,已经半数通过了决定可以写write,于是给每个Follower队列发送write命令(第二阶段)
- 左侧接收到Write之后开始写入,写完之后返给Leader Write-OK
- Leader接收到左侧的Write-ok后发送给左侧Follower Over-OK表示已经完成
- 左侧Follower接受到Leader发送来的 Over-Ok之后返回给客户端 Over-ok到此结束
右侧的Follower会依次执行队列中的消息,虽然他没有参与投票但是他最终会和Leader保持同步也就是最终一致性,客户端访问右侧Follower是有可能访问到不准确的数据的,可以选择sync获取,先去同步在拉取,当然这是一个可选项