分布式一致性协议
- 二阶段提交协议(2pc)
- 三阶段提交协议(3pc)
- paxos
- zab
在分布式系统中,每个机器都可以确定自己进行的事务操作是否成功,但是无法直接了解其他机器的操作结果。因此,当一个分布式事务操作需要保持ACID 特性时,就需要一个“协调者”节点调度其他“参与者”节点来进行分布式事务操作。
二阶段提交(2pc)
提交事务请求 -> 执行事务提交;缺点:同步阻塞(参与者之间阻塞)、单点问题,脑裂(导致数据不一致问题);主要用于关系型数据库中,解决了分布式事务的原子性问题;
1. 提交事务请求
- 协调者向参与者发送事务,并询问是否可以执行事务提交操作,等待参与者响应;
- 参与者执行事务,将操作写入本地事务日志,向协调者发送反馈;
2. 执行事务提交
参与者反馈,全部ACK
- 协调者向参与者发送Commit;
- 参与者执行事务提交,释放事务资源,反馈ACK,;
- 协调者收到反馈完成事务
参与者反馈,存在NO;协调者等待超时
- 协调者向参与者发送RollBack;
- 参与者利用undo,进行事务回滚;
- 参与者事务回滚之后,向协调者发送ACK 反馈;
- 协调者接收到ACK,完成事务中断;
三阶段提交(3pc)
cancommit -> precommit -> docommit;优缺点:降低了参与者同步阻塞范围,但是又引入了数据不一致性问题(若出现网络分区)、单点问题依然存在;
1. CanCommit
- 协调者向参与者发送cancommit 请求(包含事务内容),等待参与者反馈;
- 参与者接收到cancommit 请求之后,反馈ACK或者NO;
2. PreCommit
参与者反馈,全部ACK
- 协调者向参与者发送precommit 请求,等待反馈;
- 参与者执行事务,将操作写入本地事务日志,向协调者发送反馈;
参与者反馈,存在NO;协调者等待超时
- 协调者向参与者发送abort 请求;
- 参与者无论是接收到abort 请求还是等待超时都会中断事务;
3. DoCommit
参与者反馈,全部ACK
- 协调者向参与者发送docommit 请求,等待反馈;
- 参与者执行事务提交,释放事务资源,反馈ACK,;
- 协调者接收反馈,完成事务提交;
参与者反馈,存在NO;协调者等待超时
- 协调者向参与者发送abort 请求;
- 参与者进行事务回滚;
- 参与者反馈ACK;
- 协调者接收到ACK,完成事务中断;
paxos 算法
- paxos 基于消息传递并具有高度容错性;
- paxos 算法的核心是,分布式系统如何就某个状态(提案)达成一致;
- paxos 算法假设不存在“拜占庭将军问题”;
- paxos 算法中的角色:proposer、acceptor、learner;
- proposer:发送提案;
- acceptor:裁决提案;只能批准一个提案;过半批准原则;
- learner:学习提案;
1. prepare 阶段(生成提案)
- proposer 提出编号为Mn 的提案,向acceptor 集合发送prepare 请求;
- acceptor 反馈;
- 保证不再接收编号小于Mn 的提案;
- 返回已经批准的,编号最大的提案的Value;
- 若Mn 小于已经批准的最大编号,则忽略Mn;(优化)
- proposer 收到过半响应,则发送accept 请求(Mn,Vn)给acceptor 集合;Vn 是接收回的最大编号提案的Value;若无Value 可选(acceptor 都未接收提案),Vn 可为任意值;
2. accept 阶段(批准提案)
acceptor 接收到accept 请求之后,只要Mn 不小于已接受提案最大的编号,则批准提案;
learner 获取提案(学习策略)
- 一旦提案被批准(过半),则发送给所有learner;
- 提案批准,则发送给一个learner,该learner再发送给其他learner;
- 提案批准,则发送给一个learner集合,该learner集合再发送给其他learner;
优化
问题:proposer1 与 proposer2 两者陷入死循环;
解决:选出主proposer,只要主proposer 和 过半acceptor 能保持正常,那么但凡主proposer 能提出一个编号更高的提案,这个提案最终将会批准;
应用
chubby:分布式锁、GFS 中 master 选举
ZAB 协议
ZAB 协议
ZAB 协议是为分布式协调服务(Zookeeper)专门设计的一种支持故障恢复的原子广播协议。
消息广播:
- 只允许有一个主进程(leader)接收事务请求并处理。
- 当leader 接收到请求之后,将事务请求转化为事务提议(proposal) 并将该proposal 分别入队 (leader 会为每个follower 分别创建一个响应队列用来保证事务提交的顺序)。
- 每个事务proposal 有一个递增的全局唯一的ID,事务ID(ZXID)
- leader 通过响应队列将proposal 分发到其他节点之后,等待反馈;follower 接收到proposal 之后写入本地日志,返回 ack;
- leader 收到一半以上follower 的反馈之后,会向其他节点 发送commit,同时提交事务。
故障恢复:
- 保证已经在leader 机器上提交的事务最终被所有机器提交
- 丢弃只在leader 机器上被提出的事务
为保证以上两点:
- Leader选举:选择ZXID 最大的节点作为Leader。
- 数据同步:leader 为每个follower 创建一个队列,将没有被各个follower 提交的事务 proposal填入各个队列,并分发给follower。follower 事务同步以后,leader会将它加入到真正可用follower 列表中。
ZAB协议中两种模式:
消息广播和故障恢复。
当系统启动或者leader 机器出现故障现象时,进入故障恢复模式并进行leader选举。选举产生的leader 会与过半的follower 进行数据同步。同步结束,退出故障恢复模式,进入消息广播模式;任意一台遵从ZAB协议的机器启动后,如果检测到leader 广播,都会自动进入故障恢复模式与leader 进行数据同步,同步之后,进入消息广播模式;非leader 接收到客户端事务请求时,会转发给leader 处理;
Leader 重新选举条件:
- leader 宕机或故障
- 与leader 保持连接的机器少于一半
Zookeeper
- zookeeper 为分布式应用提供了一个高效可靠的分布式协调服务;
- 实现依赖于ZAB 协议,实现了一种主备模式的架构来保持集群的数据一致性;
- zookeeper 可以帮助分布式应用以一个共享的树形的命名空间实现协调;
- zookeeper 将数据全部存储在内存中并且集群中任意一台机器都可以响应客户端读操作,因此它更适合用以读操作为主的场景;
- zookeeper 集群节点有三种角色:leader、follower、observer。
- leader:通过选举产生的集群领导者;提供读写服务;
- follower:提供读服务;参与leader 选举和写操作“过半写成功”策略;
- observer:提供读服务;不影响集群写性能的前提下提升集群的读性能;
- zookeeper 集群节点总数为奇数;
- zookeeper 数据节点类型:持久节点(只能采用删除操作清除该节点)、临时节点(其生命周期取决于session 是否失效)、顺序节点(子节点顺序表,节点名有数字后缀) ;
- zookeeper 每个节点都有 Stat 结构(数据节点的所有状态信息)
- 最重要的功能:watcher;
- 开源客户端:zkclient、curator;