CAP原理
- C
- 强一致性
- 最终一致性
- A
- P
一致性协议
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wK7lgsIF-1611971865554)(ZooKeeper+Dubbo.assets/1611483345460.png)]
2PC 二阶段提交
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-untLcCzZ-1611971865556)(ZooKeeper+Dubbo.assets/1611483357790.png)]
- 阶段一 提交事务请求,协调者向参与者发送预请求,自己也执行请求
- 参与者执行,然后告诉协调者是否可以执行这条请求
- 只是执行,没有提交
- 阶段二 事务提交
- 所有参与者向协调者发送ack
- 协调者向所有参与者发送commit请求
- 参与者收到commit之后,执行事务提交操作
- 完成之后,向协调者发送commit-ack
- 协调者收到所有参与者的ack后,完成事务commit,否则中断事务提交
- 中断事务
- 发送回滚请求
- 各个参与者节点回滚事务
- 反馈给协调者事务回滚结果
- 协调者接收各个参与点ack后回滚事务
- 问题
- 同步阻塞, 所有参与事务的节点处于同步阻塞状态,无法参与其他操作
- 单点问题,一旦协调者故障,则无法保证事务的一致性操作
- 数据不一致,脑裂现象,有一些参与者没有收到commit命令,就没有提交,出现不一致
三阶段 3PC
将2PC中的提交阶段分成了两部
形成了 CanCommit \ preCommit \ DoCommit 三个阶段
-
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Et4QiwHT-1611971865559)(ZooKeeper+Dubbo.assets/1611483980544.png)]
-
阶段一: CanCommit
- 事务询问,能否进行操作
- 响应ACK
-
阶段二: preCommit
根据阶段一的反馈结果分成两种情况
-
进行事务预提交
- 发送预提交preCommit请求,自身进入prepared阶段
- 参与节点收到preCommit之后,执行事务操作
- 参与者节点向协调者反馈事务执行结果
-
中断事务
-
CanCommit种任意一个参与者响应No或者协调者等待超时之后,就中断事务
中断事务也分两步
- 协调者向所有参与者发送abort
- 参与者收到abort,或者等待超时之后,中断事务
-
-
-
阶段三: DoCommit
也有两种情况
- 执行提交
- 协调者向所有参与者发送提交请求
- 各个参与点收到DoCommit请求之后,执行事务提交操作
- 提交完后向协调者发送ack
- 协调者收到所有参与者的ack之后,完成十五
- 中断
- 参与者收到abort,回滚
- 回滚成功,发送ack给协调者
- 协调者回滚,结束
- 执行提交
3PC 解决了 阻塞 和 单点问题,但是没有解决网络分区问题
阻塞问题:
引入超时时间机制,如果超时没有相应,协调者就会直接退出等待状态
单点问题:
2PC所有事务的一致性全都依赖协调者,3PC中,没收到commit的节点等待一段时间后也会自己提交
Paxos:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ECifhsxV-1611971865561)(ZooKeeper+Dubbo.assets/1611485676735.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-od8DwodM-1611971865563)(ZooKeeper+Dubbo.assets/1611485683458.png)]
- 分为两个阶段
- prepare阶段
- proposer提出一个提案,编号为N,发送给所有的acceptor
- 每个表决者保存自己的accept的最大提案编号maxN,当表决者收到prepareN请求时,比较N和maxN,若N小于maxN,则提案过时,拒绝prepare(N)请求。若N大于maxN,则接受提案,并且将这个表决这曾经接受的最大提案号Proposal(id, maxN, value)反馈给建议者,如果当前表决者还没有接受过任何建议,就返回proposal(myid, null, null)
- accept阶段
- proposal发出prepare(N),如果收到过半表决者的反馈,proposer发送提案内容proposal(N, value)给所有表决者
- 表决者接收后,accept提案,然后反馈,否则拒绝,拒绝的表决者称为learner
- 过半表决者反馈后,就重新进入prepare阶段,增加提案编号,重提prepare请求
- prepare阶段
- 活锁问题
- 全序问题
Raft
- candidate
- follower
- leader
可视化演示
http://thesecretlivesofdata.com/
-
所有节点一开始都是follower节点,有一个选举超时时间 150-200ms之间随机,最先超时的节点会先给自己投一票,然后请求其他节点给他的票
-
leader选举
- follower如果没有收到leader的心跳,超过一段时间后就自动变成candidate,然后向其他结点发送请求(candidate也有超时时间)
- 其他节点收到请求后,进行投票,follower收到过半投票就升级为leader
-
心跳时间
- 每个follower如果没有收到leader的心跳,超过一段时间后就自动变成candidate
-
日志复制
- 外部节点写leader,leader不会提交,而是向其他节点发送同步请求
- 其他节点同步数据后,返回确认
- 如果收到过半确认,leader提交(注意这里,它本身这一节点的ack并没有自己收到)
- leader通知其他节点提交
ZAB
基于fast paxos
zookeeper atomic broadcat
-
支持崩溃恢复的原子广播协议
- 发送给leader
- 对leader读请求,直接返回
- 写请求,发送给follower
- 发送给follower
- 读请求,直接返回
- 写请求,转发给leader
- 发送给leader
-
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uKpcggig-1611971865564)(ZooKeeper+Dubbo.assets/1611565284711.png)]
-
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HECQqiWG-1611971865566)(ZooKeeper+Dubbo.assets/1611565298374.png)]
-
zxid
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cWnC1f01-1611971865566)(ZooKeeper+Dubbo.assets/1611565536194.png)]
-
leader选举算法
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xk45LYUG-1611971865568)(ZooKeeper+Dubbo.assets/1611565746395.png)]
Paxos与Raft的演进
-
在保证数据安全的基础上,保持服务的持续可用,是核心业务对底层数据存储系统的基本要求。业界常见的1主N备的方案面临的问题是“最大可用(Maximum Availability)”和“最大保护(Maximum Protection)”模式间的艰难抉择:
-
AP
- “最大可用”模式,表示主机尽力将数据同步到备机之后才返回成功,如果备机宕机或网络中断那么主机则单独提供服务,这意味着主备都宕机情况下可能的数据丢失(MySQL的半同步模式);
-
CP
- “最大可用”模式,表示主机尽力将数据同步到备机之后才返回成功,如果备机宕机或网络中断那么主机则单独提供服务,这意味着主备都宕机情况下可能的数据丢失(MySQL的半同步模式);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7wputPML-1611971865569)(ZooKeeper+Dubbo.assets/1611565951283.png)]
Raft和Multi-Paxos的区别
Raft是基于对Multi-Paxos的两个限制形成的:
- 发送的请求的是连续的, 也就是说Raft的append 操作必须是连续的, 而Paxos可以并发 (这里并发只是append log的并发, 应用到状态机还是有序的)。
- Raft选主有限制,必须包含最新、最全日志的节点才能被选为leader. 而Multi-Paxos没有这个限制,日志不完备的节点也能成为leader。
Raft可以看成是简化版的Multi-Paxos。
Multi-Paxos允许并发的写log,当leader节点故障后,剩余节点有可能都有日志空洞。所以选出新leader后, 需要将新leader里没有的log补全,在依次应用到状态机里。