在开始ZAB协议之前先跟兄弟们一起回顾一些知识点
协调者(Leader):主节点
参与者(Follower):从节点
2PC
,是Two-Phase Commit
的缩写,即二阶段提交
,是计算机网络尤其是在数据库领域内,为了使基于分布式
系统架构下的所有节点在进行事务处理
过程中能够保持原子性
和一致性
而设计的一种算法
。通常,二阶段提交协议
也被认为是一种一致性协议
,用来保证分布式系统
数据的一致性
。目前,绝大部分的关系型数据库
都是采用二阶段提交协议
来完成分布式事务
处理的,利用该协议能够非常方便地完成所有分布式事务参与者
的协调
,统一决定
事务的提交
或回滚
,从而能够有效地保证分布式数据一致性,因此二阶段提交协议被广泛地应用在许多分布式系统中。
一阶段:提交事务请求
1、事务询问
协调者
向所有
的参与者
发送事务内容,询问是否可以执行事务提交操作,并开始等待各参与者的响应
。2、执行事务
各
参与者
节点执行事务操作,并将Undo
和Redo
信息记入事务日志
中。3、参与者向协调者反馈
如果
各参与者成功执行了事务操作
,那么就反馈给协调者
Yes响应,表示事务可以执行;如果参与者没有成功执行事务
,那么就反馈给协调者No响应,表示事务不可以执行。
二阶段:执行事务提交
事务提交
协调者接收到所有参与者的ACK消息都是YES,执行事务提交
1、发送提交申请
协调者
给参与者
发出Commit
请求2、事务提交
参与者
收到Commit
请求后,执行事务提交,完成后释放整个事务执行期间占用的事务资源3、反馈结果
参与者
在完成事务提交后,给协调者
发送ACK
消息4、事务完成
协调者
接收到所有参与者
反馈的ACK
消息后,事务完成如图:
一阶段:
二阶段
事务中断
任何一个参与者反馈了NO,或者等待超时了导致协调者没有接收到所有参与者的反馈就会中断事务
1、发送回滚请求
协调者
向所有参与者
发送Rollback
请求2、事务回滚
参与者
接收到Rollback
请求后,会根据一阶段
中的Undo
日志进行事务回滚,3、事务回滚结果反馈
参与者
在完成回滚后,向协调者
发送ACK
消息4、中断事务
协调者
接收到所有参与者
反馈的ACK
消息后完成事务中断
如图:
一阶段
二阶段
Zookeeper 是通过 Zab 协议来保证分布式事务的最终一致性
ZAB又名原子广播协议(Zookeeper Atomic Broadcast ) 作用在
可用状态
,有Leader
时
原子
:要么成功,要么失败,没有中间状态(FIFO队列+类似2PC操作)
广播
:分布式多节点的,所以执行操作都是由Leader(协调者)
向所有Follower(参与者)
统一发送请求PS:
ZK的数据状态存储在内存
ZK是日志存储在磁盘
以
一主两从
环境下写操作
为例展开讨论
如图(由于要连很多线条,所以没有用类似上方两阶段提交中的上下结构布局):
第一步:在ZK客户端对任意一个
Follower
节点执行一个写操作create /rhys "aaa"
第二步:
Follower
节点将这笔写操作转发给Leader
节点第三步:
Leader
会创建一个事务ID(zxid),假设本次给出的事务ID为1
第四步:其实在
Leader
对于每个Follower
都维护着一个发送队列(FIFO队列)
,紧接着Leader
会给两台Follower
发起关于创建XXX节点这件事
的第一阶段
操作写日志
,那么这个写日志操作就会先入发送队列
。再顺序执行
队列中操作,当写日志操作执行成功后,Follower
会返回一个ok/yes
的状态,那对应的Leader
中也会生成一个ok/yes
的状态,由于我们是一主两从,那有了两台机返回了ok
状态,满足了过半通过
条件(3/2+1)
,这时Leader
会再次对两台Follower
发起第二阶段write
写内存操作,其实就是类似两阶段提交(2PC)
,只是这里的两阶段提交
和开始回顾的两阶段提交
不一样的地方时没有中断事务操作,因为这里的两阶段提交不需要接收到所有Follower(参与者)的ACK反馈,只需要超过一半的机器ACK就可以了
,依然是入发送队列
,然后从队列中顺序执行操作,操作完成同样的会返回一个ok/yes
状态,达到过半条件则Leader
会给Follower
返回一个over-ok
状态,再由Follower
传递给客户端兄弟这边有一点需要提一下,我们刚提到过半提交这个概念对吧,那另一台
Follower
机器没有返回ok
状态,对应的发送队列依旧会放入一个write
操作,只要最终那台没有返回ok
的Follower
机器能把队列中操作消费完,那这个节点的数据最终还是会跟其他两个节点保持一致的,这边就体现出了最终一致性
。
- 总结:回过头再看ZAB的
原子
没有中间状态其实就是依据FIFO队列+类似2PC操作
,广播其实就是体现了过半通过
的概念