分布式协议与算法实战系列(Paxos系列)

1,347 阅读4分钟

前言

工作也数年了,每天都在接触分布式系统,分布式数据库,分布式消息中间件,分布式系统等等。
用过的中间件也算数不胜数,Es, Redis, Zookeeper,RocketMQ, kafka等等。 但是,扪心自问,自己对其原理可以说懂,但是真正研究源码到深入之处,我内心都会有个想法,究竟这些中间件的高可用是怎么做的,一个节点挂了,如何选举出另外一个节点呢?是基于什么方式呢? OK,可能通过八股,通过百科发现,Kafka是用了Zookeeper实现, RocketMQ是使用了Raft协议,Redis Cluster用了Gossip协议实现.....

重点来了,Zookeeper的Paxos,Raft, Gossip到底是什么意思呢。。 其工作的思想原理又是什么,分别适合解决什么场景。其实,实际以上都是分布式算法,这些分布式算法设计的目的就是去解决各种中间件在分布式场景下,碰到机器节点故障,需要故障转移等场景的时候,依照合理的规则去选举出合适的节点,保证集群的可用性。

常见的分布式算法

  • Paxos
  • Raft
  • Gossip协议
  • ZAB协议

Paxos算法

背景

先看一个假设,有一个分布式键值系统(假设类似Redis),有三个节点:A,B,C,现在有两个客户端,分别是1和2,俩客户端都要往键X写入值,假设客户端1要写入3,客户端2要写入7。那么如何保分布式集群系统三个的值都是正确且一致的呢? 从这个问题就开始引入到Paxos算法的学习。。

过程

先说下Paxos算法的三个核心参与者:

  • 提议者:发起提案的节点。比如是美国总统,他需要去发起提案,然后将该提案给到“议会”解决。
  • 接收者:接受提案的节点。比如是美国的议会,针对提案去进行选举,选举出合适的提案。
  • 学习者:被告知提案的节点。好比是美国的群众,议会已经讨论出结论,“请接受”。

总结:其实参与决策的就只有提议者和接收者,学习者只负责接受提案后的结果。

看完了三个核心的参与者,下面来说下Paxos算法是怎么利用提议者 AND 接收者来实现选举的全流程。

决策的过程主要分为两个阶段:选举 AND 决策

选举阶段:

提议者接收到请求后,提议者会向接收者发送提案,这个提案是带上了提案编号的:

image.png

上图的前置条件:
t1 早于t2

先看t1时刻
接收者A,接收者B,先收到了提议者1的提议编号1,因为接收者A,B 之前都没收到过提案编号,故返回暂无提案。
接收者C,先收到了提议者2的提议编号5,因为接收者C也没收到过提案编号,所以也返回暂无提案。

再看t2时刻:
接收者A,接收者B,后续收到了提议者2的提议编号5,因为A,B之前收到过的提案编号1小于5。所以返回暂无提案,并承诺之后不会响应提案编号小于等于5的提案编号
接收者C,后续收到了提议者1的提议编号1,因为接收者C目前最大的提案编号是5,所以,提议者1的提案不通过。

提交阶段

提议者1和2,往提交者提交自己的值。

image.png

提议者1,提交的值是[1,3], 提议者2,提交的值是[5,7]

提议者1向接收者A,B提交,因为接收者C已经被拒绝,但是A,B中因为已经又比1编号更高的提案5,所以该提议者1的提交会被直接拒绝。

提议者2向接收者A,B,C提交,因为A,B,C中都没存在比5编号更高的提案编号,所以该提案会被A,B,C都认可。

所以最后变量X的值就被设置成7

总结

1、Paxos算法是基于两阶段提交方式来提交的。两阶段提交达成共识的 常见方式,如果有达成共识的场景,也可以优先往这个方向演进。

2、除了共识,Paxos算法还实现了容错性,只要低于一半的节点故障,整个集群依旧可以保证可用性,而不像分布式事务一样,必须要所有节点一样才能允许操作。

3、一般来说,提案编号代表着优先级,接收者无论在准备阶段 OR 接受阶段,只会去处理比他编号更小的提案编号的请求。