mavibot btree实现原理

Mavibot 是个Java 的多版本并发控制 BTree,是 JDBM(当前 Apache Directory 服务器的后端)的替代品, 但是有着更强的功能,能适应任意需要实现 Java MVCC BTree 的项目。Btree是在红黑树的基础上提出的。红黑树的高度,限制了其性能。而Btree则通过扩展节点的存储功能,降低了树的高度。

1 红黑树(平衡二叉树)

内存索引的文章中已经对平衡二叉树进行了描述。这里注意两点:
第一点: 平衡二叉树的高度,影响了插入、查询的效率。维护的数据越多,二叉树的高度越高,插入数据和查询数据的比较次数就越多。最理想的效率是进行log2n次的数据比较(n是数据个数。在完全二叉树的情况下。)
第二点:并发控制。平衡二叉树,为了维护平行特性,需要交换子树的父子节点关系。如果当前的子树高度发生了变化,那么子树所在的父节点也需要balance操作(当然,如果左右子树的高度相差小于等于1,就不需要进行交换擦做。)这么说来,插入一个节点,可能会导致根节点发生变化。从这个角度来讲,平衡而插入的并发插入需要给整棵树加锁,也就是说插入是串行的。在不改进二叉树的算法情况下(目前还不了解怎么改进二叉树算法,从而满足并发),插入的性能是无法优化的。

2 B-Tree

目前几乎所有的数据库索引都采用了B树结构。在平衡二叉树的基础上,B树每一层的数据量更多,所以树的高度降低,加快了查询和插入的效率。
B-Tree组织结构如下图:
在这里插入图片描述
TreeNode不存储数据,只负责检索。TreeLeaf存储了所有的数据。TreeLeaf中,key和value分别为两个数组。相同的位置,对应一对<key,value>.

在并发的角度来看,B树依旧很难线程安全。
下图是mavibot的BTree添加数据的算法。再添加的过程中,一个树节点的元素个数超出了限制,就需要对节点进行分裂操作。
当新的数据到来时,将数据插入叶子节点中。此时发现叶子节点的数据量已经超过限制,则对叶子节点进行分割,形成两个节点。叶子节点将分裂的信息传递给根节点。根节点原来有一个position的信息指向叶子节点。但是目前叶子节点分裂成两个,所以根节点需要新建立一个新的position指向另外一个叶子节点。根节点将position之后的所有数据向后移一位,然后在position+1的位置存储新叶子的信息。实际上相当于根节点也增加了一个数据。
在一定条件下,一个叶子节点发生分裂时,可能导致整棵树的高度变化。(沿着路径,所有的节点都发生了分裂,那么根节点就会分裂成两个。为了保证一棵树只有一个根节点,需要生成一个新的根节点,作为整棵树的根。)
所以,和平衡二叉树的情况类似,添加一个元素可能会导致整棵树的组织结构发生变化。如果想并发构建这棵树,就需要给整棵树加同步。
在这里插入图片描述

3 多版本控制(MVCC)

在mavibot中通过多版本控制的方式,达到读写并发、事物、回滚的功能。多版本可以保证在修改的时候,不会影响查询,保证查询的效率。但是无法支持并发写。
下面以插入为例,介绍多版本控制的实现方式。
当插入请求发起,mavibot会创建一个新根节点,指向当前的树。通过新树查找对应的叶子节点。找到叶子节点后,将复制当前叶子同时插入新元素。
完成后,将新的叶子节点返回给parent。这时,current树并没有发生变化。
上一级的父节点TreeNode接到返回结果后,会将本身拷贝出一个新的节点,然后返回新的节点。按此方式处理,直到根节点。
从而,从根节点到插入元素的叶子节点的路径上,所有节点都会拷贝出一个新的对象。而不在路径上的节点,保持不变。这样就以最快的速度复制出一个新的版本来。
总的来说,在多版本控制方式下,插入新的元素,需要将元素所在的叶子节点和根节点的路径上所有节点进行了复制。而非路径上的节点不会发生变化。通过此种方式,保证了插入时不影响读操作,同时也降低了完全备份带来的时间和空间的消耗。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值