这是我参与「第四届青训营 」笔记创作活动的的第14天
一、LSMT与存储引擎介绍
LSMT的原理很简单,本质上就是在SSTable基础上增加了一个MemTable,MemTable顾名思义,就是存放在内存中的数据结构,可以快速实现增删改查,比如红黑树,Skiplist都行。其次,我们还需要一个log文件,和数据库的binlog相当,记录数据发生的变化,用于服务器宕机时找回数据。
查找
当要查找一个元素的时候,会先查找MemTable,因为他在内存中,不需要读文件,如果MemTable中没找到,就去一个一个SSTable来查找,由于SSTable也是顺序存储的,可以用二分法查找,所以查询速度会比较快。
但是,如果SSTable文件数量可能会很多,而且我们必须要顺序查找,所以当SSTable数多时,会影响查找速度。为了解决这个上网呢提,我们可以引入布隆过滤器进行优化:我们对每一个SSTable建立一个布隆过滤器,可以快速地判断元素是否在某一个SSTable中。布隆过滤器判断元素不存在是一定准确的,而判断存在可能会有一个很小的几率失误,但这个失误的几率是可以控制的额,我们可以设置合理的参数,使得失误率足够低。
增删改
除了查找外,增删改都发生在MemTable中,比如当我们要增加一个元素的时候,我们直接增加在Memtable中,而不是写入文件,这样保证了高性能。
修改和删除也一样,如果需要修改的元素刚好在MemTable中,那没什么好说的,我们直接进行修改,那如果不在MemTable中,我们如果先找到,再修改,免不了要做磁盘读写,会大大消耗性能,所以我们还在Memtable中进行操作,我们会插入这个元素,然后标记成修改或者删除。
所以我们可以把增删改这三个操作看成是添加,但这样会带来一个问题,会导致很快Memtable中就积累了大量的数据,而我们的内存资源也是有限的,不能无限增长,为了解决这个问题,需要定期将memtable种的内容存储到磁盘,存储成一个SSTable。这就是为什么要设计SSTable,SSTable是LSMT落盘产生的。
同样,由于我们不断地落盘,同样也会导致SSTable文件数量的增加,如前面分析,SSTable数量多,会影响我们的查询性能,所以不能放任SSTable无限制增加。再加上我们存储了许多修改和删除的信息,我们需要把这些信息落实。为了达成这点,我们需要定期将所有的SSTable合并,在合并的过程中,完成数据的删除及修改工作。换句话说,之前的删除、修改只是被记录下来,直到合并的时候才真正执行。
整个的归并过程并不难,类似于归并排序中的归并操作,只是我们需要加上状态的判断。
二、LSMT存储引擎的优势与实现
核心思想的核心就是放弃部分读能力,换取写入的最大化能力。LSM Tree ,这个概念就是结构化合并树的意思,它的核心思路其实非常简单,就是假定内存足够大,因此不需要每次有数据更新就必须将数据写入到磁盘中,而可以先将最新的数据驻留在内存中,等到积累到最后多之后,再使用归并排序的方式将内存内的数据合并追加到磁盘队尾(因为所有待排序的树都是有序的,可以通过合并排序的方式快速合并到一起)。
日志结构的合并树(LSM-tree)是一种基于硬盘的数据结构,与B-tree相比,能显著地减少硬盘磁盘臂的开销,并能在较长的时间提供对文件的高速插入(删除)。然而LSM-tree在某些情况下,特别是在查询需要快速响应时性能不佳。通常LSM-tree适用于索引插入比检索更频繁的应用系统。Bigtable在提供Tablet服务时,使用GFS来存储日志和SSTable,而GFS的设计初衷就是希望通过添加新数据的方式而不是通过重写旧数据的方式来修改文件。而LSM-tree通过滚动合并和多页块的方法推迟和批量进行索引更新,充分利用内存来存储近期或常用数据以降低查找代价,利用硬盘来存储不常用数据以减少存储代价。
磁盘的技术特性:对磁盘来说,能够最大化的发挥磁盘技术特性的使用方式是:一次性的读取或写入固定大小的一块数据,并尽可能的减少随机寻道这个操作的次数。
三、 LSM Tree优化方式:
a、Bloom filter: 就是个带随即概率的bitmap,可以快速的告诉你,某一个小的有序结构里有没有指定的那个数据的。于是就可以不用二分查找,而只需简单的计算几次就能知道数据是否在某个小集合里啦。效率得到了提升,但付出的是空间代价。
b、compact:小树合并为大树:因为小树他性能有问题,所以要有个进程不断地将小树合并到大树上,这样大部分的老数据查询也可以直接使用log2N的方式找到,不需要再进行(N/m)*log2n的查询了