因果一致性

在 infoq 分享的腾讯朋友圈的设计中,他们在设计数据一致性的时候,使用了因果一致性这个模型。用于保证对同一条朋友圈的回复的一致性,比如这样的情况:

  1. A 发了朋友圈内容为梅里雪山的图片。

  2. B 针对内容 a 回复了评论:“这里是哪里?”

  3. C 针对 B 的评论进行了回复:”这里是梅里雪山“。

那么,这条朋友圈的显示中,显然 C 针对 B 的评论,应该在 B 的评论之后,这是一个因果关系,而其他没有因果关系的数据,可以允许不一致。

微信的做法是:

  1. 每个数据中心,都自己生成唯一的、递增的数据 ID,确保能排重。在下图的示例中,有三个数据中心,数据中心 1 生成的数据 ID 模 1 为 0,数据中心 1 生成的数据 ID 模 2 为 0,数据中心 1 生成的数据 ID 模 3 为 0,这样保证了三个数据中心的数据 ID 不会重复全局唯一。

  2. 每条评论都比本地看到所有全局 ID 大,这样来确保因果关系,这部分的原理前面提到的向量时钟一样。

有了这个模型和原理,就很好处理前面针对评论的评论的顺序问题了。

  1. 假设 B 在数据中心 1 上,上面的 ID 都满足模 1 为 0,那么当 B 看到 A 的朋友圈时,发表了评论,此时给这个评论分配的 ID 是 1,因此 B 的时钟向量数据是[1]。

  2. 假设 C 在数据中心 2 上,上面的 ID 都满足模 2 为 0,当 C 看到了 B 的评论时,针对这个评论做了评论,此时需要给这个评论分配的 ID 肯定要满足模 2 为 0 以及大于 1,评论完毕之后 C 上面的时钟向量是[1,2]。

  3. 假设 A 在数据中心 3 上,上面的 ID 都满足模 3 为 0,当 A 看到 B、C 给自己的评论时,很容易按照 ID 进行排序和合并--即使 A 在收到 C 的数据[1,2]之后再收到 B 的数据[1],也能顺利的完成合并。