RocksDB 的 Iterator
概述
RocksDB的数据主要存储在三个部分:Memtable,Immutable Memtable和SST文件,当用户需要遍历整个数据集合时,RocksDB提供了Iterator的接口解决这个问题。
Iterator的结构
1 | // Try to generate a DB iterator tree in continuous memory area to be |
RocksDB为所有的子Iterator申请连续的内存,目的是所有的Iterator指针距离更近,尽可能的在相同的Cache Line,这样迭代起来速度更快。
其中IternalIterator就是具体使用的Iterator: 它的具体实现就是依次从RocksDB里的三个数据存储部分Memtable, Immutable Memtable和SSTtable文件创建Iterator,下面解释一下具体关于数据存储部分的Iterator:
MemtableIterator
:Memtable和Immutable Memtable的Iterator:以默认的Memtable的数据结构SkipList来举例,就是SkipList暴露的Iterator接口。Iterator的
Next()
迭代也就是SkipList的第0层迭代TwoLevelIterator
:SSTable文件的IteratorLevel-0层:
因为Level-0层有重叠的数据,所以每个文件的Iterator都需要作为一个单独的Iterator被添加
非Level-0层:
迭代该层级的所有文件,因为是不重叠的,所以简单的顺序迭代就可以。
TwoLevelIterator
封装了SSTable中Block的Index Iterator和Data Iterator,根据Index定位到具体的Data:- 首先通过
index_iter_->Seek(target)
得到index_iter_
的Value,即Key所在的Data的索引信息 - 定位到具体的Data之后,调用
data_block_iter_->Seek(target)
,定位到需要查找的Key
- 首先通过
Iterator结构梳理
结合上面的结构图和解释,我们可以梳理RocksDB的Iterator结构:
数据的Iterator:
包括
MemtableIterator
,BlockIterator
,TwoLevelIterator
合并后的Iterator:
每个数据的Iterator内部是有序的,
MergingIterator
负责将这些收集的数据Iterator合并,返回一个完整的所有数据有序的Iterator,MergeingIterator
包含所有的Iterator。DBIter
的构造过程:对DB遍历时,获取整个DB内部的Iteraror,然后封装成DBIterator
- 获得Memtable的Iterator
- 获得Immutable memtable的Iterator
- 获得整个SSTable的Iterator
- Level-0中所有的SSTable的Iterator
- 非Level-0的层级上的SSTable的Iterator集合
- 将获得的所有Iterator作为
child iter
构造MergingIterator
- 构造DBIterator
Iterator使用的一个子问题
Iterator遍历的是什么时间节点的数据?
Iterator是迭代某一个快照的数据,将快照的
read_options.snapshot->GetSequenceNumber()
作为SequenceNumber。如果没有指定快照,则将versions_->LastSequence()
设为SequnceNumber。