冲突的处理,也是分布式系统中一个重要的议题。今天我们继续以 Riak 为案例,看看 Riak 是怎么做冲突处理的。
Vector Clock(向量钟)
Riak 通过一种叫做 Vector Clock
的机制来处理冲突问题。简单来说,Vector Clock
是一段 token
,
像 Riak
这样的分布式系统通过这样的 token
来追踪数据更新操作的先后顺序。
在冲突处理中,能够知道冲突操作(eg. 创建操作,更改操作)的顺序,是非常重要的。
因为对于分布式系统来说,不同的客户端连接到的是不同的服务器节点,
当一个客户端更新了一个服务器节点上的数据,也许另一个客户端也同时更新了另一个服务器节点上的数据。
这时候,也许你会想到:记录每个操作的时间戳,然后依照时间戳靠后的操作来。然而要这么做的话,这里有个隐含的前提:
在这个分布式系统中的每个服务器节点,时钟都必须是完全同步的。
然而事实上,一方面这是非常困难的:需要非常大的财力物力的投入;另一方面,整个系统又是单点故障的。
所以,Riak 使用 Vector Clocks
来处理冲突。Vector Clocks
给每个写操作(创建,更改,删除) 打上一个标签,标签代表了是哪个客户端以什么样的顺序执行的操作。
这样一来,客户端或者开发者就能决定面对冲突,该怎么决定。
如果你熟悉像 Git
, Subversion
这样的版本控制系统,
这就和两个人同时修改了同一个文件产生的冲突解决思路是相似的。
Vector Clock
小故事 —— Vector Clock
相关理论
暴走大事件的编辑部每周都要整理下一期里要播报的新闻段子。
假设负责整理新闻段子有3个人:王尼玛(A), 张全蛋(B), 纸巾(C)。他们需要确定最终的新闻段子的列表。新闻段子的列表存储在分布式的服务器中。
每个人用自己的终端连接数据库。这些终端都有着唯一的标识,用来构建 vector clock。下面就让我们模拟一下,vector clock 是如何工作的。
首先,王尼玛用自己的终端更新了列表
vclock: A[0]
value: ['news xx']
然后,张全蛋先下载了这个列表,然后更新了这个列表
vclock: A[0], B[0]
value: ['news xx', 'news xyy']
张全蛋更新的同时(王尼玛做更新之后),纸巾同样的下载了已有的列表,做了更新。
vclock: A[0], C[0]
value: ['news xx', 'news yyz']
第二天,张全蛋复查列表,由于纸巾的更新操作并不是在他之后的(而是和他同时的),
这时候就产生了一个冲突,需要处理。
他拿到两个值:
vclock: A[0], B[0]
value: ['news xx', 'news xyy']
--
vclock: A[0], C[0]
value: ['news xx', 'news yyz']
他需要解决这个冲突:于是他选择合并这两个值:
vclock: A[0], C[0], B[1]
value: ['news xx', 'news xyy', 'news yyz']
这样一来,任何人之后获取到的就是这个最新的合并后的值了。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。