为了解决分布式系统中存在的一致性问题,提出了一些经典的一致性协议和算法。html
其中著名的有:二阶段提交协议、三阶段提交协议和 Paxos 算法。 算法
2pc(Two-Phase Commit),即二阶段提交,是为了分布式系统架构下全部节点在进行事物处理过程当中可以保持原子性和一致性而设计的一种算法。数据库
二阶段提交协议也被认为是一种一致性协议,用来保证分布式系统数据的一致性。api
大部分的关系型数据库都是采用二阶段提交协议。服务器
核心是先尝试后提交的处理方式;网络
事务询问架构
协调者向全部参与者广播事务内容,询问是否能够执行事务提交操做,以后开始等待参与者的响应;框架
执行事务分布式
各参与者节点执行事务操做,并将 Undo 和 Redo 信息记入事务日志中;spa
各参与者向协调者反馈事务询问的响应
若是参与者成功执行事务操做,将反馈 Yes 给协调者,表示事务能够执行;若是没有成功执行,则反馈 No;
若是协调者收到的反馈都是 Yes,则执行事务提交:
发送提交请求
协调者向全部参与者节点发送 Commit 请求;
事务提交
参与者收到 Commit 请求后,执行事务提交操做,在完成提交后释放事务占用资源;
反馈事务提交
参与者完成事务提交后,向协调者发送 Ack 消息;
完成事务
协调者收到全部参与者 Ack 消息后,完成事务;
若是协调者收到一个 No,或等待超时后没法收到全部反馈,则执行中断事务:
发送回滚请求;
事务回滚;
参与者接收到 Rollback 请求后,利用阶段一中记录的 Undo 信息来执行事务回滚操做;
反馈事务回滚结果;
中断事务;
同步阻塞:二阶段提交的执行过程当中,各参与者都在等待其余参与者响应过程;
单点问题:协调者出问题,整个流程没法运转;若是阶段二出现问题,那被锁定的事务没法释放;
数据不一致:
太过保守:二阶段提交协议没有完善的容错机制,任意一个节点失败都会致使整个事务失败;
3pc(Three-Phase Commit),即三阶段提交,是二阶段提交的改进版;
将二阶段提交协议的”提交事务请求“过程一分为二,造成了 CanCommit、PreCommit 和 do Commit 三个阶段组成的事物处理协议。
协调者和参与者都引入超时机制;
相较于二阶段提交协议,三阶段提交协议最大的优势就是下降了参与者的阻塞范围;
在第二接单,若是参与者等待超时,则中断事务;
在第三阶段,若是协调者出现问题,参与者会收不到 do-commit 或者 rollback,等待超时后,仍是会继续 commit,至关于解决了阻塞问题,但没法避免数据不一致的问题;
Zookeeper 使用 Zookeeper Atomic Broadcast(ZAB,Zookeeper 原子消息广播协议)的协议做为其数据一致性的核心算法。
ZK 使用一个单一的主进程来保持集群中各副本之间数据的一致性;
将服务器数据的状态变动以事物 Proposal 的形式广播到全部的副本进程上去;
ZAB 协议包括两种基本模式:崩溃恢复 和 消息广播
Leader 服务器会为每一个事物请求生成对应的 Proposal 来进行广播,并在广播以前为 Proposal 分配一个全局单调递增的惟一 ID(即 ZXID);
Leader 服务器为每一个 Follower 服务器各自分配一个单独的队列,将要广播的 Proposal 依次放入队列中,并根据 FIFO 策略进行消息发送;
每一个 Follower 服务器在收到 Proposal 后,会先将其以事物日志的形式写入本地磁盘,写入成功后,给 Leader 返回 Ack;
当 Leader 收到超过半数 Follower 的 Ack 响应后,就会广播 Commit 消息给全部 Follower 服务器通知其开始事物提交;
存在问题:没法处理 Leader 服务器崩溃退出而带来的数据不一致问题,因此 ZAB 协议增长了 崩溃恢复 模式;
当服务框架在启动中或 Leader 服务器出现网络中断、崩溃、重启状况时,ZAB 协议就会进入恢复模式并选举新的 Leader;
选举 Leader
ZAB 协议要确保已经在 Leader 服务器提交的事物最终被全部服务器都提交;
ZAB 协议须要确保丢弃那些只在 Leader 服务器上被提出的事物;
完成 Leader 选举后
正常状况的数据同步
Leader 服务器首先确认本地事物日志中的全部 Proposal 是否都已经被集群中过半的机器提交,便是否已完成数据同步;
Leader 会为每个 Follower 服务器准备一个队列,并将没有被各 Follower 服务器同步的事物以 Proposal 消息的形式,广播给 Follower 服务器;
并在 Proposal 消息以后,紧跟发送 Commit 消息,以表示该事物已经提交;
等 Follower 服务器将全部还没有同步的事物 Proposal 都从 Leader 服务器同步过来并应用到本地数据库后,Leader 会将 Follower 加入真正可用的 Follower 列表中;
处理须要被丢弃的事物 Proposal
在 ZAB 协议的事物编号 ZXID 设计中,ZXID 是一个 64 位的数字,低 32 位是简单单调递增计数器,每个客户端请求 Leader 生成新事物 Proposal 对该计数器 +1;
高 32 位表示 Leader 周期 epoch 编号,每当选举产生一个新的 Leader 服务器,就会从这个 Leader 服务器上取出本地日志最大失误 Proposal 的 ZXID,并从 ZXID 中解析出对应的 epoch 值,并 +1,以后就以此编号做为新的 epoch,并将低 32 位,置 0 来开始新的 ZXID;
当过半机器与 Leader 完成状态同步后,ZAB 协议退出恢复模式;