存储 频道

详细解析Dynamo存储引擎

  解决数据版本问题

  这里我们需要讨论一下数据版本问题,这个问题不仅仅存在于分布式系统,只是分布式系统的一些要求使得这个问题更复杂。先看个简单的例子,用户x对key1做了一次写入操作,我们设值是数字3。然后用户y读取了key1,这个时候用户y知道的值是3。然后用户x对值做了一个+1操作,将新值写入,现在key1的值是4了。而用户y也做了一次+1操作,然后写入,因为用户y读到的值是3,y不知道这个值现在已经变化了,结果按照语义本应该是5的值,现在还是4。

  解决这个问题常用的方法是设置一个版本值。用户x第一次写入key1 值3的时候,产生一个版本设为v1。用户y读取的信息中包括版本编号v1。当x做了加1把值4写入的时候,告诉server自己拿到的是版本v1,要在v1的基础上把值改成4。server发现自己保存的版本的确是v1所以就同意这个写入,并且把版本改成v2。这个时候y也要写入4,并且宣称自己是在版本v1上做的修改。

  但是因为server发现自己手里已经是版本v2了,所以server就拒绝y的写入请求,告诉y,版本错误。这个算法在版本冲突的时候经常被使用。但是刚才我们描述的分布式系统不能简单采用这个方式来实现。

  假设我们设置了N=3 W=1。现在x写入key1 值3,这个请求被节点A处理,生成了v1版本的数据。然后x用户又在版本v1上进行了一次key1值4的写操作,这个请求这次是节点C处理的。但是节点C还没有收到上一个A接收的版本(数据备份是异步进行的)如果按照上面的算法,他应该拒绝这个请求,因为他不了解版本v1的信息。但是实际上是不可以拒绝的,因为如果C拒绝了写请求,实际上W=1这个配置,这个服务器向客户做出的承诺将被打破,从而使得系统的行为退化成W=N的形式。那么C接收了这个请求,就可能产生前面提到的不一致性。如何解决这个问题呢?

  Dynamo 的方法是保留所有这些版本,用vector clock记录版本信息。当读取操作发生的时候返回多个版本,由客户端的业务层来解决这个冲突合并各个版本。当然客户端也可以选择最简单的策略,就是最近一次的写覆盖以前的写。

0
相关文章