自2.7版本之后,rocksdb开始支持一种特殊的迭代器(tailing iterator,尾部迭代器),该迭代器经过优化,用于处理一种特殊的需求:新数据一旦被加入到数据库,就会被尽可能快的被读取到。他的主要功能包括:

  • 尾部迭代器不会创建快找,它可以用于读取最新加入的数据(与此对比,普通的迭代器不会看到任何在他创建后新加入的数据)
  • 针对序列化读进行特别优化——这可以避免某些潜在的昂贵的SST文件和不可变memtable的搜索。

在创建迭代器的时候,设置ReadOptions::tailing为true就可以打开这个功能了。注意,目前尾部迭代器只支持正向移动(也就是说不支持Prev和SeekToLast操作是不支持的)

并不是所有的新数据都能保证被一个尾部迭代器读取到。Seek或者SeekToFirst操作可以被认为是在一个隐式创建的快照上操作——任何在这之后的写操作都可能,但是不能被保证会被找到。

实现细节

一个尾部迭代器提供了两个内部迭代器的合并视图:

  • 一个可变迭代器,只用于访问当前的mentable内容。
  • 一个不可变迭代器,用于读取SST文件的数据以及不可变memtable的数据。

上面这些内部迭代器都是通过声明kMaxSequenceNumber来创建的,有效地禁止基于内部序列号的过滤以及允许访问这些迭代器创建之后的数据。更进一步,每个尾部迭代器都追踪数据库的状态变更(比如memtanble刷盘以及压缩)以及在其发生的时候废弃某些内部迭代器。这使之总是能保持最新数据。

由于SST文件以及不可变memtable不会修改,一个尾部迭代器总可以通过只在可变迭代器上进行seek操作来完成。为此,他会维护不可变迭代器覆盖的(prev_key, current_key]的区间(换句话说,如果有一个key k,他要么在sst文件,要么在不可变memtable)。因此,当seek被调用,并且目标在区间内,那么不可变迭代器就已经在正确的位置,并且不必再移动。