DDD-日志结构的存储DB(2)

372 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情

本系列主要是《数据密集型应用系统设计》阅读笔记,本文记录日志结构的存储引擎主题的笔记心得。

key-value对的顺序按键排序

DDD-日志结构的存储DB概述(1)每个日志结构的存储段都是一组key-value对的序列,且这些key-value对是没有顺序的。

如果要求key-value对的顺序按键排序,看起来可能会打破顺序写的规则。

这个格式便是排序字符串表,即SSTable.

之所以提出这样的一个设想,是因为:

  • SSTable合并段更加简单高效。如下图:

image.png

  • 查找特定的key,可以不用在内存中保存所有键的索引。可以用更为稀疏的索引。如下图:

image.png

  • 如果是查找某个范围,可以考虑将这些范围保存到一个块中并在写磁盘之前将其压缩,如上图所示。这样能节省磁盘空间和I/O带宽。

构建和维护SSTable

在内存中维持排序结构更加简单。有很多广为人知的树状数据结构。例如红黑树或AVL树。 存储引擎的如下工作:

  • 当写入时,添加到内存的平衡树。
  • 当内存表大于某个阈值,将其作为SStable文件写入磁盘。新的SStable文件作为数据库的最新部分,当SStable写磁盘的同时,新的心如可以添加到一个新的内存表。
  • 读请求先在内存中查找key,然后时最新的磁盘段文件,接下来是次新的。依此类推。
  • 后台进程周期性的执行段合并和压缩的过程,以合并多个段文件。
  • 如果数据库奔溃,最新写入内存表的将会丢失。为了避免这个问题,在磁盘上保留单独的日志,每个写入都会立即追加到该日志。这个并不需要排序,因为它的唯一目的是在奔溃后恢复内存表。每当内存表写入SStable文件,相应的日志可以丢弃。

LSM-tree

上面描述的算法正是LevelDB和RocksDB所使用的。最初这个索引结构被命名为日志结构的合并树(Log-Structureed Merge Tree),建立在更早的日志结构的文件系统之上。

性能优化

比如如何快速的判断一个key不在DB里面?LSM-tree可能很慢,需要先访问内存表,再访问段文件,以及更旧的段文件,直到扫描完毕,效率很低。为了优化这个问题,DB往往还会维护一个布隆过滤器。

虽然B树是使用最广泛的一种索引,但是LSM tree已经慢慢得到了更大的认可。