RocksDB系列十九:Iterator Implementation

RocksDB Iterator

  RocksDB Iterator提供用户以有序的方式前向或者后向遍历DB,也可以seek 到DB的特定key上。为了做到这样,Iterator必须以有序流的方式访问DB。RocksDB Iterator的实现类命名为DBIter。

DBIter

  • Implementation: db/db_iter.cc
  • Interface: Iterator

  DBIter是InternalIterator的封装。DBIter的任务就是解析由InternalIterator 暴露出来的InternalKeys,最后以user key的形式展现。
Example:
The underlying InternalIterator exposed

InternalKey(user_key="Key1", seqno=10, Type=Put)    | Value = "KEY1_VAL2"
InternalKey(user_key="Key1", seqno=9,  Type=Put)    | Value = "KEY1_VAL1"
InternalKey(user_key="Key2", seqno=16, Type=Put)    | Value = "KEY2_VAL2"
InternalKey(user_key="Key2", seqno=15, Type=Delete) | Value = "KEY2_VAL1"
InternalKey(user_key="Key3", seqno=7,  Type=Delete) | Value = "KEY3_VAL1"
InternalKey(user_key="Key4", seqno=5,  Type=Put)    | Value = "KEY4_VAL1"

But what DBIter will expose to the user is

Key="Key1"  | Value = "KEY1_VAL2"
Key="Key2"  | Value = "KEY2_VAL2"
Key="Key4"  | Value = "KEY4_VAL1"

MergingIterator

  • implementation: table/merging_iterator.cc
  • Interface: InternalIterator
    MergingIterator 包括很多 child iterators,MergingIterator 是一个Iterators堆。在MergingIterator 中,我们把所有的child Iterator放进heap中,以一种有序的流形式暴露。
    Example:
    The underlying child Iterators exposed:
= Child Iterator 1 =
InternalKey(user_key="Key1", seqno=10, Type=Put)    | Value = "KEY1_VAL2"

= Child Iterator 2 =
InternalKey(user_key="Key1", seqno=9,  Type=Put)    | Value = "KEY1_VAL1"
InternalKey(user_key="Key2", seqno=15, Type=Delete) | Value = "KEY2_VAL1"
InternalKey(user_key="Key4", seqno=5,  Type=Put)    | Value = "KEY4_VAL1"

= Child Iterator 3 =
InternalKey(user_key="Key2", seqno=16, Type=Put)    | Value = "KEY2_VAL2"
InternalKey(user_key="Key3", seqno=7,  Type=Delete) | Value = "KEY3_VAL1"

MergingIterator 将所有的child Iterators 放到堆中,以有序流的形式暴露。

InternalKey(user_key="Key1", seqno=10, Type=Put)    | Value = "KEY1_VAL2"
InternalKey(user_key="Key1", seqno=9,  Type=Put)    | Value = "KEY1_VAL1"
InternalKey(user_key="Key2", seqno=16, Type=Put)    | Value = "KEY2_VAL2"
InternalKey(user_key="Key2", seqno=15, Type=Delete) | Value = "KEY2_VAL1"
InternalKey(user_key="Key3", seqno=7,  Type=Delete) | Value = "KEY3_VAL1"
InternalKey(user_key="Key4", seqno=5,  Type=Put)    | Value = "KEY4_VAL1"

MemtableIterator

  • Implementation: db/memtable.cc
  • Interface: InternalIterator

MemtableIterator是MemtableRep::Iterator的封装,内存表实现自己Iterator都是以keys/values的有序流的形式暴露。

BlockIter

  • Implementation:table/block.h
  • Interface: InternalIterator

这个Iterator用来从SST file中读取blocks,与blocks是Index blocks或者data block是无关。由于,SST file blocks是有序的且不可更变的,所以我们可以load block数据到memory总,然后为这个有序的数据创建一个BlockIter。

TwoLevelIterator

  • Implementation: table/two_level_iterator.cc
  • Interface: InternalIterator

一个TwoLevelIterator 包含两个Iterators

  • First level Iterator (first_level_iter_)
  • Second level Iterator (second_level_iter_)

first_level_iter_用来计算出接下来要使用的second_level_iter_,second_level_iter_指向我们要读取的实际数据。
Example:
RocksDB使用TwoLevelIterator 来读取SST file,first_level_iter_ 是SST File Index block上的BlockIter,second_level_iter_ 是Data Block上的BlockIter。
下面看一个简单的SST file,有4个Data blocks和1个Index Block

[Data block, offset: 0x0000]
KEY1  | VALUE1
KEY2  | VALUE2
KEY3  | VALUE3

[Data Block, offset: 0x0100]
KEY4  | VALUE4
KEY7  | VALUE7

[Data Block, offset: 0x0250]
KEY8  | VALUE8
KEY9  | VALUE9

[Data Block, offset: 0x0350]
KEY11 | VALUE11
KEY15 | VALUE15

[Index Block, offset: 0x0500]
KEY3  | 0x0000
KEY7  | 0x0100
KEY9  | 0x0250
KEY15 | 0x0500

要想读这个file,我们要创建一个TwoLevelIterator

  • first_level_iter_ => BlockIter over Index block
  • second_level_iter_ => BlockIter over Data block that will be determined by first_level_iter_

当通过TwoLevelIterator seek到KEY8时,首先使用first_level_iter_ (BlockIter over Index block)计算出哪个block可能包含这个key,结果是设置second_level_iter_ to be (BlockIter over data block with offset 0x0250)。然后我们使用second_level_iter_ 在data block中读取key &value

你可能感兴趣的:(RocksDB系列十九:Iterator Implementation)