数据库入门指南:数据库存储LSM-Tree | 青训营

78 阅读4分钟
LSM-Tree树存储架构

日志结构合并树(Log-Structured Merge Tree),不是严格的树,有不同的实现。

参考链接:juejin.cn/post/720393…

LevelDB的LSM-Tree 由以下几部分组成:

  • 日志文件:防止故障导致内存表数据丢失。

  • 内存表:

    • 唯一可写的Memtable。当Memtable大小到达上限时,将转变为只读的 Immutable Memtable,然后创建一个新的 Memtable 供数据写入。
    • 一个或多个的只读的Immutable Memtable。Immutable Memtable将排序写入磁盘L0层,成为SSTable文件。

    内存表的数据结构往往是跳表(Skip List),支持高效的数据插入和查找。为了支持按序扫描操作,Leveldb的Memtable中的键值对是根据Key的大小有序存储的。

    为了避免多次的申请和释放(new/delete)带来的开销,可以一次申请大块的内存,多次分给客户,实现用户区的内存管理和分配,即内存池

  • 静态表:

    磁盘中包含多个 level 的只读的 SSTable静态表文件。

    Level 越小,表示该层级的 SSTable 数据越新,level 越大,表示该层级的 SSTable 数据越旧。

    SSTable包括:

    • 数据存储区:存放实际的 key-value 数据,由数据块组成。

      对于数据块:

      • L1层及以上的SSTable的数据块中的key是有序存储的,因此有很大的概率key的前缀重复出现,因此存储时采用前缀压缩,后一个key只存储与前一个key不同的部分。

      • 重启点(restart)指出的位置就表示该key不按前缀压缩,而是完整存储该key。

        重启点的第二个作用就是加速读取,可以通过二分的方法来定位具体的重启点位置。

    • 数据管理区:存放元数据块MetaBlock,保存元信息,如索引(指向记录的偏移量)、布隆过滤器、统计信息等,目的是更快速便捷的查找SSTable中相应的记录。

      • 索引块:记录每个数据块的最大Key与偏移,用于实现二分查找

    SSTable文件合并和压缩操作(compaction)

    定期使用多路归并排序对多个文件中的所有记录重新进行排序,生成新的SSTable 文件,并丢弃已被覆盖或删除的值。

    刚写入磁盘的L0层SSTable间是无序的,SSTable取值范围存在交集,L1层及以上SSTable间是有序的,SSTable 取值范围无交集。

    如图所示,一个L层的SSTable 被并入L+1层,参与合并的L+1层SSTable 是与L层的SSTable取值范围存在交集的SSTable 。

读写操作:

  • 写操作:

    • 将记录以顺序写的方式追加到log日志文件末尾。
    • 把记录写入到内存表 Memtable。
  • 读操作:

    • 按照Memtable、Immutable Memtable、 L0 SSTable、L1 SSTable ... LN SSTable顺序查找,即记录创建的时间先后顺序,先读到就是最新的。

      利用L1层及以上SSTable间是有序的,SSTable 取值范围无交集,可使用二分查找快速确定此层需要查找的SSTable。

      使用布隆过滤器可以快速确定目标数据是否可能在 SSTable 中,无需读取数据块。

优点和缺点:

  • 优点:日志结构的写操作只需在日志文件和 Memtable 上各添加一条记录即可,磁盘文件合并是后台异步进行,写操作只有追加日志文件的磁盘顺序写,消除了随机写,写性能好。

  • 缺点:

    • 随机读性能一般,但根据局部性,最近写的数据更可能被读出,Memtable相当于缓存优化。
    • 数据写入和数据合并会竞争磁盘I/O资源
    • 对于区间查找,需要查找每个层级对应区间的SSTable ,读放大严重,层级一般不能太多。

Bitcask和LSM比较:

Bitcask和LSM都是日志结构的存储架构,消除了随机写,只会顺序写日志文件。

  • Bitcask实现更简单,但不支持区间查找。

    LSM实现更复杂,支持区间查找。

  • Bitcask内存中的是索引,读写一定需要访问磁盘日志文件。

    LSM的内存表中是数据,写操作是写内存表和磁盘日志文件,读操作是先读内存表,内存表实际上具有缓存功能,因此LSM一般比Bitcask更优。

  • Bitcask中的日志文件的功能是存储数据。

    LSM中的日志文件的功能是保证数据的可靠性,数据存储在内存表和静态表中。