LSM存储引擎

1 LSM tree简介

目前很多数据库比如levelDB、rocksDB、HBase、OceanBase的存储引擎都是LSM tree结构。LSM是一种树形的数据结构,由多个层级组成,每层的数据按 key 有序。

2 LSM tree的优缺点

LSM树的核心特点是利用顺序写来提高写性能,但因为分层(此处分层是指的分为内存和文件两部分)的设计会稍微降低读性能,但是通过牺牲小部分读性能换来高性能写,使得LSM树成为非常流行的存储结构。

优点:具有较高的写入性能和压缩存储,适用于写多读少或写入速度较快的场景。通过将写入操作集中在内存和顺序写的日志文件中,可以获得较高的写入吞吐量。查询性能也较好,通过内存缓存和有序的SSTable文件,可以快速定位和检索键值对。

缺点:(1)读放大。如读取操作可能需要扫描多个 SSTable文件,导致查询性能不如B-tree 等结构稳定。此外,合并操作可能会引起较长的停顿时间,对于实时性要求较高的系统可能会有影响。为了解决这些问题,LSM树引入了一些优化技术,如布隆过滤器和层级结构。(2)写放大,因为是顺序追加写,所以对同一个key多次不同的操作都会记录下来,所以需要合并,去重对同一个key的冗余记录。

布隆过滤器(Bloom Filter):LSM-Tree 中的每个 SSTable文件可以关联一个布隆过滤器。布隆过滤器是一种高效的概率型数据结构,用于快速判断某个键是否存在于SSTable文件中,从而避免不必要的磁盘访问。布隆过滤器可以在非常低的误判率下,快速准确地判断某个键是否可能存在于SSTable文件中。布隆过滤器的原理和实现_布隆过滤器 id 不重复-CSDN博客 增加哈希函数数量 k:查询时间略微增加,但显著降低误判率。

层级结构:LSM-Tree 通常包含多个层级,如 Level-0、Level-1、Level-2等。Level-0是内存缓存和日志文件,Level-1及以上是磁盘上的SSTable文件。较小的层级(如Level-0)通常用于高频的写入操作,较大的层级(如Level-1及以上)用于存储稳定的数据。通过层级结构,可以减少查询时需要扫描的SSTable文件数量,提高读取性能。类似冷热分级存储的思想。

压缩和合并策略:LSM树可以采用不同的压缩算法和合并策略来优化存储和性能。例如,可以使用压缩算法对SSTable文件进行压缩,减少磁盘占用空间。合并策略可以根据不同的触发条件和优先级,灵活地控制合并操作的频率和规模,以平衡写入性能和查询性能。

3 LSM存储引擎原理

3.1 核心思想

LSM树有以下三个重要组成部分:

1) MemTable

MemTable是在内存中的数据结构,用于保存最近更新的数据,会按照Key有序地组织这些数据,LSM树对于具体如何组织有序地组织数据并没有明确的数据结构定义(红黑树或者跳表),例如Hbase使跳表来保证内存中key的有序。

因为数据暂时保存在内存中,内存并不是可靠存储,如果断电会丢失数据,因此通常会通过WAL(Write-ahead logging,预写式日志)的方式来保证数据的可靠性。

2) Immutable MemTable

当 MemTable达到一定大小后,会转化成Immutable MemTable。Immutable MemTable是将转MemTable变为SSTable的一种中间状态。写操作由新的MemTable处理,在转存过程中不阻塞数据更新操作。

3) SSTable(Sorted String Table)

有序键值对集合,是LSM树组在磁盘中的数据结构。为了加快SSTable的读取,可以通过建立key的索引以及布隆过滤器来加快key的查找。

这里需要关注一个重点,LSM树(Log-Structured-Merge-Tree)正如它的名字一样,LSM树会将所有的数据插入、修改、删除等操作记录(注意是操作记录)保存在内存之中,当此类操作达到一定的数据量后,再批量地顺序写入到磁盘当中。这与B+树不同,B+树数据的更新会直接在原数据所在处修改对应的值,但是LSM数的数据更新是日志式的,当一条数据更新是直接append一条更新记录完成的。这样设计的目的就是为了顺序写,不断地将Immutable MemTable flush到持久化存储即可,而不用去修改之前的SSTable中的key,保证了顺序写。

因此当MemTable达到一定大小flush到持久化存储变成SSTable后,在不同的SSTable中,可能存在相同Key的记录,当然最新的那条记录才是准确的。这样设计的虽然大大提高了写性能,但同时也会带来一些问题:

1)冗余存储,对于某个key,实际上除了最新的那条记录外,其他的记录都是冗余无用的,但是仍然占用了存储空间。因此需要进行Compact操作(合并多个SSTable)来清除冗余的记录。
2)读取时需要从最新的倒着查询,直到找到某个key的记录。最坏情况需要查询完所有的SSTable,这里可以通过前面提到的索引/布隆过滤器来优化查找速度。
3.2 LSM树的合并策略

leveled策略也是采用分层的思想,每一层限制总文件的大小。

但是跟size-tiered策略不同的是,leveled会将每一层切分成多个大小相近的SSTable。这些SSTable是这一层是全局有序的,意味着一个key在每一层至多只有1条记录,不存在冗余记录。之所以可以保证全局有序,是因为合并策略和size-tiered不同,接下来会详细提到。

假设存在以下这样的场景:

1) L1的总大小超过L1本身大小限制:

2) 此时会从L1中选择至少一个文件,然后把它跟L2有交集的部分(非常关键)进行合并。生成的文件会放在L2:

如上图所示,此时L1第二SSTable的key的范围覆盖了L2中前三个SSTable,那么就需要将L1中第二个SSTable与L2中前三个SSTable执行Compact操作。

3) 如果L2合并后的结果仍旧超出L2的阈值大小,需要重复之前的操作 —— 选至少一个文件然后把它合并到下一层:

leveled策略相较于size-tiered策略来说,每层内key是不会重复的,即使是最坏的情况,除开最底层外,其余层都是重复key,按照相邻层大小比例为10来算,冗余占比也很小。因此空间放大问题得到缓解。但是写放大问题会更加突出。举一个最坏场景,如果LevelN层某个SSTable的key的范围跨度非常大,覆盖了LevelN+1层所有key的范围,那么进行Compact时将涉及LevelN+1层的全部数据。

3.3 写入操作
  • 写入日志文件(Write-Ahead Log, WAL):当有新的 key-value需要写入时,首先将其追加到顺序写的日志文件中。这个操作称为预写日志(Write-Ahead Logging),它可以确保数据的持久性和一致性。
  • 写入内存缓存(Memtable):同时将新的 key-value写入内存中的数据结构,通常是跳表或红黑树等有序数据结构。内存缓存可以快速响应读取操作,并且具有较高的写入性能。
3.4 合并操作

  • 内存与磁盘的合并(Memtable to SSTable):当内存缓存达到一定大小或者其他触发条件满足时,将内存缓存中的 key-value写入到磁盘上的 SSTable 文件中,通常以一种有序的方式进行存储。
  • SSTable的合并:定期或根据其他策略执行 SSTable文件的合并操作。合并操作将多个 SSTable文件进行合并,消除重复的 key和删除的 key,并生成新的 SSTable文件。合并操作可以基于时间、文件大小或其他条件进行触发和控制。
3.5 查询操作
  • 内存缓存查询:首先在内存缓存中查找 key-value,由于内存缓存是有序的,可以快速定位。
  • 磁盘上的SSTable查询:如果在内存缓存中未找到,则依次在磁盘上的 SSTable文件中进行查找,通常采用二分查找等算法进行快速定位和检索。
3.6 删除操作

在 LevelDB 的 LSM-Tree中,删除数据并不会立马做物理删除,而且给数据打一个特殊的删除标,在 LSM-Tree里面叫做 tombstone(墓碑),查询数据时,如果最先查到打了 tombstone 标的数据,就代表数据已经删除了(做数据的物理删除是在 segment 做合并压缩时)。

3.7 层级数量的影响

(1) 层级数较多时

  • 优点
    • 降低读放大:查询时需检查的层级减少(深层数据更集中),I/O 开销降低。
    • 减少空间放大:压缩合并次数减少,冗余数据更少。
    • 优化冷数据存储:深层数据长期保留,适合历史数据分析。
  • 缺点
    • ​IO负载增加:数据需经过更多层压缩,CPU 和磁盘 I/O 负载增大。
    • 压缩延迟:高层级压缩频率低,可能导致 L0 文件堆积,触发频繁压缩。

​(2) 层级数较少时

  • 优点
    • 减少IO负载开销:压缩路径短,CPU 和磁盘负载更低。
    • 降低维护复杂度:层级管理逻辑简单,调试更容易。
  • 缺点
    • 读放大显著:查询需遍历更多层级,尤其是 L0 到 L1 的文件重叠问题。
    • 空间放大增加:数据重复存储在多个层级,存储利用率下降。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值