确定前后关系
- 服务器为每个主键维护一个版本号,每当主键新值写入时递增版本号,并将新版本号与写入值一起保存。
- 当客户端读取主键时,服务器将返回所有(未被覆盖的)当前值以及最新的版本号。且要求写入之前,客户端必须先发送读请求。
- 客户端写主键,写请求必须包含之前读到的版本号,读到的值和新值合并后的集合。写请求的响应可以像读操作一样,会返回所有当前值,这样可以一步步链接起多个写入的值。
- 当服务器收到带有特定版本号的写入时,覆盖该版本号或者更低版本的所有值,但必须保存更高版本号所有值。
当写请求包含了前一次读取的版本号时,意味着修改时基于以前的状态。否则它将与所有的其他写入同时进行,不会覆盖任何已有值,其传入的值将包含在后续读请求的返回值列表中。
合并同时写入的值
上面算法不会导致数据丢失,但是客户端需要做一些额外的工作:如果多个操作并发发生,则客户端必须通过合并并发写入的值来继承旧值。同时删除需要特殊的墓碑标记,防止被合并回去。
版本矢量
每个副本和每个主键均定义一个版本号,每个副本在处理时增加自己的版本号,并跟踪从其他副本看到的版本号。通过这些信息来指示要覆盖那些值,该保留那些并发值。
所有的版本号集合称为版本矢量。