Log Structured Merge Trees (LSM)

1      概念

LSM = Log Structured Merge Trees

来源于google的bigtable论文。

 

2      解决问题

传统的数据库如MySql采用B+树存放数据,B+树是一个随机读写的数据结构。 我们知道,顺序读写要比随机读写快无数倍,所以需要把数据结构改成顺序读写。

 

3      应用场景

LSM是当前被用在许多产品的文件结构策略:HBase, Cassandra, LevelDB, SQLite,甚至在mangodb3.0中也带了一个可选的LSM引擎(Wired Tiger 实现的)。

 

LSM-Tree比较适合的应用场景是:insert数据量大,读数据量和update数据量不高且读一般针对最新数据。

 

4      实现原理

4.1      基本原理

1、  数据按时间和大小分文件存放(sstable文件)。

2、  新的修改用Copy-On-Write Tree方式按key缓存在内存(memtable)中,内存中保序。

3、  内存达到时间或大小条件后,保存在一个新的文件里(顺序写,速度很快)。

4、  对已经保存的文件,不再修改。

5、  查询的时候,先查内存,然后依次查各个保存的文件。

6、  因为每个文件里的数据都是顺序存放的,所以查询速度较快(二分查找)。

4.2      提升读性能的方案

1、  定时触发文件合并操作,删除冗余记录,并减少文件个数,提升查询效率(由于sstable里的记录是顺序存放的,所以合并非常高效(归并算法、顺序读写))。

2、  采用页缓存,减少二分查找的消耗。LevelDB 和 BigTable 是将 block-index 保存在文件尾部,这样查找就只要一次IO操作,如果block-index在内存中。

3、  采用布隆过滤器,减少不存在数据的判定逻辑。

4、  并行合并。

打个比方,合并操作就是JVM里的GC,在合并的时候,势必会影响其他操作。所以我们用G1的思想,把文件分区域,各个区域分别合并,这样,就可以减少停顿(加锁)的时间,同时也减少了合并文件额外需要的空间。

想想这个结构,类似于一颗新的树,这个树的每个节点是一个文件,每个文件的内容是sstable。

 

 

5      优点

1、写性能高。

2、只需要对内存部分加锁,文件不会修改,无需加锁

6      缺点

1、对于频繁大规模改动的场景不好。

 

7      最佳实践

1、  memtable丢失的问题:需要记录redo日志和恢复时间点,用于重建memtable。

2、   

8      参考

LSM存储模型

https://www.cnblogs.com/chenny7/p/4568829.html

LSM 算法的原理是什么?

https://www.zhihu.com/question/19887265

 

转载于:https://www.cnblogs.com/aoyihuashao/p/10749120.html

### LSM树的数据结构及其实现原理 #### 什么是LSM树? LSM树(Log-Structured Merge Tree)是一种高效处理海量数据读写的存储引擎设计模式。其核心目标是通过减少随机写入操作的数量,从而显著提升写入性能[^3]。 --- #### LSM树的核心组件 1. **内存部分 (MemTable)** 写入请求首先被记录到一个称为 MemTable 的内存数据结构中。通常是一个有序的键值对集合,在内存中按顺序排列以便快速查找和插入。当 MemTable 达到一定大小时,会被冻结并持久化到磁盘上作为 SSTable 文件的一部分[^1]。 2. **磁盘部分 (SSTable)** 当 MemTable 被刷写到磁盘时,它会转换成不可变的文件形式,即 SSTable(Sorted String Table)。这些文件按照键值范围分片存储,并且内部按键排序。每次新的 SSTable 创建后,都会触发后台线程执行合并过程以优化整体查询效率。 3. **WAL 日志 (Write-Ahead Log)** 为了防止系统崩溃导致未保存至 MemTable 或 SSTable 中的数据丢失,所有的修改操作还会同步追加到 Write-Ahead Log (预写日志)里。这样即使发生意外宕机也能恢复最近的操作记录。 --- #### 工作流程概述 以下是 LSM 树的主要工作阶段: 1. **写入路径** - 用户发起写请求时,新条目直接存放到 MemTable 并同时追加到 WAL。 - 如果 MemTable 填满,则将其内容转储为一个新的 SSTable 文件并刷新到硬盘上。 2. **读取路径** - 对于每一次读取请求,系统依次检查多个位置:首先是当前活跃的 MemTable;其次是尚未完成合并的老版本 SSTables 和最新生成的新版 SSTables。 - 查询过程中可能涉及多层不同时间戳下的副本比较,最终返回最新的有效结果[^2]. 3. **Compaction 合并机制** 随着时间推移,会产生越来越多的小型 SSTable 文件。为了避免过多碎片化的索引影响检索速度,周期性的 Compaction 进程负责将若干个小表合并成为一个更大的全局一致视图。此步骤不仅能够消除重复项或者标记已删除项目,还能重新整理物理布局使得后续访问更加紧凑连续。 --- #### 性能特点分析 - **优势** - 提高了大批量持续写入场景下的吞吐能力,因为大部分实际改动都发生在易失性 RAM 缓冲区内而不是昂贵缓慢的传统机械硬盘介质之上; - 减少了因频繁覆盖造成的额外开销,特别是在 SSD 上表现尤为明显由于减少了擦除次数延长使用寿命; - 支持动态调整参数比如压缩比率、扇区尺寸等满足特定应用需求. - **劣势** - 可能带来较高的延迟波动尤其是对于单个事务而言如果正好赶上正在进行的大规模 compactions 操作期间; - 相较传统 B+Trees 来说初始构建成本较高并且维护复杂度也有所增加. ```python class LSMTNode: def __init__(self, key=None, value=None): self.key = key self.value = value def write_to_memtable(memtable, key, value): memtable[key] = value def flush_memtable_to_disk(memtable): sstable_file = [] sorted_items = dict(sorted(memtable.items())) for k,v in sorted_items.items(): sstable_file.append((k,v)) return sstable_file mem_table = {} write_to_memtable(mem_table,"key1","value1") # Simulate writing to memory table. flushed_data = flush_memtable_to_disk(mem_table) # Flush data when full or triggered by policy. print(flushed_data) ``` 上述代码片段展示了如何模拟向 MemTable 插入一条记录以及之后如何把整个表格的内容导出成为 SSTable 形式的列表对象。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值