Spockwang's Blog

Paper Review: Don’t Settle for Eventual: Scalable Causal Consistency for Wide-Area Storage With COPS

| 评论

这篇论文描述了如何设计保证因果一致性又不牺牲 可用性的分布式存储系统。与传统的强调可用性的分布式系统相比,因果一致性模型对程序员更加友好,又不牺牲 性能。

为什么要在Lamport时钟后附加节点标示符使写入操作的版本号全局唯一?

不唯一会导致两个问题:

  1. 跟踪的依赖不准确,在复制到其它集群时判断依赖是否已经满足时会导致误判:依赖还未写入时会误以为已经 写入。
  2. 无法解决并发写数据时的冲突,由于Lamport时钟不是全序,导致在解决并发冲突时计算最终结果时时不确定的, 这样会导致数据继续分叉。

为什么COPS-GT需要存储完整的依赖而不是从直接依赖计算出完整的依赖?

一个依赖包含key和version,每个key只会存储最近一段时间的version及其直接依赖,所以直接依赖的version可 能已经不存在了,也就无法计算出完整的依赖。

举个例子,假如存有如下数据:

1
2
<key=a, version=1, deps=[<key=b, version=1>]>
<key=c, version=1, deps=[<key=a, version=1>]>

数据c直接依赖a,间接依赖b。然后a更新了同时删除其旧版本:

1
2
<key=a, version=2, deps=[]>
<key=c, version=1, deps=[<key=a, version=1>]>

数据c依然依赖a,但是我们却丢失c对b的依赖信息。

数据中心之间同步时如何保证依赖得到满足?

论文中没有详述,但我想是这样,在消费复制队列时检查依赖在本地是否满足,若没有满足则等待一段时间重试。 没满足的依赖肯定在队列的后面,等待应该是异步的,否则阻塞了队列的消费会导致依赖永远不会被满足。为了优 化这里的重试,消费队列的节点可以跟踪没有满足的依赖,每当消费一个队列元素时则更新这个依赖关系,一旦满 足了条件就立即重试。

另外一种解决办法是操作的发送方在写入消息队列时按依赖的拓扑顺序写入,消费端也按序消费,这样就不用检查 依赖关系了。不过这会导致发送方逻辑变得复杂,而且也会导致消费端吞吐量下降。

Comments