线性一致性(Linearizability)

线性一致性又被称为强一致性、严格一致性、原子一致性。是程序能实现的最高的一致性模型,也是分布式系统用户最期望的一致性。CAP 中的 C 一般就指它

顺序一致性中只要是大家认同的顺序就行,不需要与全局时钟一直。线性一致性则要求全满足。从这种偏序(partial order)要达到全序(total order)

  • 任何一次读都能读到某个数据的最近一次写的数据。
  • 系统中的所有进程(所有replicas),看到的操作顺序,都与全局时钟下的顺序一致。

所以线性一致性在顺序一致性的基础上增加了一个约束:

  • 单个节点的事件历史在全局历史上符合程序的先后顺序
  • 全局事件历史在各个节点上一致
  • 如果事件A的开始时间晚于事件B的结束时间,则在全局历史中,B在A之前

有了新增的这一个约束之后,我们就可以发现满足顺序一致性的下图,不满足线性一致性

因为根据线性一致性新增的约束,B1的开始时间晚于A1的结束时间,那么在全局历史中,A1要在B1之前。但是B1却没有读到A1的操作结果,这显然是相悖的。

同样的,A2要在B2之前,两者的结果是相悖的;C1要在B1之前,C1读到了A1的结果但B1却没有,这两个结果也是相悖的。

在时序图中,越往下代表时间越晚。通过时序图我们可以清楚地知道各个节点中事件在全局的先后顺序。

然而我们要明确,时序图实际是全局上帝视角。在计算机系统看来,每一个节点都只知道自身时间的先后顺序(例如A1在A2之前),但是却不知道节点间的先后顺序(例如A1到底是在B2之前还是B2之后)。

但是线性一致性要求节点间事件满足全局先后顺序的约束,这就要求分布式系统必须协调出一个全局同步的时钟。这一全局时钟不要求绝对精准,只要求能区分出事件的先后顺序即可。但即便如此,这也是一个成本很高的工作。因此,线性一致性新增加的约束是一个很强的约束

全局锁就是一个常用的全局同步时钟。全局锁将全局时间分割为锁存在前、锁存在期间、锁释放后三段。这三段的先后关系是绝对成立的。基于此,便可以实现事件先后顺序的区分。

如下图中,假设我们为B1事件增加全局的锁,则A1、A2、C1事件发生在锁存在前,一定在在B1事件之前;C2时间发生在锁释放后,一定在B1事件之后。这样,便确定了B1事件在全局中的位置为晚于A1、A2、C1,且早于C2。

线性一致性通过“事件A的开始时间晚于事件B的结束时间”这样的描述增加了对节点间先后事件的限制,但没有对并发事件进行限制。下图中,A1和C1是并发的。事件C1无论读出的是x=5还是x=0都不违反线性一致性约束,因为这两个事件是并发的。

可什么样的系统能做到线性一致性呢?

为了实现线性一致性,可以将数据的变更和同步看作一个整体,不能允许外界读取一个已经变更但尚未完全同步的数据。

最简单的,我们可以给每个操作都增加锁,从而使得全局串行化,保证系统满足线性一致性要求,如下图所示。

但全局串行化对系统并发性能的损耗太大,因此很少被实际使用。在具体实施过程中,存在许多效率更高的满足线性一致性的算法,两阶段提交算法、三阶段提交算法。

Posted in C#

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注