目的:
由于分布式系统中各个机器之间的系统时间同步差异,导致无法用物理时钟准确衡量事件的先后顺序。因此,提出了逻辑时钟这一概念,用来定义分布式系统中所有事件的发生顺序
背景
偏序与全序关系,这在大学的线性代数课程中有相关概念。简单的讲,对于一个数字集合,如果能够定义两两之间的先后关系,则该集合为全序关系。如果该集合中分为多个子集,子集内部两两有先后关系,而子集之间没有先后关系,则该集合为偏序关系。
逻辑时钟
如上图所示,根据逻辑时钟的原理,我们可以定义这些事件集的一个偏序关系。在这个偏序集中,存在因果关系的事件顺序是正确的。如果要得到所有事件的一个全序关系(逻辑时钟时间戳序号相等的事件间先后关系),我们可以自己定义一个规则,比如进程号小的排序在前,这样就可以得到全部事件的一个全序关系了。
注意:Lamport逻辑时钟只保证因果关系(偏序)的正确性,不保证绝对时序的正确性。
逻辑时钟解决资源竞争问题
前提:对于任意的两个进程Pi和Pj,它们之间传递的消息是按照发送顺序被接收到的, 并且所有的消息最终都会被接收到
具体实现流程不细讲,大概是每个进程在申请资源前都会通知所有进程,从而有一个全局顺序,按这个顺序去获取资源。2PC,Paxos等协议其实多多少少都是基于这种思想实现的。
向量时钟
逻辑时钟定义的是一个全序关系,没办法准确表示出并发关系(如C2和B4事件其实是并发的),有些场景下我们需要知道事件的并发关系。逻辑时钟之所以没办法表示出并发关系,是因为每个进程只拥有自己的本地时间,没有其他进程的时间。
假设有事件 a、b 分别在节点 P、Q 上发生,向量时钟分别为 Ta、Tb,如果 Tb[Q] > Ta[Q] 并且 Tb[P] >= Ta[P],则a发生于b之前,记作 a -> b,此时说明事件 a、b 有因果关系;
反之,如果 Tb[Q] > Ta[Q] 并且 Tb[P] < Ta[P],则认为a、b同时发生,记作 a <-> b。例如上图中节点 B 上的第 4 个事件 (A:2,B:4,C:1) 与节点 C 上的第 2 个事件 (B:3,C:2) 没有因果关系,属于同时发生事件。
简单地讲:B4事件发生时它看到它本身自己的逻辑时间戳是4,C的逻辑时间戳是1。C2事件发生时它看到自己的逻辑时间戳是2,而B的逻辑时间戳是3。则这两个就是并发关系了。
向量时钟做冲突检测
通过向量时钟可以知道两个写操作之间的并发关系,如果操作的是同一条数据,则证明发生了数据冲突
还需要物理时钟吗
- 逻辑时钟只能对一整个分布式系统内部的事件做排序,对于外部的一些事件所引发的先后顺序是无法感知的。
- 物理时钟的使用是更加简单的,如果能够控制分布式系统内部各个机器之间的系统时间误差,使用物理时钟也能够解决大部分问题
参考:
Lamport Logical Clock 学习
分布式系统:Lamport 逻辑时钟
分布式系统理论基础 - 时间、时钟和事件顺序
分布式系统:向量时钟