文章很长,建议收藏起来,慢慢读! 疯狂创客圈为小伙伴奉上如下珍贵的学习资源:html
高并发 必读 的精彩博文 | |
---|---|
nacos 实战(史上最全) | sentinel (史上最全+入门教程) |
Zookeeper 分布式锁 (图解+秒懂+史上最全) | Webflux(史上最全) |
SpringCloud gateway (史上最全) | TCP/IP(图解+秒懂+史上最全) |
10分钟看懂, Java NIO 底层原理 | Feign原理 (图解) |
更多精彩博文 ..... | 请参见【 疯狂创客圈 高并发 总目录 】 |
Paxos协议/算法是分布式系统中比较重要的协议,它有多重要呢?java
大牛说:程序员
Google Chubby的做者Mike Burrows说过这个世界上只有一种一致性算法,那就是Paxos,其它的算法都是残次品。面试
实际上:算法
理解了这两个分布式协议以后(Paxos/2PC),学习其余分布式协议会变得至关容易。sql
Paxos算法及变种算法在分布式系统中应用普遍。
基于Paxos算法的变种有:ZAB、Raft。编程
Zookeeper 中的ZAB协议也是Paxos算法的变种。Zookeeper经过ZAB协议实现数据一致性,以提供数据一致性。设计模式
在分布式系统中,节点之间主要使用消息投递方式来完成。但经过消息投递的方式会遇到不少意外的状况,例如网络问题、进程挂掉、机器挂掉、进程很慢没有响应、进程重启等状况,这就会形成消息重复、一段时间内部不可达等现象。而 Paxos 算法就是基于消息传递且具备高度容错特性的一致性算法。换句话说,Paxos算法的做用就是在可能发生这些异常状况的分布式系统中,快速且正确地在集群内部对某个数据的值达成一致。安全
在各种介绍 Paxos 算法的文章中,都会提到著名的“拜占庭将军问题”,以及偶尔也会提到的“两军问题”。关于这两个问题的详细介绍能够阅读这篇下面这篇文章,基本讲清楚了。服务器
简单的来讲,拜占庭将军问题描述了这样一个场景:
拜占庭帝国有许多支军队,不一样军队的将军之间必须制订一个统一的行动计划,从而作出进攻或者撤退的决定,同时,各个将军在地理上都是被分隔开来的,只能依靠军队的通信员来进行通信。然而,在全部的通信员中可能会存在叛徒,这些叛徒能够任意篡改消息,从而达到欺骗将军的目的。
这就是著名的“拜占廷将军问题”。从理论上来讲,在分布式计算领域,试图在异步系统和不可靠的通道上来达到一致性状态是不可能的。所以在对一致性的研究过程当中,每每假设信道是可靠的。事实上,大多数系统都是部署在同一个局域网中的,所以消息被篡改的状况很是罕见;另外一方面,因为硬件和网络缘由而形成的消息不完整问题,只需一套简单的校验算法便可避免——所以,在实际工程实践中,能够假设不存在拜占庭问题,即假设全部消息都是完整的,没有被篡改的。
拜占庭将军问题是由 Paxos 算法做者莱斯利·兰伯特提出的点对点通讯中的基本问题。该问题要说明的含义是,在不可靠信道上试图经过消息传递的方式达到一致性是不可能的。
因此,Paxos 算法的前提是不存在拜占庭将军问题,即信道是安全的、可靠的,集群节点间传递的消息是不会被篡改的。
Paxos 算法是分布式技术大师 Lamport 提出的。Lamport 为了讲述这个算法,假想了一个叫作 Paxos 的希腊城邦进行选举的情景。这个算法也是所以而得名。在他的假想中,这个城邦要采用民主提议和投票的方式选出一个最终的决议,但因为城的居民没有人原意把所有时间和精力放在这种事情上,因此他们只能不定时的来参加提议,不定时来了解提议、投票进展,不定时的表达本身的投票意见。 Paxos 算法的目标就是让他们按照少数服从多数的方式,最终达成一致意见。
规定一个提议包含两个字段:[n, v],其中 n 为序号(具备惟一性),v 为提议值。
下图演示了两个 Proposer(提案者) 和三个 Acceptor(附议者) 的系统中运行该算法的初始过程,每一个 Proposer 都会向全部 Acceptor 发送提议请求。
当 Acceptor 接收到一个提议请求,包含的提议为 [n1, v1],而且以前还未接收过提议请求,那么发送一个提议响应,设置当前接收到的提议为 [n1, v1],而且保证之后不会再接受序号小于 n1 的提议。
以下图,Acceptor X 在收到 [n=2, v=8] 的提议请求时,因为以前没有接收过提议,所以就发送一个 [no previous] (尚无提案)的提议响应,而且设置当前接收到的提议为 [n=2, v=8],而且保证之后不会再接受序号小于 2 的提议。其它的 Acceptor 相似。
若是 Acceptor 以前已经接收过提议 [n1, v1],如今接收到一个提议请求,提议为 [n2, v2]。
若是 n1 > n2,那么就丢弃该提议请求;
不然,发送提议响应,该提议响应包含以前已经接收过的提议 [n1, v1],设置当前接收到的提议为 [n2, v2],而且保证之后不会再接受序号小于 n2 的提议。
以下图:
Acceptor Z 收到 Proposer A 发来的 [n=2, v=8] 的提议请求,因为以前已经接收过 [n=4, v=5] 的提议,而且 2 < 4, 所以就抛弃该提议请求;
Acceptor X 收到 Proposer B 发来的 [n=4, v=5] 的提议请求,由于以前接收到的提议为 [n=2, v=8],而且 2 <= 4,所以就发送 [n=2, v=8] 的提议响应,设置当前接收到的提议为 [n=4, v=5],而且保证之后不会再接受序号小于 4 的提议。
Acceptor Y 相似。
当一个 Proposer 接收到超过一半 Acceptor 的提议响应时,就能够发送接受请求。
Proposer A 接收到两个提议响应以后,就发送 [n=2, v=8] 接受请求。该接受请求会被全部 Acceptor 丢弃,由于此时全部 Acceptor 都保证不接受序号小于 4 的提议。
Proposer B 事后也收到了两个提议响应,所以也开始发送接受请求。须要注意的是,接受请求的 v 须要取它收到的最大 v 值,也就是 8。所以它发送 [n=4, v=8] 的接受请求。
Acceptor 接收到接受请求时,若是序号大于等于该 Acceptor 承诺的最小序号,那么就发送通知给全部的 Learner(学习者)。当 Learner 发现有大多数的 Acceptor 接收了某个提议,那么该提议的提议值就被 Paxos 选择出来。
Paxos 算法的一致性主要体如今如下几点:
参考文献:
《从Paxos到ZooKeeper》