Tailing Iterator 尾部迭代器

自2.7版以来,RocksDB支持一种特殊类型的迭代器(称为拖尾迭代器),该迭代器针对一种用例进行了优化, 在这种用例中,新数据只要添加到数据库就会被读取。其主要特点是:

  • 跟踪迭代器在创建快照时不会创建快照。因此,它还可以用来读取新添加的数据(而普通迭代器在创建迭代器之后不会看到添加的任何记录)。
  • 它针对顺序读取进行了优化——在许多情况下,它可能避免对SST文件和不可变的memtables执行潜在的昂贵查找。 要启用它,请在创建新迭代器时将ReadOptions::tailing设置为true。注意,拖尾迭代器目前只支持向前移动(换句话说,不支持Prev()和SeekToLast())。

并不是所有的新数据都保证对跟踪迭代器可用。跟踪迭代器上的Seek()或SeekToFirst()可以看作是创建一个隐式快照——在它之后编写的任何内容都可以,但不能保证能够被看到。

实现细节

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

  • 一个可变迭代器,仅用于访问当前memtable内容
  • 一个不可变的迭代器,用于从SST文件和不可变的memtables中读取数据

这两个内部迭代器都是通过指定kMaxSequenceNumber创建的,它有效地禁用基于内部序列号的过滤,并允许访问在创建这些迭代器之后插入的记录。 此外,每个跟踪迭代器都跟踪数据库的状态更改(如memtable刷新和压缩),并在发生更改时使其内部迭代器失效。这使得它总是最新的。

由于SST文件和不可变memtables不会更改,跟踪迭代器通常只能在可变迭代器上执行seek操作。 为此,它维护当前由不可变迭代器覆盖的区间(prev_key, current_key)(换句话说,没有key k的记录使得prev_key < k < current_key既不在SST文件中也不在不可变memtables中)。 因此,当调用Seek(target)并且目标位于该区间内时,不可变迭代器已经位于正确的位置,没有必要移动它。