为 Key-Value 数据库实现MVCC 事务
Posted ITPUB
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为 Key-Value 数据库实现MVCC 事务相关的知识,希望对你有一定的参考价值。
-
任何时候只能有一个缓存处于可用状态,代理接口会把所有的请求路由给它(图1.1)。
-
更新数据的时候把新数据加载到目前不可用的缓存中(图1.2)。
-
更新进程切换标志哪个缓存可用的标记(图1.3),代理接口开始把新的读请求分发到新标记为可用的缓存。
-
缓存切换阶段的事务可以依据不用的持久性和隔离性要求来分别处理。如果允许“不可重复读” ,那么切换很简单,老数据会被立刻清理掉。否则,代理接口会维护一个仍未结束的事务列表,并把属于这个列表中的每一个请求都路由到原来的缓存中。只有当列表中的所有事物都提交或者放弃之后老数据才会被清空。
相同的技术也可用于部分更新。依据存储方式的不同也有多种实现方法,我们来看一个有三个缓存简单例子。这个例子中的框架遇上一个类似,但是代理接口按照以下逻辑运行(图 2):
-
用户请求被路由到主缓存("PRIMARY"缓存)(图 2.1)
-
新增数据和更新数据加载进2号缓存(“NEW”缓存),删除项的key放入3号缓存("DELETE"缓存)(图2.2)
-
提交进程(特指写事务)切换全局标示,这个标示会告诉代理接口先去"NEW"和"DELETE"缓存去查找所请求的数据,如果在这两个区域中没有发现再去"PRIMARY"缓存查找(图2.3)。换句话说,在这一步所有的请求都被改派到了更新过的数据中查找。
-
提交进程将 NEW 和 DELETE 区域的变化传递给PRIMARY。也即在PRIMARY缓存区以非原子的方式更新、增加、删除数据项(图2.4)。
-
最后,所有的提交进程把全局标识切换回来,所有的请求仍然路由到 PRIMARY 缓存区域(图2.5)。
-
在第4步,可以把老数据拷贝到另一个缓存区,这样就可以支持回滚操作。即使是全量更新也可以用这种方法。
从上面的两个例子我们可以看出,专用于读的数据快照避免了数据更新的干扰,大大降低了复杂性。在一个写密集型的环境中就不容易做到这一点了。在下一节我们会讨论一种非常好的方法可以完美的解决这个问题。
-
它会获得一个全局唯一且单调递增的事务ID ,也叫 XID。 -
进程里保存着所有事务的XID.
-
当数据项被某个事务建立的时候, xmin 设置为该事务的XID ,xmax 无值。 -
当数据被某个事务移除的时候,xmin 不变,xmax 设置为该事务的XID。数据并没有真的从缓存中清除,只是被标记为已删除。 -
当数据被某个事务更新的时候,老数据仍然保存在缓存里,xmax 被赋值为事务的XID,同时增加一条新的数据,新数据的 xmin 也赋值为XID 并且xmax 为空。换句话说更新操作等于一次删除加一次增加。
-
xmin 有值并且小于或等于当前事务ID。 -
xmax 为空,或者等于未提交事务(放弃的或者还未完成的)的XID ,或者大于当前事务ID。
-
所有的版本都存储在同一个key-value空间中,对版本数量没有限制(也即可以储存任意多的版本,译者注)。由一个后台进程来回收老版本数据,这个回收可以按计划调度执行也可以再读或者写的时候触发。 -
主key-value 空间只储存最新的版本,之前的版本储存在另外的地方,且储存老版本的空间大小是固定的。 最新的版本会指向之前的版本,但是却不能够由此上溯到之前的任意版本, 因为存储老版本数据的区域大小是固定的, 太早的版本会被移除。如果某个事务不能够找到指定版本的数据就会失败。
大会以"架构创新之路"为主题,共设置两个主场分享时段,24个技术交流专场时段;邀请来自互联网、电子商务、金融、电信、政府、行业协会等20多个领域,150多位技术专家及行业领袖来分享他们的经验;并将吸引4000多名系统运维、架构师、及各种企业的IT决策人士参会,为他们提供最具价值的交流平台。
以上是关于为 Key-Value 数据库实现MVCC 事务的主要内容,如果未能解决你的问题,请参考以下文章