Basic Paxos
优点:
- Paxos算法有严格的数学证明,系统设计精妙。
缺点:
一般不会直接用于实践:
- Basic Paxos 只能对单个值形成决议。
- 决议的形成至少需要2 轮 RPC 通讯(准备阶段prepare和批准阶段accept)往返消息多、耗性能、延迟大,高并发情况下将产生较大的网络开销。
- 如果多个提议者同时提交提案,就可能发生因为没有提议者接收大多数(超过半数)响应,而准备失败,需要重新协商。
- 极端情况 (两个提案节点交替使用更大的提案 ID ) 下甚至可能形成活锁。
Multi Paxos
优点:
- 引入领导者,领导者节点作为唯一提议者,这样就不存在多个提议者同时提交提案的情况,也就不存在提案冲突的情况了(解决base paxos这个问题)。领导者是通过执行 Basic Paxos 算法,进行投票选举产生的。
- 领导者在提交命令时,可以省掉准备阶段,直接进入到接受阶段(解决base paxos 两轮rpc问题)。领导者节点上,序列中的命令是最新的,不再需要通过准备请求来发现之前被大多数节点通过的提案,领导者可以独立指定提案中的值。
缺点:
- 省掉 Basic Paxos 的准备阶段,提升了数据的提交效率,但是所有写请求都在主节点处理,限制了集群处理写请求的并发能力,约等于单机。
- Multi-Paxos 是一种思想(raft zab都是其中一种),缺失实现算法的必须编程细节,这就导致,Multi-Paxos 的最终算法实现,是建立在一个未经证明的基础之上的,正确性是个问号。
- 兰伯特的 Multi-Paxos,虽然能保证达成共识后的值不再改变,但它不关心达成共识的值是什么,也无法保证各值(也就是操作)的顺序性。
ZAB
优点:
-
能保证操作顺序性的,基于主备模式的原子广播协议。 ZAB 是通过“一切以领导者为准”的强领导者模型和严格按照顺序处理(基于 事务标识符=任期+事务计数器 唯一单增性)、提交提案,来实现操作的顺序性的(解决multi paxos顺序问题)。
ZAB vs. Raft
ZAB算法划分阶段
raft算法划分阶段
| zab | raft | |
|---|---|---|
| 协商阶段 | zab的协商(广播阶段)分为两个阶段,移除了回滚操作的二阶段提交协议。proposecommit | raft以心跳机制 +日志连续的特性将协商优化成“一个阶段”。具体来说,从节点ack后,主节点会直接提交日志,然后回复客户端,不用立刻发起commit来让从节点也commit。那么从节点什么时候commit呢?在ld发起下一次协商或心跳的时候,携带commited index,这个时候从会把这个index之前的日志都提交了。 |
| 领导者选举 | ZAB 采用的“见贤思齐、相互推荐”的快速领导者选举(Fast Leader Election)。zab通过增加成员id来解决选举冲突的问题,也就是选举的时候,把成员id大小作为选举pk的条件。成员在一轮选举中可以投多票。 | Raft 采用的是“一张选票、先到先得”的自定义算法。引入随机超时时间,降低选举冲突的可能性。raft成员只会投出一票 |
| 日志复制 | 都是以领导者的日志为准来实现日志一致,而且日志必须是连续的,也必须按照顺序提交。 | |
| follower接受提案的条件 | zab的follewer只会被动的接收 | raft的follower会参与提案值的决策。日志匹配机制:raft的follower接受某个日志项条件一定是拥有上一个日志项,且该日志项和ld一样。 |
| 历史提案处理 | zab对于前任提出的不明确提交状态的日志都认为已提交,并将这些日志项复制到其他成员中。具体体现在,ld收集所有follewer日志项,然后广播,尝试协商达成共识。 | raft认为前任不明确提交状态的日志都是未提交的,需要等待当前ld提出新的日志项且达成共识后,才认为之前的日志项已提交。 |
| 读操作和一致性 | ZAB 的设计目标是操作的顺序性,在 ZooKeeper 中默认实现的是最终一致性,读操作可以在任何节点上执行; | Raft 的设计目标是强一致性(也就是线性一致性),所以 Raft 更灵活,Raft 系统既可以提供强一致性(读在主节点),也可以提供最终一致性。 |
| 写操作 | 写操作都必须在领导者节点上处理。 | |
| 成员变更 | ZAB 以动态配置(dynamic configuration)的方式实现的。那么当你在节点变更时,不需要重启机器,集群是一直运行的,服务也不会中断。join consensus,两个阶段。第一阶段后,需要同时获得旧和新两个配置多数派的支持。 | Raft的配置变更,一次只能操作一个节点的上线/下线。join consensus |
| 数据日志流向 | zab 协议在 discovery 阶段,一个 prospective leader 需要将自己的 log 更新为 quorum 里面最新的 log,也就是需要收集所有follower的数据,来生成initial history。然后才好在 synchronization 阶段将 quorum 里的其他机器的 log 都同步到一致。 | raft 协议数据只有单向地从 leader 到 follower,因为成为 leader 的条件之一就是拥有最新的 log。 |
| 其他 | ZAB 的成员发现,可以和领导者选举合到一起,类似 Raft,在领导者选举结束后,直接建立领导者关系,而不是再引入一个新的阶段;数据同步阶段,是一个冗余的设计,可以去除的,因为 ZAB 不是必须要先实现数据副本的一致性,才可以处理写请求,而且这个设计是没有额外的意义和价值的。 | Raft 的设计更为简洁,比如 Raft 没有引入类似 ZAB 的成员发现和数据同步阶段,而是当节点发起选举时,递增任期编号,在选举结束后,广播心跳,直接建立领导者关系,然后向各节点同步日志,来实现数据副本的一致性。 |