算法简介
Paxos算法是莱斯利-兰伯特在1990年提出的一种基于消息传递的、具有容错性的一致性算法,Google Chubb(分布式锁服务)的作者Mike Burrwos说过,世上只有一种一致性算法,那就是Paxos算法,其他一致性算法都是Paxos的不完整版,Paxos算法是一种公认的晦涩难懂的算法,并且工程实现上也具有很大的难度,出名的实现比如Google Chubby/ZAB/微信的PhxPaxos等
Paxos算法要解决的问题就是在分布式系统中如何就某一个协议达成一致
拜占庭将军问题
这个问题是由Paxos的作者提出的点对点通信中的基本问题,该问题说的就是"在存在消息丢失的不可靠信道上试图通过信息传递的方式达到一致性是不可能的"
Paxos算法的前提就是不存在拜占庭将军问题,即信道是安全、可靠的,集群节点间传递的消息是不会被篡改的,在工程实践中,大多数系统都是部署在一个局域网内,因此被篡改的情况很少,另一方面,由于硬件和网络原因造成的消息不完整问题,现在已经不再是问题,只需要一套简单的校验算法即可,因此,在实现工程中各个服务间消息传递过程可以认为不存在拜占庭将军问题
一般情况下,分布式系统中各个节点间采用两种通讯模型:"共享内存","消息传递",而Paxos是基于消息传递通讯模型的
算法描述
三个角色
在Paxos算法中有三个角色,分别具有三种不同的行为,更多时候,一个进程可能同时充当着多种角色
-
Proposer:提案(Proposal)的提议者;
-
Acceptor:提案的(accept)表决者,即是否承认、接受该提案,超过半数接受,该提案被认定为"选定";
-
Learners:提案的学习者,当提案被选定后,其会同步并执行提案,说白一点,他就是那个没有接受提案,但提案最后通过被迫接受的那个;
一个提案的表决者会存在多个,但在一个集群中,提议者是可能存在多个的,不同的提议者给提出不同的提案,而一致性算法则可以保证以下几点
-
没有提案被提出则不会有提案被选定
-
每个提案者在提出提案时都会为该提案指定一个具有全局唯一性的、递增的提案编号N,在整个集群中时唯一的
-
每个表决者在表决某提案后,会将该提案的编号N记录在本地,这样每个表决者中保存的以及被表决的提案中会存在一个编号最大的提案,其编号架设为maxN,每个表决者仅会表决接受编号大于自己本地manN的提案
-
在众多提案中,最终只有一个提案被选定
-
一旦一个提案被选定,则其他服务器会主动同步该提案到本地
算法过程描述
Paxos算法的执行过程划分为两个阶段:"准备阶段","接受阶段"
一、准备(prepare)阶段
-
提议者准备提交一个编号为N的提案,其首先向所有的表决者发起 prepare(N)请求,用于试探集群是否支持该编号的提议
-
每个表决者Acceptor中都保存着自己曾经accept(表决,接受)过的提议中的最大编号manN,当一个表决者接收到其他主机发送来的prepare(N)请求时,其会比较N与manN的值,若N的值小于等于maxN,则说明该提议已经过时,当前表决者采用不回应或者回应Error的当时来决绝该preare请求,若N大于manN.则说明该提议是可以接受的,当前表决者会将其曾经接受的编号最大的提案Proposal(mid,manN,value)反馈给提议者,以向提议者展示自己支持的提案意愿,其中第一个参数mid表示该决策者Acceptor的标识id,第二个参数表示期曾接受提案的最大编号maxN,第三个参数表示该提案的真正内容value,当然,若当前表决者还未曾表决、接受过任何提议,则会将Proposal(mid,null,null)反馈给提议者
二、表决(accept)阶段
-
当提议者发出prepare(N)请求后,若收到超过半数的表决者的接受(Acceptor)的反馈,那么该提议者就会将其真正的提案Proposal(N,value)发送给所有的表决者
-
当表决者(accpetor)接受接受到提议者发送的Proposal(N,value)提案后,会再次拿出自己曾经接受(accept)过的提议的最大编号maxN,以及曾经反馈过的prepare的最大编号,让N与它们进行比较,若N大于这两个编号,则当前表决者接受(accept)这个提案,并反馈给提议者,若N不大于这两个编号,则表决者采取不回应或者回应Error的方式来拒绝该提议
-
后面会有一个列子,具体的阐述这种逻辑关系,但由于我没有笔记文档,都是照着视频中敲的,所有做的笔记比较慢;