在分布式系统中,一致性(consensus,早期叫 agreement)问题是指对于系统中的多个服务节点,给定一系列操作,在一致性协议保障下,试图使得它们对处理结果达成一致。
如果系统能实现一致性,对外就可以呈现是一个功能正常的,但性能和稳定性都要好很多的“虚处理节点”。
需要注意,这个一致性并不代表正确与否,所有节点都达成失败状态也是一种一致性。
举个例子,某影视公司旗下有西单和中关村的两个电影院,都出售某电影票,票一共就一万张。那么,顾客到达某个电影院买票的时候,售票员该怎么决策是否该卖这张票,才能避免超售呢?当电影院个数更多的时候呢?
这个问题在人类世界中,看起来似乎没那么难,你看,英国人不是刚靠 投票 达成了“某种一致性”吗?
在实际的计算机系统(看似强大的计算机系统,很多地方都比人类世界要脆弱的多)中,存在如下的问题:
要解决这些挑战,愿意动脑筋的读者可能会很快想出一些不错的思路。
为了简化理解,仍然以两个电影院一起卖票的例子。可能有如下的解决思路:
这些思路大致都是可行的。实际上,这些方法背后的思想,将可能引发不一致的并行操作进行串行化,就是现在计算机系统里处理分布式一致性问题的基础思路和唯一秘诀。只是因为计算机系统比较傻,需要考虑得更全面一些;而人们又希望计算机系统能工作的更快更稳定,所以算法需要设计得再精巧一些。
规范的说,一个分布式的一致性算法应该满足:
第一点很容易理解,这是计算机系统可以被使用的前提。需要注意,在现实生活中这点并不是总能得到保障的,例如取款机有时候会是“服务中断”状态,电话有时候是“无法连通”的。
第二点看似容易,但是隐藏了一些东西。算法考虑的是任意的情形,凡事一旦推广到任意情形,就往往有一些惊人的结果。例如现在就剩一张票了,中关村和西单的电影院也分别刚确认过这张票的存在,然后两个电影院同时来了一个顾客要买票,从各自“观察”看来,自己的顾客都是第一个到的……怎么能达成结果的一致呢?记住我们的唯一秘诀,核心在于需要把这两件事情有能力进行排序,而且这个顺序还得是大家都认可的。
第三点看似绕口,但是其实比较容易理解,即达成的结果必须是节点执行操作的结果。仍以卖票为例,如果两个影院各自卖出去一千张,那么达成的一致就是还剩八千张,决不能是票售光了。
做过分布式系统的读者应该能意识到,绝对理想的一致性很难达成。除非不发生任何故障,所有节点之间的通信无需任何时间,这个时候其实就等价于一台机器了。实际上,越强的一致性要求往往意味着越弱的性能。
很多时候,人们发现对一致性可以适当放宽一些要求,在一定约束下实现一致性,从弱到强分别有如下几种:
莫非分布式领域也有一个测不准原理?这个世界为何会有这么多的约束呢?
搞学术的人都喜欢对问题先确定一个界限,那么,这个问题的最坏界限在哪里呢?很不幸,一般情况下,分布式系统的一致性问题无解。
当节点之间的通信网络自身不可靠情况下,很显然,无法确保实现一致性。但好在,一个设计得当的网络可以在大概率上实现可靠的通信。
然而,即便在网络通信可靠情况下,一个可扩展的分布式系统的一致性问题的下限是无解。
这个结论,被称为 FLP 不可能性 原理,可以看做分布式领域的“测不准原理”。