Riak 是以 Erlang 编写的一个高度可扩展的分布式数据存储,Riak的实现是基于Amazon的Dynamo论文,Riak的设计目标之一就是高可用。Riak支持多节点构建的系统,每次读写请求不需要集群内所有节点参与也能胜任。像这样的系统,我们需要版本机制来确定哪个值是最新的。所以就引入了向量时钟(Vector Clock)

当存储一个对象到Riak时,都被打上向量时钟标签。通过向量空间祖先继承的关系比较,Riak可以自动的修复不同步的值,使数据保持最终一致性。

向量时钟的作用

有个比较经典的例子,说明向量时钟的作用。假设有如下场景:

Alice、Ben、Catby和Dave四人约定下周一起聚餐,四个人通过邮件商量聚餐的时间。
Alice首先建议周三聚餐。
之后Dave和Catby商量觉得周四更合适。
后来Dave又和Ben商量之后觉得周二也行。
最后Alice要汇总大家的意见,得到的反馈如下:
Cathy说,他和Dave商量的时间是周四
Ben说,他和Dave商量的时间是周三此时恰好联系不上Dave,而且不知道Cathy和Ben分别与Dave确定时间的先后顺序,Alice就不能确定到底该定在哪天了。

Vector Clock就是为了解决这种问题而设计的,简单来说,就是为每个商议结果加上一个时间戳,当结果改变时,更新时间戳。所以加上时间戳之后,我们再一次描述上面的场景,如下:

当Alice第一次提议将时间定为周三时,可以这样描述信息
date = Wednesday
vclock = Alice:1其他三个人都收到了信息,Dave和Ben开始交流,Ben建议改成周二,把Alice的初试向量加进去标识Ben看到Alice的消息了
date = Tuesday
vclock = Alice:1, Ben:1Dave回复Ben,确定周二可以
date = Tuesday
vclock = Alice:1, Ben:1, Dave:1然后Cathy开始说话,也和Dave说建议周四,此时在Dave看来就收到了两个数据如下:
date = Tuesday
vclock = Alice:1, Ben:1, Dave:1date = Thursday
vclock = Alice:1, Cathy:1
这两份数据,各自都不是互相的祖先,所以就产生了冲突,Dave要自动解决这个冲突,他选择了周四,然后将消息改成如下,继承来自Dave现在收到的两条消息,这个消息发回给Cathy
date = Thursday
vclock = Alice:1, Ben:1, Cathy:1, Dave:2最后来了,Alice只问Ben和Cathy最后的决定:
Ben说
date = Tuesday
vclock = Alice:1, Ben:1, Dave:1Cathy说
date = Thursday
vclock = Alice:1, Ben:1, Cathy:1, Dave:2Alice就明白了,因为第二个Cathy说的是完全继承于Ben说的,所以最后采纳Cathy说的决定,周四去。

以上这个决策用到了向量时钟,有个图还比较清晰了说明整个过程:

向量时钟的空间无限增长问题

以上的做法还比较完美的解决了问题,这里只列举了四个决策者的向量时钟,不过在现实生活中,如果有很多的决策者,相当于有很多的客户端,整个向量时钟的长度就无限制增长了,这对于存储系统来说,不是一个好消息。我们需要想办法解决。

一个直接的想法是,不要用client来标识向量空间,用server来标识向量空间,因为server的数量是可控的,这里用X,Y两台server来重现以上决策的过程,只是标签不再用客户端,而是用server标识,决策过程如下

此时Dave收到两个消息

Tue X:2,Y:1  with Ben

Thu X:1,Y1   from Cathy (这个消息比较新)

发现后者是前者的祖先,所以自然抛弃祖先,最终最新的,这样就悄无声息的把Cathy给他的消息给丢了。

所以尝试用server来做标识,以期减少向量时钟的空间是不可取的,因为会丢数据。实际情况还是需要用客户端的标识来做向量时钟。

向量时钟的剪枝

所以为了解决向量时钟空间的无限增长问题,引入了向量时钟的剪枝

Riak用四个参数来避免向量时钟空间的无限增长:

  • small_vclock
  • big_vclock
  • young_vclock
  • old_vclock

small_vclock和big_vclock参数标识向量时钟的长度,如果长度小于small_vclock就不会被剪枝掉,如果长度大于big_vclock就会被剪枝掉

young_vclock和old_vclock参数标识存储这个向量时钟时的时间戳,剪枝策略同理,大于old_vclock的才会被剪枝掉,剪枝策略如下图

这样只会丢掉一些向量时钟的信息,即数据更新过程的信息,但是不会丢掉实实在在的数据。只有当一种情况会有问题,就是一个客户端保持了一个很久之前的向量时钟,然后继承于这个向量时钟提交了一个数据,此时就会有冲突,因为服务器这边已经没有这个很久之前的向量时钟信息了,已经被剪枝掉了可能,所以客户端提交的此次数据,在服务端无法找到一个祖先,此时就会创建一个sibling。

所以这个剪枝的策略是一个权衡tradeoff,一方面是无限增长的向量时钟的空间,另一方面是偶尔的会有"false merge",对,但肯定的是,不会悄无声息的丢数据。综上,为了防止向量时钟空间的无限增长,剪枝还是比用server标识向量时钟工作的更好。

参考:

http://docs.basho.com/riak/latest/theory/concepts/Vector-Clocks/

http://basho.com/why-vector-clocks-are-easy/

http://basho.com/why-vector-clocks-are-hard/

《大型网站系统与Java中间件实践》

向量时钟Vector Clock in Riak相关推荐

  1. Dynamo分布式系统——「RWN」协议解决多备份数据如何读写来保证数据一致性,而「向量时钟」来保证当读取到多个备份数据的时候,如何判断哪些数据是最新的这种情况...

    转自:http://blog.jqian.net/post/dynamo.html Dynamo是Amazon开发的一款高可用的分布式KV系统,已经在Amazon商店的后端存储有很成熟的应用.它的特点 ...

  2. 分布式系统:向量时钟

    Lamport时钟存在的问题 使用Lamport时间戳,只是比较事件 a a a和 b b b各自的时钟值 C { a } C\{a\} C{a}和 C { b } C\{b\} C{b},无法说明它 ...

  3. NoSQL生态系统——一致性RWN协议,向量时钟,gossip协议监测故障

    13.5 一致性 在NoSQL中,通常有两个层次的一致性:第一种是强一致性,既集群中的所有机器状态同步保持一致.第二种是最终一致性,既可以允许短暂的数据不一致,但数据最终会保持一致.我们先来讲一下,在 ...

  4. Dynamo涉及的算法和协议——p2p架构,一致性hash容错+gossip协议获取集群状态+向量时钟同步数据...

    转自:http://www.letiantian.me/2014-06-16-dynamo-algorithm-protocol/ Dynamo是Amazon的一个分布式的键值系统,P2P架构,没有主 ...

  5. Vector Clock理解

    背景 近期在重读"Dynamo: Amazon's Highly Available Key-value Store"(经典好文,推荐!).文章4.4 中聊到了Data Versi ...

  6. 批处理编程的异类——时钟(Clock)

    批处理编程的异类--时钟(Clock) 1.暂停(Pause).延迟(Delay).等待(Wait).睡眠(Sleep) 1)for+set+if,时间精度为0.01秒,适用平台为WinNT/2K/X ...

  7. 【 Vivado 】时钟组(Clock Groups)

    Vivado会分析所有XDC约束时钟间的时序路径.通过set_clock_groups约束不同的时钟组(clock group),Vivado在时序分析时,当source clock和destinat ...

  8. 向量时钟算法简介——本质类似MVCC

    转自:http://blog.chinaunix.net/uid-27105712-id-5612512.html 一.使用背景 先说一下需要用到向量时钟的场景.我们在写数据时候,经常希望数据不要存储 ...

  9. Why Vector Clock are Easy or Hard?

    通过实际例子来阐述vector clock其实是容易理解的, easy 同样通过实际例子来描述在使用vector clock时会遇到哪些难以解决的问题, hard Why Vector Clocks ...

最新文章

  1. yii2 mysql gone away,yii2 console MySQL server
  2. [.net]webform 版本冲突
  3. Java SE 7 Update 25 –发行说明进行了解释。
  4. NDoc修改版,支持中文注释及中文界面。
  5. libsvm java 实例_LibSVM Java API调用示例程序
  6. 某少儿不宜网站图片拍摄位置分析,Python批量读取图片GPS位置!
  7. apache的tomcat负载均衡和集群配置
  8. 设计模式01-模板设计模式
  9. 64 位下,dsoframer.ocx 注册时失败,错误代码为 0x80070005
  10. 深度学习-各类数据集汇总
  11. PowerPoint储存此文件时发生错误 出现错误的问题解决方法
  12. 大学计算机第四讲答案,大学职业生涯规划课第四讲答案
  13. jquery获取第一个子元素
  14. 耳机驱动调试(插拔检测与按键检测)
  15. 什么是交叉检验(K-fold cross-validation)
  16. 您为什么要加入CSDN个人空间
  17. python云盘搭建教程_超简单!基于Python搭建个人“云盘”,目前最好用的个人云盘...
  18. 通过token窃取实现降权或者提权
  19. [软件需求]软件需求规格说明书样例
  20. 2020低压电工考试题库及低压电工复审模拟考试

热门文章

  1. Shell编程之条件语句(if语句,case分支语句)
  2. CAN波形解析实例(1)
  3. 组装电脑最容易犯的五大错误
  4. android 观察者更新ui,android通过观察者模式实现更新UI
  5. python自动化报表定时跑_POINTer分享:Python如何做报表自动化
  6. android intent 跳转卡顿_Intent七大属性
  7. python反转列表_Python实现list反转实例汇总
  8. spring下连接mysql_使用Spring连接mysql数据库
  9. 计算机网络及公文写作知识,计算机网络期末复习题
  10. (11) Hibernate 缓存机制