在使用分布式数据库的时候,不一样节点中数据的一致性一贯是一个经典且难以解决的问题,而这个问题的根源是难以实现一个全局统一的时钟。下面就描述了这种问题的一种状况:mysql
如上图所示:A,B,C 表示分布式系统中的三个数据库,纵轴表示时间。在 TA1 时刻 A 作出了更改 Key=Value1 ,此次更改在 TC2 时刻传输到了 C;在 TB1 时刻 B 作出了更改 Key=Value2 ,此次更改在 TC1 时刻传输到了 C。那么问题来了:C 数据库中的 Key 应该等于 Value1 仍是 Value2 呢?算法
天然地,咱们能够想到: Key 的取值应该和最新的更改保持一致。可是,因为很难实现一个全部节点都一致的全局时钟,因此不一样节点各自的时钟实际上并不具备可比性,即 TA1 < TB1 也不能说明 B 对 Key 的更改是在 A 以后发生的。sql
接下来要介绍的向 量时钟算法
就可以部分解决上面的问题。数据库
在一个有 N 个节点的分布式数据库中,用一个 N 维的向量来表征时间,其中的某一个维表示一个节点的时间,这个时间向量按照如下规则进行处理:分布式
其中的偏序关系是指: 若A向量中的每一维都大于等于B向量,那么就说A,B向量之间存在偏序关系,不然不存在偏序关系 。ui
举个例子:spa
A,B,C 三个节点的初始时间向量都是 (0,0,0) ,该向量的一,二,三维分别对应 A,B,C 三个节点各自的时间。.net
虽然咱们已经学会了怎么使用时钟向量算法,可是彷佛还和算法的本质隔着一层雾:咱们其实并无解决“不一样节点之间统一的时钟”这一个客观的问题,可是经过向量时钟算法,咱们却能够肯定一些更改的前后顺序,而这些是在以前没法肯定。那多出来的信息是从哪里得到的?code
结合前面给出的两张图中的两个例子,对比传统的方法和时间向量算法的差别:blog
其实客观上是能够得知 B 对 Key 的更改是在 A 以后的,由于 B 是在收到 A 的更改以后才进行的下一步更改。传统的方法丢失了这部分信息,而向量时钟算法将这个信息保存了起来,用于后面对更改的前后顺序的断定。用数学表达就是:
由于 TB0 > TA1, TB1 > TB0,因此 TB1 > TA1;而传统的方法丢失了“TB1 > TB0”这条信息。
那么,既然向量时钟的惟一目的是传输“TB1 > TB0”这条信息,那么其余任何方法,只要可以将这类信息包含进去,也拥有和向量时钟算法相同的效果。好比 Git 中冲突合并的思想和向量时钟算法的本质实际上是同样的: Git 中不一样的本地仓库拥有不一样的时间维度,每一次 commit 对应一个时间维度上值的增长,能够快速合并的两个仓库对应的时间向量是具备偏序关系的。
总结以下:
因此向量时钟算法的实质是:
上面算法中的这种 A,B 之间不存在可以将某一个向量的尾端顺着同一个节点连到另外一个向量中间的事件 和 用一个多维的时间来代替一维的时间 的时空观,和狭义相对论中的时空观很是相似。
在狭义相对论中,同一事件从不一样的惯性参考系中观察是不同的,而两次事件能够创建因果关系的前提是:两个事件之间能够用等于或小于光速的速度传递信息(或者说一事件位于另外一事件的光锥内部)。
联系:
在狭义相对论中的描述 | 在向量时钟算法中的描述 |
不一样的惯性参考系有不一样的时间 | 不一样的节点有不一样的时钟向量维度 |
两件事件具备因果关系(事件 2 位于事件 1 的光锥内部) | 两次更改可肯定前后顺序(两个向量具备偏序,相似光锥内部) |
两件事件不具备因果关系(事件 2 位于事件 1 的光锥外部) | 两件事件不具备因果关系(事件 2 位于事件 1 的光锥外部) |
更详细的关于时钟向量算法和狭义相对论时空观的比较能够阅读参考文献 3。
区别:
狭义相对论能够用洛伦兹变换将不一样的参考系中的时间进行变换(利用到不一样参考系之间的相对速度),可是向量时钟算法不能够(其实逻辑上也能够,可是实现后没有现实意义),因此只能用多维的时间来表征不一样节点中的时间却无法相互转化。