8、LSM树

news2024/11/27 1:31:19

一、前言

最近在调研NoSQL数据库,发现RocksDB、LevelDB、HBase以及Prometheus等,其底层的存储引擎都是基于LSM树,于是决定花时间彻底吃透LSM树这一数据结构。

不幸的是,在查阅资料学习的过程中,发现网上各种文章汗牛充栋、抄来抄去,不是文不对题就是不知所云。

一气之下决定自己写一篇出来消消气,便有了这篇文章。。。

PS:学了这么多数据结构,LSMTree应该是最年轻的一个,它在1996年被设计出来(属老鼠的),年纪比我还小~

相比于B/B+树或者倒排索引,LSMTree采用了“疯狂到不顾一切”的干啥都磁盘顺序写的方案,赋予了它无与伦比的写吞吐量。

二、LSM树数据结构定义

查阅了一些资料,LSM树并没有一种固定死的实现方式,更多的是一种将:

“磁盘顺序写” + “多个树(状数据结构)” + “冷热(新老)数据分级” + “定期归并” + “非原地更新”这几种特性统一在一起的思想。

为了方便后续的讲解分析,我们尝试先对LSM树做一个定义。

LSM树的定义:

  1. LSM树是一个横跨内存和磁盘的,包含多颗"子树"的一个森林。
  2. LSM树分为Level 0,Level 1,Level 2 ... Level n 多颗子树,其中只有Level 0在内存中,其余Level 1-n在磁盘中。
  3. 内存中的Level 0子树一般采用排序树(红黑树/AVL树)、跳表或者TreeMap等这类有序的数据结构,方便后续顺序写磁盘。
  4. 磁盘中的Level 1-n子树,本质是数据排好序后顺序写到磁盘上的文件,只是叫做树而已。
  5. 每一层的子树都有一个阈值大小,达到阈值后会进行合并,合并结果写入下一层。
  6. 只有内存中数据允许原地更新,磁盘上数据的变更只允许追加写,不做原地更新。

以上6条定义组成了LSM树,如图1所示。

图1 LSM树的组成和定义(狗日的知乎把我高清图片压缩了。。。)

  • 图1中分成了左侧绿色的内存部分和右侧蓝色的磁盘部分(定义1)。
  • 图1左侧绿色的内存部分只包含Level 0树,右侧蓝色的磁盘部分则包含Level 1-n等多棵"树"(定义2)
  • 图1左侧绿色的内存部分中Level 0是一颗二叉排序树(定义3)。注意这里的有序性,该性质决定了LSM树优异的读写性能。
  • 图1右侧蓝色的磁盘部分所包含的Level 1到Level n多颗树,虽然叫做“树”,但本质是按数据key排好序后,顺序写在磁盘上的一个个文件(定义4) ,注意这里再次出现了有序性。
  • 内存中的Level 0树在达到阈值后,会在内存中遍历排好序的Level 0树并顺序写入磁盘的Level 1。同样的,在磁盘中的Level n(n>0)达到阈值时,则会将Level n层的多个文件进行归并,写入Level n+1层。(定义5)
  • 除了内存中的Level 0层做原地更新外,对已写入磁盘上的数据,都采用Append形式的磁盘顺序写,即更新和删除操作并不去修改老数据,只是简单的追加新数据。图1中右侧蓝色的磁盘部分,Level 1和Level 2均包含key为2的数据,同时图1左侧绿色内存中的Level 0树也包含key为2的数据节点。(定义6)

下面我们遵循LSM树的6条定义,通过动图对LSM树的增、删、改、查和归并进行详细分析。

三、插入操作

LSM树的插入较简单,数据无脑往内存中的Level 0排序树丢即可,并不关心该数据是否已经在内存或磁盘中存在。(已经存在该数据的话,则场景转换成更新操作,详见第四部分)

图2展示了,新数据直接插入Level 0树的过程。

图2 LSM树的插入操作示例

如上图2所示,我们依次插入了key=9、1、6的数据,这三个数据均按照key的大小,插入内存里的Level 0排序树中。该操作复杂度为树高log(n),n是Level 0树的数据量,可见代价很低,能实现极高的写吞吐量。

四、删除操作

LSM树的删除操作并不是直接删除数据,而是通过一种叫“墓碑标记”的特殊数据来标识数据的删除。

删除操作分为:待删除数据在内存中、待删除数据在磁盘中 和 该数据根本不存在 三种情况。

3.1 待删除数据在内存中:

如图3所示,展示了待删除数据在内存中的删除过程。我们不能简单地将Level 0树中的黄色节点2删除,而是应该采用墓碑标记将其覆盖(思考题:为什么不能直接删除而是要用墓碑标记覆盖呢)

图3 LSM树删除操作示例——待删除数据在内存中时

3.2 待删除数据在磁盘中:

如图4所示,展示了待删除数据在磁盘上时的删除过程。我们并不去修改磁盘上的数据(理都不理它),而是直接向内存中的Level 0树中插入墓碑标记即可。

图4 LSM树删除操作示例——待删除数据在磁盘中时

3.3 待删除数据根本不存在:

这种情况等价于在内存的Level 0树中新增一条墓碑标记,场景转换为情况3.2的内存中插入墓碑标记操作。

综合看待上述三种情况,发现不论数据有没有、在哪里,删除操作都是等价于向Level 0树中写入墓碑标记。该操作复杂度为树高log(n),代价很低。

五、修改操作

LSM树的修改操作和删除操作很像,也是分为三种情况:待修改数据在内存中、在磁盘中和 该数据根本不存在。

4.1 待修改数据在内存中:

图5 LSM树修改操作示例——待修改数据在内存中时

如图5所示,展示了待修改数据在内存中的操作过程。新的蓝色的key=7的数据,直接定位到内存中Level 0树上黄色的老的key=7的位置,将其覆盖即可。

4.2 待修改数据在磁盘中:

图6 LSM树修改操作示例——待修改数据在磁盘中时

如图6所示,展示了待修改数据在磁盘中的操作过程。LSM树并不会去磁盘中的Level 1树上原地更新老的key=7的数据,而是直接将新的蓝色的节点7插入内存中的Level 0树中。

4.3 该数据根本不存在:

此场景等价于情况b,直接向内存中的Level 0树插入新的数据即可。

综上4.1、4.2、4.3三种情况可以看出,修改操作都是对内存中Level 0进行覆盖/新增操作。该操作复杂度为树高log(n),代价很低。

我们会发现,LSM树的增加、删除、修改(这三个都属于写操作)都是在内存中倒腾,完全没涉及到磁盘操作,所以速度飞快,写吞吐量高的离谱。。。

六、查询操作

LSM树的查询操作会按顺序查找Level 0、Level 1、Level 2 ... Level n 每一颗树,一旦匹配便返回目标数据,不再继续查询。该策略保证了查到的一定是目标key最新版本的数据(有点MVCC的感觉)。

我们来分场景分析:依然分为 待查询数据在内存中 和 待查询数据在磁盘中 两种情况。

5.1 待查询数据在内存中:

如图7所示,展示了待查询数据在内存中时的查询过程。

图7 LSM树查询操作示例——待查询数据在内存中时

沿着内存中已排好序的Level 0树递归向下比较查询,返回目标节点即可。我们注意到磁盘上的Level 1树中同样包括一个key=6的较老的数据。但LSM树查询的时候会按照Level 0、1、2 ... n的顺序查询,一旦查到第一个就返回,因此磁盘上老的key=6的数据没人理它,更不会作为结果被返回。

5.2 待查询数据在磁盘中:

如图8所示,展示了待查询数据在磁盘上时的查询过程。

图8 LSM树查询操作示例——待查询数据在磁盘中时

先查询内存中的Level 0树,没查到便查询磁盘中的Level 1树,还是没查到,于是查询磁盘中的Level 2树,匹配后返回key=6的数据。

综合上述两种情况,我们发现,LSM树的查询操作相对来说代价比较高,需要从Level 0到Level n一直顺序查下去。极端情况是LSM树中不存在该数据,则需要把整个库从Level 0到Level n给扫了一遍,然后返回查无此人(可以通过 布隆过滤器 + 建立稀疏索引 来优化查询操作)。代价大于以B/B+树为基本数据结构的传统RDB存储引擎。

六、合并操作

合并操作是LSM树的核心(毕竟LSM树的名字就叫: 日志结构合并树,直接点名了合并这一操作)

之所以在增、删、改、查这四个基本操作之外还需要合并操作:一是因为内存不是无限大,Level 0树达到阈值时,需要将数据从内存刷到磁盘中,这是合并操作的第一个场景;二是需要对磁盘上达到阈值的顺序文件进行归并,并将归并结果写入下一层,归并过程中会清理重复的数据和被删除的数据(墓碑标记)。我们分别对上述两个场景进行分析:

LSM树

6.1 内存数据写入磁盘的场景:

如图9所示,展示了内存中Level 0树在达到阈值后,归并写入磁盘Level 1树的场景。

图9 LSM树合并操作示例——内存数据写入磁盘

对内存中的Level 0树进行中序遍历,将数据顺序写入磁盘的Level 1层即可,我们可以看到因为Level 0树是已经排好序的,所以写入的Level 1中的新块也是有序的(有序性保证了查询和归并操作的高效)。此时磁盘的Level 1层有两个Block块。

6.2 磁盘中多个块的归并:

如图10所示,该图展示了磁盘中Level 1层达到阈值时,对其包含的两个Block块进行归并,并将归并结果写入Level 2层的过程。

我们注意到key=5和key=7的数据同时存在于较老的Block 1和较新的Block 2中。而归并的过程是保留较新的数据,于是我们看到结果中,key=5和7的数据都是红色的(来自于较新的Block2)。

综上我们可以看到,不论是场景6.1还是场景6.2,由于原始数据都是有序的,因此归并的过程只需要对数据集进行一次扫描即可,复杂度为O(n)。

七、优缺点分析

以上便是对LSM树的增、删、改、查和归并五种核心操作的详细分析。

可以看到LSM树将增、删、改这三种操作都转化为内存insert + 磁盘顺序写(当Level 0满的时候),通过这种方式得到了无与伦比的写吞吐量。

LSM树的查询能力则相对被弱化,相比于B+树的最多3~4次磁盘IO,LSM树则要从Level 0一路查询Level n,极端情况下等于做了全表扫描。(即便做了稀疏索引,也是lg(N0)+lg(N1)+...+lg(Nn)的复杂度,大于B+树的lg(N0+N1+...+Nn)的时间复杂度)。

同时,LSM树只append追加不原地修改的特性引入了归并操作,归并操作涉及到大量的磁盘IO,比较消耗性能,需要合理设置触发该操作的参数。

综上我们可以给出LSM树的优缺点:

优:增、删、改操作飞快,写吞吐量极大。

缺:读操作性能相对被弱化;不擅长区间范围的读操作; 归并操作较耗费资源。

LSMTree的增、删、改、查四种基本操作的时间复杂度分析如下所示:

操作平均代价最坏情况代价
插入11
删除11
修改11
查找lgNlgN

八、总结

以上是对LSM树基本操作以及优缺点的分析,我们可以据此得出LSM树的设计原则:

  1. 先内存再磁盘
  2. 内存原地更新
  3. 磁盘追加更新
  4. 归并保留新值

如果说B/B+树的读写性能基本平衡的话,LSM树的设计原则通过舍弃部分读性能,换取了无与伦比的写性能。该数据结构适合用于写吞吐量远远大于读吞吐量的场景,得到了NoSQL届的喜爱和好评。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/402817.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

浅谈对Promise的理解以及在工作中的应用

浅谈对Promise的理解以及在工作中的应用Promise的概念背景知识JavaScript的同步和异步JavaScript事件循环回调函数进行异步操作解决方案:PromisePromise 在工作中的运用创建PromisePromise封装AJAXPromise链式操作Promise.all()Promise.race()async和await总结Promi…

轻松转换文档:antennahouse/Office Server Document Converter

关于 Office Server 文档转换器 (OSDC)破解版 无需 Microsoft Office 或 Adob​​e 软件即可快速准确地转换文档。 Office Server 文档转换器 (OSDC) 会将您在 Microsoft Office(Word、Excel、PowerPoint)中创建的重要文档转换为高质量的 PDF 或图像格式…

国内32位MCU在电机控制上的应用方案

电机(Electric machinery,俗称“马达”)是依据电磁感应定律,实现电能转换或传递的一种电磁装置,其主要作用是产生驱动转矩,为用电器或各类机械提供动力。电机作为工业世界的动力之源,几乎用于所…

ThinkPHP 6.1 模板篇之布局与继承

本文主要讲述ThinkPHP 6.1版本模板几种布局的方法和如何实现继承, 可以与《ThinkPHP 6.1 模板篇之文件加载》结合来看。 模板布局 布局方式有两种可以实现。 布局方法1 开启配置 默认情况下,不支持模版布局功能,需要在配置文件中开启&…

如何快速通过PMP考试?

我建议准备的最短时间至少一个月,我用了一个半月,我每天集中精力备考大约4个小时,大家可以根据自己的专注力的长短去调节每天的备考时间。 准备5月的,还没备考的,现在开始也来得及。5月没有报名的可以准备8月的&#…

【Linux系统编程】05:多进程

多进程 OVERVIEW多进程一、进程创建1.创建1个子进程2.创建多个子进程二、进程控制1.进程结束2.进程等待3.子进程操作14.子进程操作2三、进程体系1.守护进程2.进程调度程序:一种已经编译好的、存在磁盘中的二进制文件(脚本为普通文件)。进程&a…

超图iServer扩展开发记录Restlet 3

HTTP 请求在达到 REST 应用对象,交给资源实现类处理的时候,先要解析 HTTP 请求中的参数,然后才会进入业务逻辑进行处理。参数解析的工作由参数解析器(Decoder)进行,即可以实现将请求参数转换为 Java 对象。…

qt tcp通讯

TCP 协议(Transmission Control Protocol)全称是传输控制协议是一种面向连接的、可靠的、基于字节流的传输层通信协议。tcp服务端使用QTcpServer、QTcpSocket。tcp客户端使用QTcpSocket1.在工程文件(工程文件.pro)中的第一行添加network 如QT core gui …

WeSpeaker支持C++部署链路

WeSpeaker正式更新C部署链路,推理引擎使用OnnxRuntime,支持从语音中提取Speaker Embedding信息,代码详见WeSpeaker/runtime[1]。 Libtorch和onnx的选择? Speaker Embedding提取任务流程简单,并且声纹模型(如ResNet\E…

前端js学习

1. js入门 1.1 js是弱类型语言 1.2 js使用方式 1.2.1 在script中写 1.2.2 引入js文件 1.2.3 优先级 1.3 js查错方式 1.4 js变量定义 1.4 js数据类型 数据类型英文表示示例数值类型number1.1 1字符串类型string‘a’ ‘abc’ “abc”对象类型object布尔类型booleannumber函数…

包教包会的Node.js

一、简介 1、什么是Node.js 简单的说 Node.js 就是运行在服务端的 JavaScript。 Node.js是一个事件驱动I/O服务端JavaScript环境,基于Google的V8引擎,V8引擎执行Javascript的速度非常快,性能非常好。 2、Node.js有什么用 如果你是一个前…

风起|微软突发声明:始终严格保护并捍卫用户隐私

开放隐私计算 3 月 9 日消息,微软中国今天发布了声明,针对日前国内某些自媒体传播的有关个人用户使用微软消费类产品和服务的误解,特做了相关说明。微软表示,微软始终严格遵守个人隐私保护与数据安全等方面的各项法律法规。微软提…

深眸科技突破革新机器视觉技术,加速实现工业自动化与智能化发展

随着现代生活水平的不断提高,人们对产品的品质需求持续提升,且在智能制造这一大环境下,多数制造企业积极转型,寻求更高效的检测方式。而机器视觉及相关技术的发展,让多数公司通过创新机器视觉应用产品,以及…

面试必会-MySQL篇

1. Mysql查询语句的书写顺序Select [distinct ] <字段名称>from 表1 [ <join类型> join 表2 on <join条件> ]where <where条件>group by <字段>having <having条件>order by <排序字段>limit <起始偏移量,行数>2. Mysql查询语…

vue3使用nextTick

发现nextTick必须放在修改一个响应式数据之后&#xff0c;才会在onUpdated之后被调用&#xff0c;如果nextTick是放在所有对响应式数据修改之前&#xff0c;则nextTick里面的回调函数会在onBeforeUpdate方法执行前就被调用了。可是nextTick必须等到onUpdated执行完成之后执行&a…

Android代码重构系列-02-使用Kotlin协程实现一个支持任务编排的轻量级启动器

前言虽然本文的主题是启动器&#xff0c;但是笔者不打算去写怎么做启动优化&#xff0c;以及怎么实现一个完美的启动器。关于开源的第三方Android启动器已经有很多优秀的轮子了&#xff0c;比如阿里巴巴的alpha&#xff0c;参考 alpha 并改进其部分细节的Anchors&#xff0c;St…

Mybatis框架源码笔记(七)之Mybatis中类型转换模块(TypeHandler)解析

1、JDBC的基本操作回顾 这里使用伪代码概括一下流程: 对应数据库版本的驱动包自行下载加载驱动类 (Class.forName("com.mysql.cj.jdbc.Driver"))创建Connection连接: conn DriverManager.getConnection("jdbc:mysql://数据库IP:port/数据库名称?useUnico…

最新消息:2023年软考高项教材改版!

最新通知&#xff1a;从2023年上半年软考开始信息系统项目管理师考试将依据新版考试大纲进行。 给备考高项的朋友的一些建议&#xff1a; 备考资源&#xff1a; 【腾讯文档】软考各科资料分享 https://docs.qq.com/doc/DTVN1SWtFZHdicUNp 复习方法&#xff1a; 选择题 选择题…

ChatGPT,乌合之众的疯狂

最近ChatGPT有多火爆就不用我说了。公司里&#xff0c;从CEO到技术人员&#xff0c;乃至于门口的保安、食堂的大婶&#xff0c;没有一个不会聊两句ChatGPT的。连我20年未见的小学同学、三线城市警官&#xff0c;都问我这东西能不能给领导写汇报材料。 用不了多久&#xff0c;家…

颠覆推特VS改造推特:什么是去中心化社交的正确姿势?

去年&#xff0c;“钢铁侠”伊隆马斯克收购了全球最大的社交媒体之一——推特。推特成立于2006年&#xff0c;是一个“公民广场”&#xff0c;允许大家公开发表观点和内容。用户可以关注自己喜欢的账号&#xff0c;也可以点赞转发评论他人的推文&#xff0c;中国的微博便是照搬…