分布式系统-共识协议

共识协议就是要让多个节点共同决定一个东西,这个东西可以是一个数字,可以是一个决定(yes or no),也可以是指令(字符串表示)。
在分布式系统中,把常见的错误模型分为两类,一类是非拜占庭错误,这个模型的意思是,节点可以不响应(意外关闭),但是不能发送错误(故意发送错误信息,诱导其他节点犯错),根据不响应之后的行为有分为两类,一是发生错误后永远不回来了,这个叫fail-stop,二是后面又恢复了,这个叫fail-recovery,默认我们使用fail-recovery模型。第二类是拜占庭错误模型,节点不仅可以不响应,也可以编造一些虚假信息来诱导其他节点作出错误决定。
分布式系统依赖网络环境,网络环境的错误是分布式系统中常见的错误,具体地,我们把网络环境的模型也抽象出三个错误类型。

  • 同步网络
    同步网络是指,网络的发送时间有上界。什么意思呢?是说发送一条消息,我们可以确定对方一定能收到,并且在一个固定的时间内。这个时间可以很长,一天,一年,甚至一亿年,这都没关系,但是它有个固定的上届。

  • 异步网络
    异步网络是指网络发送的时间没有上届。换句话说,我们不知道我们发送的消息,对方到底有没有收到。在这个模型下,只要有一个节点发生错误,不管是拜占庭还是非拜占庭错误,共识都无法达成。

  • 半同步网络
    这个是指网络的发送有时间上届,但是我们不知道这个上届是多少。也就是说我们不能在共识协议中使用超时机制。一般我们讨论的共识协议都是在同步或者半同步模型下。

什么正确的协议

有两个特性标准。
第一个是:

  • agreement
  • validity
  • termination
    第二个是:
  • correctness
  • liveness

其中,agreement and validity corresponds to the correctnesss and termination corresponds to the liveness property.

非拜占庭共识协议

非拜占庭的问题可以抽象(简化)为召集10(不包括你)个同学一起吃饭,你该如如何做?要保证的是:1.11个同学要么全到,要么全不到,不能有同学去了,有的同学没去;2.最终大家都要有个结论,不能一致再这晾着,不知道去还是不去好。

2pc

日常中,我们最常用的方式,先打电话给每一个人,问:“明天晚上6点吃饭,有空吗?”,当所有人都回答:“有空”之后,你再打电话给每个人:“确定了,明天6点吃饭,11个人都到”;当有人回答没空的时候,你也会给每个人打电话:“明天6点,某人没空,不聚啦,我改时间约你们”。
对应到协议里面,就是一个典型的2阶段协议,第一个阶段先提议,收集大家的意见,同时让大家先预定一下时间(锁住资源);第二阶段根据大家的反馈,来决定“聚”还是“不聚”。一旦协调者(你)做了这个决定,就是最终决定,需要同步给对方,就算对方一直不接你电话,你也要一直联系对方,告知决定。不然对方会一直锁住资源(预留明天6点时间)。所以2pc是一个阻塞协议,在协调者不告诉我最终决定时,我明天6点不能安排任何事情。这也是这个协议最大的问题,比如在第二阶段,协调者忙别的事情了,所有的10个同学都联系不到他,所有人都要等待。

3pc

2pc是在1970年提出的,为了克服上述的最大问题,在1980年代,有人提出了3pc协议。目的是想在第二阶段,协调者挂了之后,其他的参与者能够重新选择协调者,通过相互询问其他节点状态,来猜测原来协调者的决定。3pc将第二阶段(commit),分为了小阶段:pre-commit, commit。通过引入pre-commit,相当于在提案和提交之间增加一个状态:预提交。这个预提交是一个中间状态,处于这个状态之后,所有的正常迁移只能到提交状态,而在二阶段协议中,准备状态即可以到提交,也可以到取消状态,这是二阶段协议造成阻塞的根本原因,因为当所有参与节点处于这个准备状态后,如果协调者挂了,那么参与者是不知道走哪个分支迁移的,即时新选一个协调节点,获取了所有存活节点的状态,也不知道该走哪个分支。所以我们需要在二阶段协议中增加通讯,或者记录更多信息,帮助发生错误后,后续流程能够获得更多的信息用于猜测错误发生时的全局状态。三阶段协议中,预提交的状态表示,所有节点都同意提交交易啦,为了多保留一些线索,协调节点将这个结论通过pre-commit发送给所有的参与节点,参与节点收到消息后,将状态也更改为pre-commit,同时返回给协调节点ack消息。一旦处于pre-commit状态,正常的迁移只能到提交状态。
当协调者在pre-commit之后,commit之前挂掉之后,可以选择任意一个节点当新的协调者(简单办法是通过节点的编号选择最大或者最小)。新的协调者询问所有活着的其他节点的状态:

  • 有任何一个在提交,那么可以确定老的协调者一定是在预提交阶段了,所以最终决定也是提交,因为所有的阶段都准备好提交了;
  • 有任何一个在预提交状态,继续进行3pc流程。
  • 否则,取消这个交易。

唯一需要注意的一点是,当一个失败的节点恢复后,如果处于预提交阶段,它必须先询问其他节点状态,或者等新协调者发送指令,不能自己直接迁移到提交。因为:有可能在它是唯一一个收到pre-commit的节点,然后它和协调者都挂了,新选的协调者联系其他节点,发现没有任何一个节点有比预提交更高的状态,然后取消了交易。
目前还没有任何一个商业数据库和软件产品使用3pc,主要是因为它终结协议较为复杂,并且无法处理网络分区带来的问题。

paxos

raft

拜占庭共识协议

pbft

pow

pos

poa

おすすめ

転載: blog.csdn.net/wlstephenw/article/details/123065455