前言
假设一块磁盘每年损坏的概率是 5%,使用四块磁盘来保存同一份数据,就已经保证了这份数据在一年内有超过 99.9999% 的概率是安全可靠的。
对应到软件系统里,保障系统可靠性的方法,与拿几个磁盘备份并没有什么本质区别。单个节点的系统宕机导致无法访问数据的原因可能有很多,比如程序运行出错、硬件损坏、网络分区、电源故障,等等,一年中出现系统宕机的概率也许比 5% 还要大。这就决定了软件系统也必须有多台机器能够拥有一致的数据副本,才有可能对外提供可靠的服务。
但是,在软件系统里,要保障系统的可用性,面临的困难与磁盘备份却又有着本质的区别。因为磁盘之间是孤立的不需要互相通讯,备份数据是静态的,初始化后状态就不会发生改变。但是,到了分布式系统里面,我们就必须考虑动态的数据如何在不可靠的网络通讯条件下,依然能在各个节点之间正确复制的问题。
最容易想到的答案是“数据同步”:每当数据有变化,就把变化情况在各个节点间的复制看成是一种事务性的操作,只有系统里的每一台机器都反馈成功地完成磁盘写入后,数据的变化才能宣布成功。
之前介绍过的2PC、3PC就可以实现这种同步操作。同步的一种真实应用场景是,数据库的主从全同步复制(Fully Synchronous Replication)。比如,MySQL Cluster 进行全同步复制时,所有 Slave 节点的 Binlog 都完成写入后,Master 的事务才会进行提交。
不过,这里有一个显而易见的缺陷,尽管可以确保 Master 和 Slave 中的数据是绝对一致的,但任何一个 Slave 节点、因为任何原因未响应都会阻塞整个事务。也就是说,每增加一个 Slave 节点,整个系统的可用性风险都会增加一分。
以同步为代表的数据复制方法,叫做状态转移(State Transfer)。这类方法属于比较符合人类思维的可靠性保障手段,但通常要以牺牲可用性为代价。
如果你有一份会随时变动的数据,要确保它正确地存储于网络中的几台不同机器之上,并且要尽可能保证数据是随时可用的,你会怎么做?
状态机复制
系统高可用和高可靠之间的矛盾,是由于增加机器数量反而降低了可用性带来的。为缓解这个矛盾,在分布式系统里主流的数据复制方法,是以操作转移(Operation Transfer)为基础的。我们想要改变数据的状态,除了直接将目标状态赋予它之外,还有另一种常用的方法,就是通过某种操作,把源状态转换为目标状态。
能够使用确定的操作,促使状态间产生确定的转移结果的计算模型,在计算机科学中被称为状态机(State Machine)。
状态机有一个特性:任何初始状态一样的状态机,如果执行的命令序列一样,那么最终达到的状态也一样。在这里我们可以这么理解这个特性,要让多台机器的最终状态一致,只要确保它们的初始状态和接收到的操作指令都是完全一致的就可以。
广播指令与指令执行期间,允许系统内部状态存在不一致的情况,也就是不要求所有节点的每一条指令都是同时开始、同步完成的,只要求在此期间的内部状态不能被外部观察到,且当操作指令序列执行完成的时候,所有节点的最终的状态是一致的。这种模型,就是状态机复制(State Machine Replication)。
我们需要设计出一种算法,能够让分布式系统内部可以暂时容忍存在不同的状态,但最终能够保证大多数节点的状态能够达成一致;同时,能够让分布式系统在外部看来,始终表现出整体一致的结果。
这个让系统各节点不受局部的网络分区、机器崩溃、执行性能或者其他因素影响,能最终表现出整体一致的过程,就是各个节点的协商共识(Consensus)。
这里需要注意的是,共识(Consensus)与一致性(Consistency)是有区别的:一致性指的是数据不同副本之间的差异,而共识是指达成一致性的方法与过程。
分布式共识算法(Distributed Consensus Algorithm)
Paxos 算法
Paxos 算法,是由Leslie Lamport提出的一种基于消息传递的协商共识算法。现在,Paxos 算法已经成了分布式系统最重要的理论基础。
(待补充)
附
此文章为2月Day17学习笔记,内容来源于极客时间《周志明的软件架构课》