LSM(Log-Structured Merge Tree)

发布于:2022-12-24 ⋅ 阅读:(532) ⋅ 点赞:(0)

一、什么是LSM Tree

LSM Tree全称日志结构合并树Log-Structured Merge Tree)。对于存储介质为磁盘固态盘的数据库,长期以来主流使用B+树这种索引结构来实现快速数据查找。当数据量不太大时,B+树读写性能表现非常好。但是在海量数据情况下,B+树越来越高,由于B+树更新和删除数据时需要沿着B+树逐层进行页分裂页合并,严重影响数据写入性能。为了解决这种情况,google在论文《Bigtable: A Distributed Storage System for Structured Data》中介绍了一种新的数据组织结构LSM Tree(Log-Structured Merge Tree),LSM Tree是其中着重介绍的一种新的分布式存储系统的一个理论模型。LSM Tree的存储架构设计在机械盘时代大方异彩,同时也是一个把顺序写发挥到极致的设计架构,核心之一是log文件。当前比较流行的NoSQL数据库,如Cassandra、RocksDB、HBase、LevelDB等,newSQL数据库,如TIDB,都是使用LSM Tree来组织磁盘数据的。

二、基本原理简述

LSM Tree是一个分层有序针对块存储设备HDDSSD)特点而设计的数据存储结构。他的核心理论基础还是磁盘的顺序写速度比随机写速度快非常多,即使是SSD,由于块擦除和垃圾回收的影响,顺序写速度还是比随机写速度快很多。
在这里插入图片描述

2.1 SSTable和Level

LSM Tree将存储数据切分为一系列的SSTableSorted String Table),并将SSTable分为 Level 0 - Level N。每个SSTable内的数据都是有序的任意字节组,并且SSTable一旦写入磁盘中就像日志一样无法修改。对于LSM Tree若需要修改或者删除数据并不是直接对旧数据进行操作,而是将新数据写入新的SSTable中。若需删除数据则是写一个相应数据的删除标记的记录到一个新的SSTable中。依照这种方法也确保了LSM Tree写数据时对磁盘的操作都是顺序块写入操作,而没有随机写操作。

LSM Tree这种独特的写入方式,导致在查找数据的时候,LSM Tree 不能像B+ Tree那样在一个统一的索引表中进行查找,而是从最新的SSTable老的SSTable中依次进行查找。如果在新的SSTable中找到了需要查找的数据或者相应的删除标记,则直接返回查找结果;若没找到,再到老的SSTable中进行查找,直到老的SSTable查找完。为了提高查找效率,LSM Tree对SSTable进行分层、有序组织,就是将SSTable组织成多层,同一层可以有多个SSTable,并且每个SSTable内的数据是有序的,前一个SSTable的最大数据值小于后一个SSTable的最小数据值(实际情况更加复杂),以达到提升在同一层SSTable的查询效率。同时,LSM Tree会将多个SSTable合并(Compact)为一个新的SSTable,这样可以减少SSTable的数量,同时把修改前的数据或删除的数据真正从SSTable中删除,减少SSTable的大小(这就是LSM中Merge(合并)的由来),对提高查找性能起到了极其重要的作用。

2.2 分布式存储系统(BigTable)

2.2.1 数据模型

BigTable本质上是一个为稀疏结构化数据设计的分布式多维排序Map。这里的“稀疏”指的是对于某一个结构化对象,有大量属性缺失的,且多个对象之间缺失的属性分布也很分散。Map的Key由三个部分组成,分别是Row、Column Family:Column、Timestamp。

  • Row(行)
    行是结构化对象的一个实例。在BigTable中行是根据Key用字典序排序存储的。BigTable支持单行级别的原子更新操作,客户端无须在并行调用场景关系行操作的原子性。
  • Column Family(列簇):Column(列)
    列簇是多个列的集合。一般情况下,存储在同一个列簇中的数据具有同样的类型,并且会压缩在一起。列簇还是访问权限控制最小单元
  • Timestamp(时间/版本)
    Timestamp是一个64-bit的时间版本号。BigTable可以存储同一份数据的多个版本,并支持按照版本进行访问。Timestamp可以由客服端自行指定,或由BigTable实时生成。

2.2.2 组件

  • Tablet
    Tablet是数据调度最小单位,由一个Key Range组成,包含了这个Key Range中的所有数据。每一行Key又包含了多个列簇,同一个列簇内的数据被压缩并存放在SSTable中。
    SSTable是Google内部的持久化KV存储结构,将数据按Key排序存储实现高效检索。SSTable被创建过后,不可对其内容进行更改,属于“只读结构”。SSTable内部由多个Block组成,每个Block默认大小为64KB,在SSTable的最后存放Block的索引信息。
    使用SSTable时,首先将Block索引信息加载到内存中;检索时,首先通过二分查找检索Block索引确定Block,再从磁盘读取该Block的数据。这样设计可以更好的利用磁盘的顺序读取特性,提高查找性能。同时SSTable也可以直接映射内存中。
    在这里插入图片描述
  • MemTable
    前面介绍到的SSTable是不可变的,若需对BigTable实现增删改操作就要用到MemTable。
    MemTable是存放在内存中的数据结构,当发生变更操作时,首先对MemTable进行写入;同样,读取数据时,就同时读取SSTable和MemTable,将结果合并。随着数据持续写入,MemTable不断增长,被写满后,会重新创建一个新的MemTable老的MemTable锁定,然后Merge(合并)到新的SSTable中。
    由于MemTable存放在内存的缘故,当机器发生故障进程突然被kill时,MemTable中的数据会丢失。为了保证系统的稳定高可用,BigTable通过磁盘Log记录了所有的Commit操作,当发生数据丢失时,可以通过Log和SSTable的时间戳,及时恢复MemTable中的数据。
    在这里插入图片描述

三、LSM Tree框架图

在这里插入图片描述
从图中可知,LSM Tree的数据主要由Memory(内存)和Disk(磁盘)组成。Memory主要由一个MemTable和一个或多个Immutable MemTable组成。Disk主要由分布在多级LevelSSTable组成。Level级数越表示处于该Level的SSTable越,Level级数越表示处于该Level的SSTable越,最大级数(Level N)大小由系统设定。在此处Disk中最小的级数是Level 0,也会有系统把Memory中的Immutable MemTable定义为Level 0,即Disk中的数据从Level 1开始,这只是Level定义不同,不影响系统的工作流程和对系统的理解。

WAL(Write Ahead LOG)严格来说不是LSM Tree结构的一部分,但是实际系统中,WAL是数据库不可或缺的一部分,WAL的结构和作用跟其他数据库一样,是一个只能在尾部以Append Only方式追加记录的日志结构文件,他用来当系统崩溃重启时重放操作,使MemTable和Immuntable MemTabel中未持久化到磁盘中的数据不会丢失,这是通过LOG保证存储在内存中数据不丢失的一个方法。

MemTable往往是一个跳表(Skip List)组织的有序数据结构(也可以是有序数组或者红黑树二叉搜索树),跳表既支持高效的动态插入数据,对数据进行排序,也支持高效的对数据进行精确查找范围查找

SSTable一般由一组数据block和一组元数据block组成。元数据block存储了SSTable数据block的描述信息,如索引BloomFilter(布隆过滤器)、压缩统计等信息。因为SSTable是不可更改的,且是有序的,索引往往采用二分数组结构就行了。为了节省存储空间以及提高数据块block的读写效率,可以对数据block进行压缩。

四、总结

  • LSM Tree以牺牲部分读取性能为代价提高写入性能,通常适用于类似时序数据库这类写多读少的场景。
  • LSM Tree主要利用磁盘顺序访问要比随机访问快很多的思想实现提高写入性能的特点。
  • LSM Tree是一种分层的有序的基于磁盘数据结构。设计思想是先将数据的操作存到内存中,并由LOG记录,当内存的MemTable达到阈值时就通过归并排序方式合并放到磁盘队尾
  • LSM Tree提升读性能的优化策略主要是使用布隆过滤器多路归并机制等。

参考:

经典论文研读:《Bigtable: A Distributed Storage System for Structured Data》
LSM Tree原理详解
LSM-Tree介绍

本文含有隐藏内容,请 开通VIP 后查看