知识卡片

多机房写入冲突解决的三种方案:时间戳最新、Primary Key、Vector Clock

普通读书笔记卡

内容

当同一份数据允许在多个机房被并发写入时,几乎必然产生冲突,解决冲突的方案在正确性和复杂度上依次递进。最简单的是”时间戳最新”策略:任意机房写入的数据都带上时间戳,冲突发生时直接以时间戳最新的版本为准,实现极其简单,但隐含一个风险——不同机房的时钟未必精确同步,时间戳比较在极端情况下可能给出错误的先后判断。第二种是Yahoo Pnuts提出的Primary Key机制:给每个key指定一个归属的Primary IDC,这个key的所有修改、删除操作都只在它归属的这个机房内完成(配合类似CAS的Version信息保证单条数据的事务性),其他机房只能读取;如果数据本身很少跨地域被同一批人反复修改(比如用户自己的profile信息,90%的情况下修改者本人都在同一个机房),这个方案的性能会非常好——本机房内的写入延迟很低,只有真正发生跨机房修改时才需要付出较高的Cross-IDC延迟,如果发现某个key被其他机房频繁修改,还可以主动把这个key的Primary IDC迁移过去做优化。第三种是Vector Clock(向量时钟):核心思路是承认服务端对数据内容一无所知(对Server而言value只是一段字符串),真正理解数据语义、知道该如何合并冲突的是客户端,所以当客户端读到多个机房存在冲突的版本时(通过比较各自携带的向量时钟判断出这些版本互相不是祖先-后代关系而是并发修改),由客户端自己决定如何合并这些版本、再把合并结果重新写回,服务端全程只负责存储和暴露冲突,不参与冲突的语义判断。Bada线上实际主要使用时间戳最新和Primary Key两种方案,没有采用Vector Clock,反映出在权衡”实现复杂度”和”冲突处理精确度”时,业务方通常优先选择足够简单、能覆盖大部分场景的方案,只有在数据结构足够复杂、必须由客户端理解语义才能正确合并时,才值得引入Vector Clock这类更重的机制。

参考来源

- 位置:《高可用架构(第1卷)》第2章《高可用架构原理与分布式实践》"2.5 360分布式存储系统Bada的架构设计和应用"节,"2.5.6 多机房架构"(源文件:_epub-src/OEBPS/Text/Chapter2_5_7.xhtml) - 结论依据:原文分别介绍时间戳最新、Yahoo Pnuts Primary Key、Vector Lock三种冲突解决方案的机制,并说明"我们线上目前支持的是时间戳最新以及Primary key的方案。大部分使用的是时间戳最新来进行冲突解决",共同支撑本卡片结论。 - 原始内容:时间戳最新……Yahoo Pnuts Primary key……这里我们对每一个key有一个Primary IDC……Vector Lock的核心思想就是Client对这个数据的了解是远远超过服务端的……我们线上目前支持的是时间戳最新以及Primary key的方案。