下午听了关于MyRocks-PASV的研究讲座,很有意思所以学习了一下LSM树的一些简单的底层原理。现在整理一下


我们都知道目前Key:Value型的数据库普遍较之关系型数据库有着更好的表现,为什么会有这样的一个差异呢?关键就在于存储形式和读写机制的不同。Key:Value型数据库可以通过LSM Tree(Log-Structured-Merge-Tree)来进行存储,而以MySQL为代表的关系型数据库则以B+树的形式来组织聚簇索引文件和二级索引文件来进行存储。二者的实现机制由于是否顺序写产生了很大的差别。

LSM树的具体机制

LSM树其实并不是一个真正意义上的树形结构,其核心特点是利用顺序写来提高写性能,顺序写很好理解。举个很多人都背过的例子就是MySQL的InnoDB引擎在写入内容时会首先通过WAL机制,先将改动写进磁盘中的redo log这个物理日志中,物理日志记录的是对某表的某数据页某偏移量处做了某更新,然后再找机会把redo log中的内容刷进磁盘中真正存储数据的地方。这么做的好处就是因为写入物理日志只需要接着之前写到的位置往下写就行,不需要随机存取磁盘内容,可以进行的相对快速。

但问题就是,MySQL终究还是要把redo log中的操作写入磁盘中真正存储数据的地方,而这个动作就限制了关系型数据库的性能发挥。而LSM树就是直接将WAL机制作为存储数据的主要机制来实现数据库的存取。

如图所示,LSM树有以下三个重要组成部分

  • MemTable
  • Immutable MemTable
  • SS Table

MemTable

MemTable是在内存中的数据结构,用于保存最近更新的数据操作,这里会按照Key有序地组织这些数据。至于具体如何组织这些数据以使其按照Key有序,LSM树并没有做出相应的规定,可以自行实现。

要注意的是因为数据暂时保存在内存中,那么如果断电了就会存在丢失数据的风险,因此这里还是会跟InnoDB一样通过WAL机制来写入磁盘,以保证数据不会因为崩溃或断电而丢失。

Immutable MemTable

当MemTable存储的数据达到阈值后,就会将该Memtable就地转化成Immutable MemTable。Immutable MemTable是将转MemTable变为SSTable的一种中间状态。你可以理解其为一个暂存文件,该文件不再继续写入,而是等待刷入磁盘的SSTable中。之后的写入工作则由一个新创建的MemTable处理。

SSTable(Sorted String Table)

其本质是有序键值对的集合文件,是LSM树在磁盘中的数据结构,我们可以建立key的索引来加快查找。

重点来了,LSM树会将所有的数据插入、修改、删除等操作记录(注意是操作记录)保存在内存之中,当此类操作达到一定的数据量后,再批量地顺序写入到磁盘当中。注意,这与B+树不同,B+树数据的更新会直接在原数据所在处修改对应的值,但是LSM数的数据更新是日志式的,就跟上面说的WAL机制的redo log一样,一条数据更新是直接将更新记录写进log的最后来完成的。而这样设计的目的就是为了顺序写,我们只需要不断地将Immutable MemTable刷入磁盘进行持久化存储即可,不用去修改之前的SSTable中的key,也就保证了顺序写,提升了效率。

不过不断地向后写也就意味着,在不同的SSTable中,可能存在相同Key的记录,显然最新的那条记录才是真实的。那么这样设计的虽然大大提高了写性能,但同时也会带来一些问题:

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

Compact策略

讲到SSTable,我们可以看到这里从MemTable到SSTable一路下来全是顺序写的,问题是磁盘容量并不是无限的,何况SSTable中实际上的真实数据只有最新的那一条,所以如何对SSTable进行Compact来释放空间是很重要的。

Compact释放空间的策略讲到底就是围绕着三大性能的权衡策略。即在以下三个问题中,我们必须至少接受其中之一:

  • 读放大:读取数据时实际读取的数据量大于真正的数据量。

    • 例如在LSM树中需要先在MemTable查看当前key是否存在,不存在继续从SSTable中寻找。
  • 写放大:写入数据时实际写入的数据量大于真正的数据量。
    • 例如在LSM树中写入时可能触发Compact操作,导致实际写入的数据量远大于该key的数据量。
  • 空间放大:数据实际占用的磁盘空间比数据的真正大小更多。
    • 上面提到的冗余存储,对于一个key来说,只有最新的那条记录是有效的,而之前的记录都是可以被清理回收的。

size-tiered 策略

简单来说就是把SSTable分层,限制各层的SSTable数量,并且要求每一层的SSTable的大小都要相近,注意不是相同。当上层SSTable过多时,就将多出来的SSTable合并,作为一个更大的SSTable存入下一层。

可以看出,当层数达到一定数量时,最底层的单个SSTable的大小会变得非常大。而且这种策略会导致空间放大严重。因为即使对于同一层的SSTable,每个key的记录是可能存在多份的,只有当该层的SSTable执行compact操作才会消除这些key的冗余记录,那么积累到整个结构中,冗余的记录占比可想而知。

leveled 策略

leveled策略也是采用分层的思想,与size-tiered策略不同的地方在于,leveled策略会将每一层切分成多个大小相近的SSTable,并且保证这些SSTable是这一层是全局有序的,而这就意味着一个key在每一层至多只有1条记录,不存在冗余记录。

Leveled策略是通过合并策略来保证每一层的SSTable全局有序的。具体实现方法为当某一层总大小超过限制,那么选择该层中与下一层存在交集的SSTable文件进行合并并放入下一层,重复这个操作直到该层大小恢复到限制以内为止。并且,多个不相干的合并是可以并发进行的,这大大提高了效率。

这种策略极大缓解了空间放大的问题,但是代价是写放大问题更加突出。在最坏的情况下,如果该层某个SSTable的key的范围跨度非常大,覆盖了下一层所有key的范围,那么进行Compact时将涉及下一层的全部数据。

不过这里只是简单的聊了一下这些机制,具体使用LSM树进行存储的那些应用中,基本都对它们进行了进一步的优化。这里不再细说

基于LSM树的存储机制简述的更多相关文章

  1. HBase LSM树存储引擎详解

    1.前提 讲LSM树之前,需要提下三种基本的存储引擎,这样才能清楚LSM树的由来: 哈希存储引擎. B树存储引擎. LSM树(Log-Structured Merge Tree)存储引擎. 2. 哈希 ...

  2. 面对key数量多和区间查询低效问题:Hash索引趴窝,LSM树申请出场

    摘要:Hash索引有两个明显的限制:(1)当key的数量很多时,维护Hash索引会给内存带来很大的压力:(2)区间查询很低效.如何对这两个限制进行优化呢?这就轮到本文介绍的主角,LSM树,出场了. 我 ...

  3. LSM树由来、设计思想以及应用到HBase的索引

    讲LSM树之前,需要提下三种基本的存储引擎,这样才能清楚LSM树的由来: 哈希存储引擎  是哈希表的持久化实现,支持增.删.改以及随机读取操作,但不支持顺序扫描,对应的存储系统为key-value存储 ...

  4. LSM树由来、设计思想以及应用到HBase的索引(转)

    转自: http://www.cnblogs.com/yanghuahui/p/3483754.html 讲LSM树之前,需要提下三种基本的存储引擎,这样才能清楚LSM树的由来: 哈希存储引擎  是哈 ...

  5. 为什么选择b+树作为存储引擎索引结构

    为什么选择b+树作为存储引擎索引结构 在数据库或者存储的世界里,存储引擎的角色一直处于核心位置.往简单了说,存储引擎主要负责数据如何读写.往复杂了说,怎么快速.高效的完成数据的读写,一直是存储引擎要解 ...

  6. LSM树以及在hbase中的应用

    转自:http://www.cnblogs.com/yanghuahui/p/3483754.html 讲LSM树之前,需要提下三种基本的存储引擎,这样才能清楚LSM树的由来: 哈希存储引擎  是哈希 ...

  7. 17-看图理解数据结构与算法系列(NoSQL存储-LSM树)

    关于LSM树 LSM树,即日志结构合并树(Log-Structured Merge-Tree).其实它并不属于一个具体的数据结构,它更多是一种数据结构的设计思想.大多NoSQL数据库核心思想都是基于L ...

  8. 看图轻松理解数据结构与算法系列(NoSQL存储-LSM树) - 全文

    <看图轻松理解数据结构和算法>,主要使用图片来描述常见的数据结构和算法,轻松阅读并理解掌握.本系列包括各种堆.各种队列.各种列表.各种树.各种图.各种排序等等几十篇的样子. 关于LSM树 ...

  9. MongoDB索引存储BTree与LSM树(转载)

    1.为什么 MongoDB 使用B-树,而不是B+树 MongoDB 是一种 nosql,也存储在磁盘上,被设计用在数据模型简单,性能要求高的场合.性能要求高,我们看B-树与B+树的区别: B+树内节 ...

  10. 【转帖】LSM树 和 TSM存储引擎 简介

    LSM树 和 TSM存储引擎 简介 2019-03-08 11:45:23 长烟慢慢 阅读数 461  收藏 更多 分类专栏: 时序数据库   版权声明:本文为博主原创文章,遵循CC 4.0 BY-S ...

随机推荐

  1. 使用『jQuery』『原生js』制作一个选项卡盒子 —— { }

    效果 HTML 部分 <body> <div id="main-box"> <div id="left-nav"></ ...

  2. 水晶报表导出pdf文件

    /// <summary> /// 导出pdf文件 /// </summary> /// <param name="mjsReport">报表文 ...

  3. Codeforces Round #821(Div.2) (A-C) 题解

    Codeforces Round #821(Div.2) (A-C) A.Consecutive Sum 大致题意 给定一组共 n 个数据 ,如果俩个数的下标在 mod k 意义下同余,则可以交换a[ ...

  4. 使用 Docker 安装 Elastic Stack 8.0 并开始使用

    文章转载自:https://mp.weixin.qq.com/s/fLnIzbbqYfILS6uCvGctXw 运行 Elasticsearch docker network create elast ...

  5. Elasticsearch: Ngrams, edge ngrams, and shingles

    Ngrams和edge ngrams是在Elasticsearch中标记文本的两种更独特的方式. Ngrams是一种将一个标记分成一个单词的每个部分的多个子字符的方法. ngram和edge ngra ...

  6. shell脚本中执行source命令不生效的解决办法

    一个shell脚本文件中有一个source命令,使用bash a.sh命令执行后source命令进行验证没有生效. 这是因为在shell脚本中执行source会看到效果,但是shell脚本执行完后再次 ...

  7. Pod的dns记录怎么组成的

    Pod的dns记录怎么组成的 <Pod Name>.<service name>.<namespace name>.svc.cluster.local Pod的Na ...

  8. 2_JDBC

    一. 引言 1.1 如何操作数据库 使用客户端工具访问数据库, 需要手工建立连接, 输入用户名和密码登陆, 编写SQL语句, 点击执行, 查看操作结果(结果集或受行数影响) 1.2 实际开发中, 会采 ...

  9. Java问题之超过数值表示范围(例如64位)结果是什么 (阶乘)

    关于老师在课上所提及的这个问题 我做了验证 截图如下 只是一个简单的计算阶乘的代码 在运行时得到了如下结果 可以看到,对于部分数字如果超出范围会从64位处自动截断,而这时由于是二进制表示,首位默认是符 ...

  10. .Net WebApi 中的 FromBody FromForm FromQuery FromHeader FromRoute

    在日常后端Api开发中,我们跟前端的沟通中,通常需要协商好入参的数据类型,和参数是通过什么方式存在于请求中的,是表单(form).请求体(body).地址栏参数(query).还是说通过请求头(hea ...