LSM架构
简介
LSM全称指:Log-Structured Merge-Tree
, 是一种专门为写密集型应用设计的数据结构,主要在键值存储和数据系统中使用。它的核心思想是将所有的写操作(包括插入、更新、和删除)先记录到内存中,然后再定时周期性地将这些更改批量写入到磁盘上,从而减少磁盘I/O操作,提高写入性能。
LSM-Tree架构的主要组件和流程包括: 内存表(MemTable)、不变的磁盘表(SSTable)、合并(Merge)过程、压缩(Compaction)、Bloom Filter以及日志(WAL - Write-Ahead Log)
。
-
内存表(MemTable):暂存新写入的数据。
-
不变的磁盘表(SSTable):内存表满后,数据被批量写入到不可变的磁盘表。
-
合并(Merge)过程:定期将多个磁盘表合并,保持磁盘表的数量和大小在可控范围内。
-
压缩(Compaction):合并过程中对数据进行压缩,优化存储空间。
-
Bloom Filter:减少非必要的磁盘读取,快速判断键值是否存在于某个SSTable中。
-
日志(WAL - Write-Ahead Log):保证数据的持久性,在数据写入MemTable的同时写入日志,以便系统崩溃后恢复数据。
优缺点
LSM-Tree架构的优点包括高性能写入、批量数据写入、延迟合并和压缩,这些特点使得它在写密集型应用中表现出色。然而,它也存在一些缺点,如读取操作可能较慢、空间放大以及写放大。尽管如此,LSM-Tree架构因其高效的数据写入性能而在许多应用中得到广泛应用。
LSM在大数据领域的应用
hbase 应用 LSM-tree 架构
Hbase 的架构来体会其架构中基于LSM-tree 的部分特点。 按照WAL的原则,
-
第一步数据首先会写到Hbase的Hlog(相当于commit log)里,
-
第二部再写到Memstore(相当于memtable) 里,
-
第三部数据会冲写到磁盘storeFile(相当于sstable)中。
这样HBase的HRegionServer 就通过LSM-tree 实现了数据文件的生成。
lsm-tree 这种结构非常由利于数据的快速写入(理论上可以接近磁盘顺序写速度)。但读取过程可能不太友好(因为理论上读的时候可能需要同时从memtable和所有磁盘上的sstable 中查询数据,这样显然会对性能做成较大的影响 )为了解决读取的问题,Lsm-tree 采取了以下主要的相关措施。
-
定期将磁盘上小的sstable 合并(通常叫做merge 或compaction 操作)成大的sstable,以减少sstable的数量,并且平时数据的更新删除操作并不会更新原有的数据文件,只会将更新和操作加到当前的数据文件末端,只有再sstable 合并的时候才会真正将重复的操作或更新去重、合并。
-
对每个sstable 使用(bloom filter),以加速对数据在该sstable 的存在性进行判定,从而减少数据的总查询时间。
Apache Druid 应用 LSM-tree 架构
LSM-tree 架构显然比较适合那些数据插入操作远多于数据更新删除操作和读操作的场景,同时Druid 在一开始就是为时序数据场景设计的,而该场景正好符合LSM-tree 的特定,因此Druid 架构便顺理成章的吸取了其思想。
druid 的类LSM-tree 架构中的实时节点(Realtime Node),负责实时消费实时数据,与经典的LSM-tree 架构不同的是,Druid 部提供日志及实行原则.
-
第一步
实时数据首相会被直接加载进实时系欸DNA内存中的对结构缓冲区(相当于 memtable),当条件满足时,缓存区里的数据会被冲写到磁盘上形成一个数据块(segment split),同时实时节点又会立即将新生成的数据块加载到内存的非堆区,因此无论时堆结构缓存区还是非堆区里的数据,都能够被查询节点(Broker Node)查询。实时节点数据块的生成示意图如
-
第二步
实时节点会周期性的将磁盘上同一个时间段内生成的所有数据块合并为一个大的数据块(Segment)。这个过程在实时节点中叫做 Segment merge 操作,也相当于LSM-tree 架构中的数据合并操作。合并好的Segment 会立即被实时节点上传到数据文件存储库(DeepStorage)中
-
第三步
协调节点(Coordinator node) 会知道一个历史节点(Historical NOde) 去文件存储库,将新生成的segment 下载到本地磁盘中,当历史节点 成功加载到新的Segment 后,会通过分布式协调服务(coordinator)在集群中声明其从此刻开始负责该segment 的查询。接下来查询节点会转从该历史节点查询此segement 的数据。
-
第四步
对于一个查询来说,会分成两部分。查询节点会同时从实时节点(少量当前数据)与历史节点(大量历史数据)分别查询,然后做一个结果的整合,最后再返回给用户。druid 的这种架构安排一定程度上借鉴名利查询职责分离模式。 这是druid 不同于Hbase 等LSM -tree 系架构的显著特定。