physical clock

机器上的物理时钟,不同的机器在同一个时间点取到的physical clock不一样,之间会存在一定的误差,NTP可以用来控制这个误差,同一个机房内的机器之间的时钟误差可以控制在1us以内,
跨机房可以控制在几十ms。两个事件a和b,a在机器M1上physical clock为12点5分0秒6ms发生,b在机器M2上physical clock为12点5分0秒7ms发生,这并不代表a发生在b之前,因为两个机器上取到的physical clock和真实时间(这个时间就是国际标准时间UTC,可以通过原子钟,internet,卫星获得)之间都有误差。比如机器M1的physical clock比真实时间慢10ms,那么事件a实际上是在真实时间12点5分0秒16ms发生的,机器M2的physical clock比真实事件慢5ms,那么事件b的实际上是在真实时间12点5分0秒12ms发生的,显然,事件a发生在事件b之后。

Lamport's Logical Clock

单机系统容易给发生的所有事件定义一个全局顺序(total order),但是分布式系统没有全局时钟,很难给所有事件定义一个全局顺序。所以,Lamport定义了一种偏序关系,happens-before.记作 ->

a->b意味着所有的进程都agree事件a发生在事件b之前。

在三种情况下,可以很容易的得到这个关系:

  1. 如果事件a和事件b是同一个进程中的并且事件a发生在事件b前面,那么a->b

  2. 如果进程A发送一条消息m给进程B,a代表进程A发送消息m的事件,b代表进程B接收消息m的事件,那么a->b(由于消息的传递需要时间)
  3. ->满足传递性,如果a->b AND b->c => a->c

Lamport's Logical Clock算法如下:

  1. 每个机器本地维护一个logical clock LCi
  2. 每个机器本地每发生一个事件设置LCi = LCi + 1,并且把结果作为这个事件的logical clock。
  3. 当机器i给机器j发送消息m时,把LCi存在消息里。
  4. 当机器j收到消息m时候,LCj = max(LCj, m timestamp)+1,结果值作为收到消息m这个事件的时间戳。

这个算法能够保证a->b,那么a事件的logical clock比b事件的logical clock小。反过来,通过只比较两个事件的logical clock不能得到a和b的先后。

Vector Clock

每个机器维护一个向量VC,也就是Vector Clock,这个向量VC有如下属性:

  1. VCi[i] 是到目前为止机器i上发生的事件的个数

  2. VCi[k] 是机器i知道的机器k发生的事件的个数(即机器i对机器j的知识)

每个机器都有一个向量(Vector),每个向量中的元素都是一个logical clock,所以取名为Vector Clock。

通过如下算法更新Vector Clock

  1. 机器i本地发生一个事件时将VCi[i]加1
  2. 机器i给机器j发送消息m时,将整个VCi存在消息内
  3. 机器j收到消息m时,VCj[k]=max(VCj[k],VCi[k]),同时,VCj[j]+1

可以看出,Vector Clock是一种maintain因果关系(causality)的一种手段,Vector Clock在机器之间传递达到给对方传递自己已有的关于其他机器知识的目的。

Dynamo为什么需要Vector Clock(实际上是Version Clock)

Dynamo是一个分布式Key/Value存储系统,这个Value可以是一行,包含多个列, 为了容错,每个Key/Value保存多副本,通常在不同的机器上,一般是3,后面以3为例。对外是一个最终一致性系统,即客户端A写入一个值返回成功后,在一定的时间内另外一个客户端可能读不到最新的值。通常,成功写入两个副本成功即返回给客户端成功,同时请求会异步的同步到第三个副本。然而,高可用是Dynamo的主要设计目标之一,即使在出现网络分区或者机器宕机时依然可读可写。

假设Key K有三个副本k1,k2,k3分别在M1,M2,M3上。

正常情况

M1处理写请求,M1将请求发往M2,M3,只要有一个返回,即返回客户端成功。

网络分区

如果M1和M2/M3之间网络都不通,k1被更新(持续高可用,依然给客户端返回成功),随后,其他节点(集群中任意一个节点都可以接客户端请求,并且将请求路由到正确的节点上)路由了写请求给M2(假设其他节点和M1/M3之间网络不通),k2被更新。这时,k1和k2数据不一样,最后网络恢复,三个副本进行同步时,应该保留哪个版本?如果只保留k2,即采用last write win机制,那么同步后,第一个客户端会发现它写的数据丢了。

这个时候就需要Vector Clock,更确切的说是Version Clock。

为了处理这种场景,Dynamo使用Version Clock来捕获同一个Object的不同版本之间的causality。每个Object的每个版本会有一个相关联的Version Clock, 形如[(serverA,counter),(serverB,counter),...], 通过检查同一个Object不同版本的Version Clock,可以决定是否可以完全丢弃一个版本,仅保留另外一个版本,还是需要将两个版本进行merge。如果Object的版本A的VCA包含的每项(server, counter)在版本B的VCB中都有对应项,并且counter小于等于版本B中对应项的counter(记作VCB descends VCA),那么这个Object的版本A可以被丢弃,否则需要对两个版本进行merge。

回到刚才的例子,k1被更新,Version Clock(注:此处假设k1/k2/k3三个副本之前一模一样,那么就可以省略之前的Version Clock)为[(M1,1)],k2被更新,Version Clock为[(M2,1)],随后k1/k2网络通了,他们通过比较两个Version Clock发现两个Version Clock存在冲突,不是descends的关系,那么就两个版本都保留,当客户端来读Key K的时候,两个版本的数据和对应的VC都返回给客户端,由客户端进行冲突合并,客户端进行冲突合并后写入Key K的时候,带着合并后的VC[(M1, 1), [M2, 1]]发到M1/M2,覆盖服务器版本,冲突解决。

可以看出,Vector Clock最初是为了给分布式系统的事件定序发明的,本质上是一种捕获causality的手段,只是他们捕获的是事件的关系。而Version Clock是捕获同一个数据的不同版本之间的causality.

Riak这个系统也使用了Vector Clock来做冲突合并,对Vector Clock的用法可谓比较深入,具体可以看最后两篇参考资料。

参考资料

Dynamo

Scalable and Accurate Causality Tracking
for Eventually Consistent Stores

version-vectors-are-not-vector-clocks

Causality Is Expensive

Vector Clocks Revisited

vector-clocks-revisited-part-2-dotted-version-vectors

Vector Clock/Version Clock的更多相关文章

  1. Clock Skew , Clock Uncertainty和 Period

    本文将介绍FPGA中和时钟有关的相关概念,阅读本文前需要对时序收敛的基本概念和建立.保持关系有一定了解,这些内容可以在时序收敛:基本概念,建立时间和保持时间(setup time 和 hold tim ...

  2. Clock Pictures

    Clock Pictures 题目描述 You have two pictures of an unusual kind of clock. The clock has n hands, each h ...

  3. clock()、time()、clock_gettime()和gettimeofday()函数的用法和区别【转】

    转自:http://www.cnblogs.com/krythur/archive/2013/02/25/2932647.html 转自http://blog.sina.com.cn/s/blog_7 ...

  4. imx6 uboot lvds clock

    在uboot中添加logo,lvds接口的lcd显示不正常,出现波动.网上说是lvds时钟频率的问题. 使用示波器测量之后,发现频率是60M,而lcd最大频率才46.8M. 因此就需要更改uboot中 ...

  5. clock gating and PLL

    一个gating的clock是指:clock network除了包含inverter和buffer外,还有其他logic. PrimeTime会自动的对gating input进行setup和hold ...

  6. clock sense和analysis mode

    PrimeTime会自动track clock tree中的inverter和buffer,从而得到每个register的clock sense. 如果clock tree中,只有buffer和inv ...

  7. Cesium中Clock控件及时间序列瓦片动态加载

    前言 前面已经写了两篇博客介绍Cesium,一篇整体上简单介绍了Cesium如何上手,还有一篇介绍了如何将Cesium与分布式地理信息处理框架Geotrellis相结合.Cesium的强大之处也在于其 ...

  8. Linux时间子系统之(五):POSIX Clock

    专题文档汇总目录 Notes: 本章主要介绍了若干种类的静态时钟,这些时钟都可以通过k_clock表示,注册到posix_clocks中.这些都是静态时钟,可以分为三大类:各种REALTIME时钟.带 ...

  9. 【小玩意】time-passing-by clock

    就着youtube上的教程用html和js做了个小时钟. Code: clock.html //clock.html <!DOCTYPE html> <html> <he ...

随机推荐

  1. BZOJ 4726: [POI2017]Sabota? 树形dp

    4726: [POI2017]Sabota? 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=4726 Description 某个公司有n ...

  2. ecshop登陆后价格可见,会员注册登陆才能显示价格

    打开模版文件夹里面的goods.dwt 查找{$lang.shop_price}<font class="price" id="ECS_SHOPPRICE" ...

  3. 在matlab中配置vlfeat

    [转自]http://cnyubin.com/?p=85 在VLFeat官网上是这么介绍VLFeat的:VLFeat开源库实现了很多著名的机器视觉算法,如HOG, SIFT, MSER, k-mean ...

  4. JavaScript跨域方法

    一.什么是跨域 JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象.但在安全限制的同时也给注入iframe或是ajax应用上带来了不少麻烦.这里把涉及到跨域的一些问题简单地整理一下: ...

  5. phonegap3.0 simple

    environment: window8(64bit) First you go to the phonegap site and install it. note that installing y ...

  6. ORACLE 日期函数[转载]

    一. 常用日期数据格式 .Y或YY或YYY 年的最后一位,两位或三位 SQL> Select to_char(sysdate,'Y') from dual; TO_CHAR(SYSDATE,'Y ...

  7. C# 用代码创建 DataSet 和 DataTable 的列和记录

    System.Data.DataSet objSet = new DataSet(); System.Data.DataTable objTable = new DataTable("tes ...

  8. C# winForm 窗体闪烁问题

    在构造函数里加上以下代码: this.DoubleBuffered = true;//设置本窗体            SetStyle(ControlStyles.UserPaint, true); ...

  9. Spring3系列5-Bean的基本用法

    Spring3系列5-Bean的基本用法 本篇讲述了Bean的基本配置方法,以及Spring中怎样运用Bean. 主要内容如下: 一.      Spring中Bean的相互引用 二.      Sp ...

  10. [转]ios平台内存常见问题

    本文转自CocoaChina,说的满详细的: 链接地址:http://www.cocoachina.com/bbs/read.php?tid=94017&keyword=%C4%DA%B4%E ...