LSM-Tree 的理解和应用

感时花溅泪,恨别鸟惊心。

1 前言

在前文 OceanBase分布式云数据库实践 中提到了 OceanBase 的数据存储结构使用的是 LSM-tree 即日志结构合并树 (Log-Structured Merge Tree), 随着对众多分布式数据库的了解,使用 LSM-tree 数据结构的数据库还挺多,于是便深入了解一下这个数据结构。众所周知,常用的 mysql 数据库使用的是 b+tree 这种索引结构来实现数据的快速查找,当数据量不大时,这种数据结构对数据的读写支持表现优秀,但是在大量数据时,b+tree 的数据层级会越来越高,此时数据的更新和删除会引发页分裂和页合并,严重的影响了数据的写入性能,需要在适当的时候进行索引重建,释放树结构中的空空间用于提高性能。

LSM-Tree 是一种新的分布式存储系统模型,这种架构设计将顺序写发挥到极致,诸多的数据库如 OceanBase、 HBase、 LevelDB、 PolarDB、 TiDB 都是使用 LSM-Tree 来组织数据结构。

2 基本原理

如下图所示, LSM-Tree 主要由内存数据和磁盘数据组成,在内存中有一个 memtable 和多个 immutable 组成,在磁盘中由多层级的 sstable 组成。 level 越小表示该 levelsstable 数据越新, level 层级越高则表示数据越旧,数据的层级 level 大小可以由系统指定。通常情况下,磁盘中的最小级数为 level0, 但是也可以把内存中的 immutable memetable 定义为 level0, 磁盘中的层级从 level1 开始。

WAL(write ahead log), WAL 是一个以追加的方式记录日志的一个机制。这个机制在数据库中是一个常用的机制,是在操作数据之前先记录日志,以便在系统宕机重启数据时进行数据的恢复。

memtable 是一个有序的数据结构(跳表、有序数组、红黑树或者二叉搜索树) ,这个结构一般是在内存中存在。

sstable 一般是一组 block 元数据组成,元数据 block 存储了 sstable 数据的描述信息,如索引、压缩信息,统计信息,bloomfilter 等信息, sstable 的信息是有序的,一旦写入不能修改。

3 lsm-tree 数据写入

在前文中已经介绍了 LSM-Tree 的基本原理,那么 LSM-Tree 是如何写入数据的呢?

当写入数据时,需要先写入一条 WAL log 日志记录,然后将数据写入内存中的 memtable,这样写入的操作即完成了。 写入的过程和修改的过程都是一样的,删除数据时,则是写入该数据的一条删除标记。当 memtable 的大小达到设定的值(一般是 64KB)时, LSM-Tree 会把当前的 memtable 冻结成为一个不可修改的 immutable memtable ,然后创建一个新的 memtable 继续接受数据的新增、修改和删除。同时 LSM-Tree 会有一个异步线程负责将 immutable memtable 刷新(flush)到磁盘中对数据进行持久化。完成持久化后,即可将该数据对应的 WAL 日志从磁盘中删除。内存中的 immutable memtable 数量取决于 flush 操作的速度。

从数据的写入过程来看,过程比较简单且操作简便,只需要写入 WAL 日志 和内存中的 memtable 即可,WAL 日志是顺序写入的,所以写入速度很快,memtable 的结构一般是二叉搜索树,由于其数据规模小,所以其写入的速度还是很快的。对于 mysql 数据库,其写入的速度随着数据的规模变大而减慢,但是对于 LSM-Tree 结构,其写入的单元是 memtable ,所以数据的规模不影响其写入的速度。

4 lsm-tree 数据读取

了解了 LSM-Tree 的数据写入过程,如果一个数据更新过多次,那么数据将存在多个不同的 sstable 中,在查找数据时,需要按顺序从 level0 到 levelN 进行查找,直到查找到所有的数据位置,读取的数据以低级别的 sstable 为准,因为最新的修改都是在低级别的 level 中。为了提高数据读取的性能,LSM-Tree 采用了 sstable 压缩、布隆过滤器 bloomfilter、 缓存、sstable 合并(compaction) 等操作来提高其读数据性能。

从这个过程可以知道,其读取的数据过程比较复杂和繁琐,随着 level 层级的提高,其读取的数据也会增加。因此,LSM-Tree 支持将多个 sstable 合并成为一个新的 sstable ,在合并的过程中会物理删除被删除的数据,将多个修改合并成一个修改,这个过程和 jvm 垃圾回收算法中的标记整理算法类似,这个过程会增加磁盘IO 和 CPU 的消耗,因此该过程需要在业务低峰期进行。

5 总结

LSM-Tree 主要是牺牲部分读取性能为代价提高了写入性能,适用于时序数据库类的写多读少的场景。 LSM-Tree主要利用磁盘顺序访问要比随机访问快的多的思想以提高写入性能。分布式数据库采用了 LSM-Tree 高效的数据写入特性,同时优化了其数据读取性能,同时充分利用了内存存储的廉价性。相比 mysql 数据库的 b+tree 数据结构,LSM-Tree 提高了分布式数据库的性价比。

相关推荐
苹果酱05676 分钟前
一文读懂SpringCLoud
java·开发语言·spring boot·后端·中间件
掐指一算乀缺钱26 分钟前
SpringBoot 数据库表结构文档生成
java·数据库·spring boot·后端·spring
TravisBytes31 分钟前
linux 系统是如何收发数据包
linux·运维·服务器
ice___Cpu2 小时前
Linux 基本使用和 web 程序部署 ( 8000 字 Linux 入门 )
linux·运维·前端
z202305082 小时前
linux 之0号进程、1号进程、2号进程
linux·运维·服务器
计算机学姐3 小时前
基于python+django+vue的影视推荐系统
开发语言·vue.js·后端·python·mysql·django·intellij-idea
狐心kitsune3 小时前
erlang学习:Linux常用命令1
linux·学习·erlang
JustinNeil3 小时前
简化Java对象转换:高效实现大对象的Entity、VO、DTO互转与代码优化
后端
青灯文案13 小时前
SpringBoot 项目统一 API 响应结果封装示例
java·spring boot·后端
DREAM依旧3 小时前
《深入了解 Linux 操作系统》
linux