一、共识算法 -- 拜占庭问题
两忠一叛问题:
如上图所示,将军A、B、C约定同时进攻或者撤退,假如将军C叛变了,被中间人截取消息并发送进攻给A、撤退给B,当所有将军消息都收到后结果如下:
A:2票进攻1票撤退;
B:2票撤退1票进攻;
导致最终A独自去攻打敌军,B撤退,最终会任务失败。
口信消息型拜占庭问题之解
如上图所示,经过2轮协商可以解决上述的两忠一叛问题;第一轮协商由leader发起,向其余3个将军发送进攻的指令消息,如果未收到消息则默认撤退指令;第二轮协商为3个将军之间的互通消息,假如将军C叛变为干扰信息向将军A、B发送撤退消息,则最终结果:
A:2进攻1撤退;
B:2进攻1撤退;
最终会执行进攻指令,这样解决了两忠一叛问题。
如果叛将人数为m,将军总人数不能少于3m + 1 。叛将数m决定递归循环的次数(将军们要进行多少轮作战信息协商),即m+1轮,n位将军,最多能容忍(n - 1) / 3位叛将。
Quorum选举算法
在N个副本中,一次更新成功的如果有W个,那么在读取数据时是要从大于N-W个副本中读取,这样就能至少读到一个更新的数据了。
如:维护了10个副本,一次成功更新了三个,那么至少需要读取八个副本的数据,可以保证读到最新的数据。
WARO算法(Write All Read one)
只有当所有的副本都更新成功之后,这次写操作才算成功,否则视为失败。WARO 优先保证读服务,因为所有的副本更新成功,才能视为更新成功,从而保证了所有的副本一致,这样的话,只需要读任何一个副本上的数据即可。写服务的可用性较低,因为只要有一个副本更新失败,此次写操作就视为失败了。假设有 N 个副本,N-1 个都宕机了,剩下的那个副本仍能提供读服务;但是只要有一个副本宕机了,写服务就不会成功。WARO 牺牲了更新服务的可用性,最大程度地增强了读服务的可用性,而 Quorum 就是在更新服务和读服务之间进行的一个折衷。
Quorum的应用
Quorum机制无法保证强一致性,也就是无法实现任何时刻任何用户或节点都可以读到最近一次成功提交的副本数据。
Quorum机制的使用需要配合一个获取最新成功提交的版本号的metadata服务,这样可以确定最新已经成功提交的版本号,然后从已经读到的数据中就可以确认最新写入的数据。
Quorum是分布式系统中常用的一种机制,用来保证数据冗余和最终一致性的投票算法,在Paxos、Raft和ZooKeeper的Zab等算法中,都可以看到Quorum机制的应用。
如上图所示,DATA-1有2个副本,DATA-2有3个副本,DATA-3 有1个副本,副本的数量即表示N;对DATA-2执行写操作时,完成了2个副本的更新(节点B、C),才完成写操作,即W此时为2;对DATA-2执行读操作,客户端读取DATA-2的数据时,需要读取2个副本中的数据,然后返回最新的那份数据,即读副本R为2。
无论客户端如何执行读操作,即使访问写操作未强制更新副本节点B,执行读操作时,因为要读2份数据副本,所以除了节点B上的DATA-2,还会读取节点C上的DATA-2,而节点C的DATA-2数据副本是强制更新成功的,这个时候返回给客户端肯定是最新的那份数据。
对于Quorum:
当W+R>N的时候,对于客户端来讲,整个系统能保证强一致性,一定能返回更新后的那份数据。