Log Structured Merge Trees(LSM) 原理(LSM 算法的原理是什么?)

2023-11-07

十年前,谷歌发表了 “BigTable” 的论文,论文中很多很酷的方面之一就是它所使用的文件组织方式,这个方法更一般的名字叫 Log Structured-Merge Tree。

LSM是当前被用在许多产品的文件结构策略:HBase, Cassandra, LevelDB, SQLite,甚至在mangodb3.0中也带了一个可选的LSM引擎(Wired Tiger 实现的)。

LSM 有趣的地方是他抛弃了大多数数据库所使用的传统文件组织方法,实际上,当你第一次看它是违反直觉的。

背景知识

简单的说,LSM被设计来提供比传统的B+树或者ISAM更好的写操作吞吐量,通过消去随机的本地更新操作来达到这个目标。

那么为什么这是一个好的方法呢?这个问题的本质还是磁盘随机操作慢,顺序读写快的老问题。这二种操作存在巨大的差距,无论是磁盘还是SSD。

thoughput of two op

上图很好的说明了这一点,他们展现了一些反直觉的事实,顺序读写磁盘(不管是SATA还是SSD)快于随机读写主存,而且快至少三个数量级。这说明我们要避免随机读写,最好设计成顺序读写。

所以,让我们想想,如果我们对写操作的吞吐量敏感,我们最好怎么做?一个好的办法是简单的将数据添加到文件。这个策略经常被使用在日志或者堆文件,因为他们是完全顺序的,所以可以提供非常好的写操作性能,大约等于磁盘的理论速度,也就是200~300 MB/s。

因为简单和高效,基于日志的策略在大数据之间越来越流行,同时他们也有一些缺点,从日志文件中读一些数据将会比写操作需要更多的时间,需要倒序扫描,直接找到所需的内容。

这说明日志仅仅适用于一些简单的场景:1. 数据是被整体访问,像大部分数据库的WAL(write-ahead log) 2. 知道明确的offset,比如在Kafka中。

所以,我们需要更多的日志来为更复杂的读场景(比如按key或者range)提供高效的性能,这儿有4个方法可以完成这个,它们分别是:

  1. 二分查找: 将文件数据有序保存,使用二分查找来完成特定key的查找。
  2. 哈希:用哈希将数据分割为不同的bucket
  3. B+树:使用B+树 或者 ISAM 等方法,可以减少外部文件的读取
  4. 外部文件: 将数据保存为日志,并创建一个hash或者查找树映射相应的文件。

所有的方法都可以有效的提高了读操作的性能(最少提供了O(log(n)) ),但是,却丢失了日志文件超好的写性能。上面这些方法,都强加了总体的结构信息在数据上,数据被按照特定的方式放置,所以可以很快的找到特定的数据,但是却对写操作不友善,让写操作性能下降。

更糟糕的是,当我们需要更新hash或者B+树的结构时,需要同时更新文件系统中特定的部分,这就是上面说的比较慢的随机读写操作。这种随机的操作要尽量减少

所以这就是 LSM 被发明的原理, LSM 使用一种不同于上述四种的方法,保持了日志文件写性能,以及微小的读操作性能损失。本质上就是让所有的操作顺序化,而不是像散弹枪一样随机读写。

很多树结构可以不用 update-in-place,最流行就是 append-only Btree,也称为 Copy-On-Write Tree。他们通过顺序的在文件末尾重复写对结构来实现写操作,之前的树结构的相关部分,包括最顶层结点都会变成孤结点。尽管通过这种方法避免了本地更新,但是因为每个写操作都要重写树结构,放大了写操作,降低了写性能。

The Base LSM Algorithm

从概念上说,最基本的LSM是很简单的 。将之前使用一个大的查找结构(造成随机读写,影响写性能),变换为将写操作顺序的保存到一些相似的有序文件(也就是sstable)中。所以每个文件包 含短时间内的一些改动。因为文件是有序的,所以之后查找也会很快。文件是不可修改的,他们永远不会被更新,新的更新操作只会写到新的文件中。读操作检查很 有的文件。通过周期性的合并这些文件来减少文件个数。

basic lsm
让我们更具体的看看,当一些更新操作到达时,他们会被写到内存缓存(也就是memtable)中,memtable使用树结构来保持key的有序,在大部 分的实现中,memtable会通过写WAL的方式备份到磁盘,用来恢复数据,防止数据丢失。当memtable数据达到一定规模时会被刷新到磁盘上的一 个新文件,重要的是系统只做了顺序磁盘读写,因为没有文件被编辑,新的内容或者修改只用简单的生成新的文件。

所以越多的数据存储到系统中,就会有越多的不可修改的,顺序的sstable文件被创建,它们代表了小的,按时间顺序的修改。

因为比较旧的文件不会被更新,重复的纪录只会通过创建新的纪录来覆盖,这也就产生了一些冗余的数据。

所以系统会周期的执行合并操作(compaction)。 合并操作选择一些文件,并把他们合并到一起,移除重复的更新或者删除纪录,同时也会删除上述的冗余。更重要的是,通过减少文件个数的增长,保证读操作的性 能。因为sstable文件都是有序结构的,所以合并操作也是非常高效的。

当一个读操作请求时,系统首先检查内存数据(memtable),如果没有找到这个key,就会逆序的一个一个检查sstable文件,直到key 被找到。因为每个sstable都是有序的,所以查找比较高效(O(logN)),但是读操作会变的越来越慢随着sstable的个数增加,因为每一个 sstable都要被检查。(O(K log N), K为sstable个数, N 为sstable平均大小)。

所以,读操作比其它本地更新的结构慢,幸运的是,有一些技巧可以提高性能。最基本的的方法就是页缓存(也就是leveldb的 TableCache,将sstable按照LRU缓存在内存中)在内存中,减少二分查找的消耗。LevelDB 和 BigTable 是将 block-index 保存在文件尾部,这样查找就只要一次IO操作,如果block-index在内存中。一些其它的系统则实现了更复杂的索引方法。

即使有每个文件的索引,随着文件个数增多,读操作仍然很慢。通过周期的合并文件,来保持文件的个数,因些读操作的性能在可接收的范围内。即便有了合 并操作,读操作仍然会访问大量的文件,大部分的实现通过布隆过滤器来避免大量的读文件操作,布隆过滤器是一种高效的方法来判断一个sstable中是否包 含一个特定的key。(如果bloom说一个key不存在,就一定不存在,而当bloom说一个文件存在是,可能是不存在的,只是通过概率来保证)

所有的写操作都被分批处理,只写到顺序块上。另外,合并操作的周期操作会对IO有影响,读操作有可能会访问大量的文件(散乱的读)。这简化了算法工 作的方法,我们交换了读和写的随机IO。这种折衷很有意义,我们可以通过软件实现的技巧像布隆过滤器或者硬件(大文件cache)来优化读性能。
read

Basic Compaction

为了保持LSM的读操作相对较快,维护并减少sstable文件的个数是很重要的,所以让我们更深入的看一下合并操作。这个过程有一点儿像一般垃圾回收算法。

当一定数量的sstable文件被创建,例如有5个sstable,每一个有10行,他们被合并为一个50行的文件(或者更少的行数)。这个过程一 直持续着,当更多的有10行的sstable文件被创建,当产生5个文件时,它们就被合并到50行的文件。最终会有5个50行的文件,这时会将这5个50 行的文件合并成一个250行的文件。这个过程不停的创建更大的文件。像下图:
compaction

上述的方案有一个问题,就是大量的文件被创建,在最坏的情况下,所有的文件都要搜索。

Levelled Compaction

更新的实现,像 LevelDB 和 Cassandra解决这个问题的方法是:实现了一个分层的,而不是根据文件大小来执行合并操作。这个方法可以减少在最坏情况下需要检索的文件个数,同时也减少了一次合并操作的影响。

按层合并的策略相对于上述的按文件大小合并的策略有二个关键的不同:

  1. 每一层可以维护指定的文件个数,同时保证不让key重叠。也就是说把key分区到不同的文件。因此在一层查找一个key,只用查找一个文件。第一层是特殊情况,不满足上述条件,key可以分布在多个文件中。
  2. 每次,文件只会被合并到上一层的一个文件。当一层的文件数满足特定个数时,一个文件会被选出并合并到上一层。这明显不同与另一种合并方式:一些相近大小的文件被合并为一个大文件。

这些改变表明按层合并的策略减小了合并操作的影响,同时减少了空间需求。除此之外,它也有更好的读性能。但是对于大多数场景,总体的IO次数变的更多,一些更简单的写场景不适用。

总结

所以, LSM 是日志和传统的单文件索引(B+ tree,Hash Index)的中立,他提供一个机制来管理更小的独立的索引文件(sstable)。

通过管理一组索引文件而不是单一的索引文件,LSM 将B+树等结构昂贵的随机IO变的更快,而代价就是读操作要处理大量的索引文件(sstable)而不是一个,另外还是一些IO被合并操作消耗。

如果还有不明白的,这还有一些其它的好的介绍。 here and here

关于 LSM 的一些思考

为什么 LSM 会比传统单个树结构有更好的性能?

我们看到LSM有更好的写性能,同时LSM还有其它一些好处。 sstable文件是不可修改的,这让对他们的锁操作非常简单。一般来说,唯一的竞争资源就是 memtable,相对来说需要相对复杂的锁机制来管理在不同的级别。

所以最后的问题很可能是以写为导向的压力预期如何。如果你对LSM带来的写性能的提高很敏感,这将会很重要。大型互联网企业似乎很看中这个问题。 Yahoo 提出因为事件日志的增加和手机数据的增加,工作场景为从 read-heavy 到 read-write。。许多传统数据库产品似乎更青睐读优化文件结构。

因为可用的内存的增加,通过操作系统提供的大文件缓存,读操作自然会被优化。写性能(内存不可提高)因此变成了主要的关注点,所以采取其它的方法,硬件提升为读性能做的更多,相对于写来说。因此选择一个写优化的文件结构很有意义。

理所当然的,LSM的实现,像LevelDB和Cassandra提供了更好的写性能,相对于单树结构的策略。

Beyond Levelled LSM

这有更多的工作在LSM上, Yahoo开发了一个系统叫作 Pnuts, 组合了LSM与B树,提供了更好的性能。我没有看到这个算法的开放的实现。 IBM和Google也实现了这个算法。也有相关的策略通过相似的属性,但是是通过维护一个拱形的结构。如 Fractal Trees, Stratified Trees.

这当然是一个选择,数据库利用大量的配置,越来越多的数据库为不同的工作场景提供插件式引擎。 Parquet 是一个流行的HDFS的替代,在很多相对的文面做的好很(通过一个列格式提高性能)。MySQL有一个存储抽象,支持大量的存储引擎的插件,例如 Toku (使用 fractal tree based index)。
Mongo3.0 则包含了支持B+和LSM的 Wired Tiger引擎。许多关系数据库可以配置索引结构,使用不同的文件格式。

考虑被使用的硬件,昂贵的SSD,像FusionIO有更好的随机写性能,这适合本地更新的策略方法。更便宜的SSD和机械盘则更适合LSM。

延伸阅读

  • There is a nice introductory post here.
  • The LSM description in this paper is great and it also discusses interesting extensions.
  • These three posts provide a holistic coverage of the algorithm: herehere and here.
  • The original Log Structured Merge Tree paper here. It is a little hard to follow in my opinion.
  • The Big Table paper here is excellent.
  • LSM vs Fractal Trees on High Scalability.
  • Recent work on Diff-Index which builds on the LSM concept.
  • Jay on SSDs and the benefits of LSM

来自:http://lcblog.sinaapp.com/?p=223

扩展阅读

用于JVM的高性能持久LSM key-value存储库:HeftyDB
Kudu:支持快速分析的新型Hadoop存储系统
Go语言的嵌入式key/value数据库:bolt
HBase中的备份和故障恢复方法 
谷歌三大核心技术(三)Google_BigTable中文版 

为您推荐

谷歌三大核心技术(三)Google_BigTable中文版 
开源大数据处理工具汇总(下)
H5 缓存机制浅析 移动端 Web 加载性能优化
Cassandra研究报告

开源大数据处理系统/工具大全





http://www.open-open.com/lib/view/open1424916275249.html


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Log Structured Merge Trees(LSM) 原理(LSM 算法的原理是什么?) 的相关文章

  • 一文彻底搞懂leveldb架构

    leveldb leveldb是一个写性能十分优秀的存储引擎 xff0c 是典型的LSM tree的实现 LSM的核心思想是为了换取最大的写性能而放弃掉部分读性能 那么 xff0c 为什么leveldb写性能高 xff1f 简单来说它就是尽
  • leveldb之log文件

    leveldb之log文件 1 log文件在LevelDb中的主要作用是系统故障恢复时 xff0c 能够保证不会丢失数据 因为在将记录写入内存的Memtable之前 xff0c 会先写入Log文件 xff0c 这样即使系统发生故障 xff0
  • LevelDB源码分析之从Put说起

    之前分享的文章leveldb实现原理分析详细描述了LevelDB的实现原理 xff0c 本文从Put接口来看下leveldb数据写流程的源码实现 LevelDB的读写接口在类DB中定义 xff08 leveldb db h xff09 xf
  • leveldb之log文件

    leveldb之log文件 1 log文件在LevelDb中的主要作用是系统故障恢复时 xff0c 能够保证不会丢失数据 因为在将记录写入内存的Memtable之前 xff0c 会先写入Log文件 xff0c 这样即使系统发生故障 xff0
  • 【数据库】Redis和RocksDB、levelDB的区别

    区别 Redis 是一个服务 xff0c 独立的进程 xff0c 用户的程序需要与它建立连接才能向它发请求 xff0c 读写数据 RocksDB 和LevelDB 是一个库 xff0c 嵌入在用户的程序中 xff0c 用户程序直接调用接口读
  • leveldb源码分析--SSTable之Compaction 详解

    http www cnblogs com KevinT p 3819134 html leveldb源码分析 SSTable之Compaction 对于compaction是leveldb中体量最大的一部分 也应该是最为复杂的部分 为了便于
  • leveldb代码结构

    leveld代码结构 源文件 tree I test AUTHORS build detect platform db 具体逻辑 builder cc 定义了BuildTable函数 builder h c cc c封装 暂时不用看 db
  • Leveldb源码分析--13

    8 FilterPolicy Bloom之2 8 5 构建FilterBlock 8 5 1 FilterBlockBuilder 了解了filter机制 现在来看看filter block的构建 这就是类FilterBlockBuilde
  • LevelDB源码阅读-key

    levelDB中的key 前言 在levelDB中有五种不同的key 在正式分析memtable之前我们先介绍一下这5中不同的key user key ParsedInternalKey InternalKey LookupKey Memt
  • LevelDB.NET 使用

    LevelDB是google实现的非常高效的kv数据库 多数是和redis比较 这里记录下如何使用 新建项目 Nuget添加类库 通过反编译发现运行时是 NET 4 0 这里我用4 5测试需要选择64位平台 代码 写数据 db Put Wr
  • LevelDB使用指南

    这篇文章是levelDB官方文档的译文 原文地址 LevelDB library documentation 这篇文章主要讲leveldb接口使用和注意事项 leveldb是一个持久型的key value数据库 key value可以是任意
  • Windows下 VS2015编译RocksDB

    Windows下 VS2015编译RocksDB VS2015编译RocksDB RocksDB 是一个来自 facebook 的可嵌入式的支持持久化的 key value 存储系统 也可作为 C S 模式下的存储数据库 但主要目的还是嵌入
  • LSM树由来、设计思想以及应用到HBase的索引

    讲LSM树之前 需要提下三种基本的存储引擎 这样才能清楚LSM树的由来 哈希存储引擎 是哈希表的持久化实现 支持增 删 改以及随机读取操作 但不支持顺序扫描 对应的存储系统为key value存储系统 对于key value的插入以及查询
  • Log Structured Merge Trees(LSM) 原理

    Log Structured Merge Trees LSM 原理 十年前 谷歌发表了 BigTable 的论文 论文中很多很酷的方面之一就是它所使用的文件组织方式 这个方法更一般的名字叫 Log Structured Merge Tree
  • MongoDB wiredTiger存储引擎下的存储方式LSM和B-Tree比较

    前段时间做拦截件监控的时候把拦截件生命期存入mongodb 因生命期有各种变化 因此对此表的更新写操作非常多 老大给我看了一篇文章 才知道mongodb已经支持lsm存储方式了 原文如连接 https github com wiredtig
  • CODIS原理 之 数据迁移流程[2.X]

    CODIS原理 之 数据迁移流程 2 X 分类 源码剖析设计思路 1173 0 作者 邹祁峰 邮箱 Qifeng zou job hotmail com 博客 http blog csdn net qifengzou 日期 2016 08
  • IndexedDB 性能和 IndexedDB 与 WebSQL 性能比较

    WebSQL 和 IndexedDB 都是用于在 Web 浏览器中访问 CRUD 底层嵌入式数据库的 DB API 如果我没猜错的话 这就像用于访问 CRUD 任何客户端服务器数据库 如 Oracle 等 的 SQL 在许多情况下 同一浏览
  • 从 Bash 或 Python 获取 google Chrome IndexedDB 中的数据

    我的 Google Chrome 中有 LevelDB IndexedDB 文件 该文件位于此文件夹中 home
  • 无法构建 Objective-C 模块“CoreGraphics”

    当我尝试运行任何单元或 UI 测试时 出现以下错误 运行应用程序本身时不会发生 错误信息如下所示 Applications Xcode app Contents Developer Platforms iPhoneSimulator pla
  • g++ 找不到标头,但我确实包含了它们

    我开始使用 c 并且已经出错了 我正在尝试编译 levelDB 的一个小测试 include

随机推荐

  • 阿里云部署k8s及常见的错误解决方法

    目录 一 背景介绍 二 环境准备 2 1 ECS云服务资源清单 2 2 K8s软件列表 三 阿里云ECS服务器网络问题 3 1 问题阐述 3 2 解决方案 四 服务节点调整 master node1 node2 4 1 关闭firewall
  • UI自动化截图之chrome&Firefox篇

    在web的UI自动化中 小伙伴们经常遇到的一个问题是 IE的截屏非常好实现 一个save screenshot即可满足 而chrome和Firefox的全屏截图就让人很是头疼了 今天作者来给大家分享下自己实例中使用的chrome和Firef
  • Python/练习题

    1 执行 Python 脚本的两种方式 交互方式 命令行 Windows操作系统下 快捷键cmd 输入 python 启动交互式python解释器 文件方式 python文件 2 简述位 字节的关系 一个二进制位是计算机里最小表示单元 一个
  • 《第1阶段》——边界值分析法

    Video Number 091820 学习时间 4月23日 091820 边界值分析法 对输入或输出的边界值进行测试的一种黑盒测试设计方法 通常是作为等价类划分法的补充 这种情况下 其测试用例来自等价类的边界 不是从某等价类中随便挑一个作
  • quasar在axios.js中使用响应拦截器不能正常跳转解决

    问题描述 提示 这里描述具体问题 在quasar框架中的 src boot axios js中使用router push 无效 router index js import route from quasar wrappers import
  • 最近用matplotlib绘制了一张天气折线图,分享给大家

    usr bin env python coding utf 8 作者 志在星空 时间 2022 04 04 19 38 文件名 绘制折线图 py 软件 PyCharm import matplotlib pylab as pyl impor
  • 机器学习中的范数规则化之(一)L0、L1与L2范数

    机器学习中的范数规则化之 一 L0 L1与L2范数 zouxy09 qq com http blog csdn net zouxy09 今天我们聊聊机器学习中出现的非常频繁的问题 过拟合与规则化 我们先简单的来理解下常用的L0 L1 L2和
  • 某验滑块js逆向 - 底图还原

    注 本篇博客仅供学习使用 请勿用做其他商业用途 如有侵权 请联系本菜鸟 前段时间本小菜鸟研究了某验的点选类型验证码 今天开始研究他们的另一类验证码 滑块 先直接上流程 和点选的步骤基本相同 1 请求gt register slide off
  • 【Linux】shell的简单模拟实现

    目录 一 大概思路 二 命令行显示及获取用户输入命令 三 分析命令 四 创建子进程执行命令 五 导入环境变量 六 源码 总结 前言 我们已经接触了很长时间的Linux 我们对shell特别的好奇 正好前面我们学习了shell的运行原理 以及
  • Ambari——大数据平台的搭建利器(一)

    Ambari是hadoop分布式集群配置管理工具 是由hortonworks主导的开源项目 它已经成为apache基金会的孵化器项目 已经成为hadoop运维系统中的得力助手 引起了业界和学术界的关注 Ambari采用的不是一个新的思想和架
  • matlab系统稳定性仿真实验,基于Matlab的电力系统暂态稳定仿真实验与分析

    基于Matlab的电力系统暂态稳定仿真实验与分析 第29卷第4期2010年4月 实验室研究与探索 RESEARCHANDEXPLORATIONINLABORATORY Vol 29No 4Apr 2010 Matlab 1引言 长期以来 电
  • vue2与vue3的区别

    1 vue2和vue3双向数据绑定原理发生了改变 vue2 的双向数据绑定是利用ES5 的一个 API Object definePropert 对数据进行劫持 结合 发布订阅模式的方式来实现的 vue3 中使用了 es6 的 ProxyA
  • glTexSubImage2D的使用详解

    Name glTexSubImage2D glTextureSubImage2D specify a two dimensional texture subimage C Specification void glTexSubImage2D
  • LeetCode第3题解析

    给定一个字符串 请你找出其中不含有重复字符的 最长子串 的长度 示例 1 输入 abcabcbb 输出 3 解释 因为无重复字符的最长子串是 abc 所以其长度为 3 示例 2 输入 bbbbb 输出 1 解释 因为无重复字符的最长子串是
  • 【洛谷 P1170】兔八哥与猎人 题解(数学+辗转相除法)

    兔八哥与猎人 题目描述 兔八哥躲藏在树林旁边的果园里 果园有 M N M times N M N 棵树 组成一个 M M M 行
  • 本地从0搭建Stable Diffusion WebUI及错误记录

    从0开始搭建本地Stable Diffusion WebUI环境 一 环境配置 1 使用的电脑配置 系统 Windows10 处理器 英特尔 i7 内存 24GB 显卡 NVIDIA GTX 1060 6GB 2 镜像源 阿里云 清华大学
  • MySql 简介

    目录 数据存取演变历史 数据库软件应用史 数据库的本质 数据库的分类 1 关系型数据库 关系型数据库有哪些 2 非关系型数据库 非关系型数据库有哪些 MySQL简介 基本使用 系统服务制作 密码相关操作 SQL与NoSQL 数据库的概念 数
  • Spring Junit 单元测试@Test 报错 ServletContext找不到 No qualifying bean of type javax.servlet.ServletContext

    Spring Junit 单元测试 Test 报错 ServletContext找不到 No qualifying bean of type javax servlet ServletContext found for dependency
  • 微信小程序画布详解

    有的时候需要插入动画 这时就需要用到画布 接下来浅谈一下画布的功能和用法吧 wxml代码
  • Log Structured Merge Trees(LSM) 原理(LSM 算法的原理是什么?)

    十年前 谷歌发表了 BigTable 的论文 论文中很多很酷的方面之一就是它所使用的文件组织方式 这个方法更一般的名字叫 Log Structured Merge Tree LSM是当前被用在许多产品的文件结构策略 HBase Cassan