引言
无论是MemTable、还是immutable MemTable,在leveldb源码实现中都是MemTable类型。其核心数据结构是跳表。
1 跳表原理
1.1 数据结构
跳表主要是优化传统有序链表的操作时间复杂度,类似二分查找算法思想。其结构如下图:
图中是一个最大高度为3的跳表。表头有3个指针域,数据节点为1到3个指针域。所有的指针域指向后续节点的基地址,例如数据域1的level ptr0和头节点的level ptr1都指向数据域2对应节点的基地址。
1.2 数据查询
数据查询核心思想就是查询大于或等于查找数据的节点。以查询数据域4为例,其步骤如下:
- 首先,在level 2级,从表头开始遍历查询大于或等于数据域4的节点,得到数据域5所在节点。同时,记录level 2与数据域3所在节点的索引关系;
- 然后,在level 1级,从数据域3所在节点开始遍历查询大于或等于数据域4的节点,得到数据域5所在节点。同时,记录level 1与数据域3所在节点的索引关系;
- 继续,在level 0级,从数据域3所在节点开始遍历查询大于或等于数据域4的节点,得到数据域4所在节点。同时,记录level 0与数据域3所在节点的索引关系;
- 最后比较数据域4所在节点是否与数据域4相等,因为相等所以查询成功。
1.3 插入节点
插入节点按照如下的顺序:
- 首先,根据算法生成一个节点并填充数据域。例如在leveldb中,是通过随机生成高度为1到12不等的节点;
- 然后,查询大于或等于插入数据的节点,得到一个level 0到2的前继节点索引。leveldb中用数组代替索引,即用下标表示level;
- 遍历插入节点的每个level,将插入节点追加到前继节点索引中对应level ptr的后面。
1.4 删除节点
注:删除节点与插入类似,也是借助查询来剔除节点、重建链表指向关系。
2 源码解读
整个MemTable类由两部分组成,即Area类和SkipList模板类。前者是内存池的实现,后者是跳表的模板实现。
注:Area的实现原理参考上节。
在SkipList只提供了插入、查询、迭代功能,未提供delete操作。之所以没有提供delete操作,是因为MemTable只提供追加数据操作,当我们delete key只是将操作类型追加到数据库中。