当前位置: 首页 > news >正文

【LSM tree 】Log-structured merge-tree 一种分层、有序、面向磁盘的数据结构

文章目录

  • 前言
  • 基本原理
  • 读写流程
    • 写流程
    • 读流程
  • 写放大、读放大和空间放大
  • 优化


前言

LSM Tree 全称是Log-structured merge-tree, 是一种分层,有序,面向磁盘的数据结构。其核心原理是磁盘批量顺序写比随机写性能高很多,可以通过围绕这一原理进行设计和优化,让写性能达到最优。相较于传统的B+树,它减少了磁盘随机读取的需求,从而在一定程度上改善了数据库的写能力,当然在一定程度上牺牲了数据库的读能力。LSM tree也是当今流行的各种NoSQL或NewSQL数据库最基础的底层数据结构,广泛使用在包括Hbase,Cassandra,Leveldb, RocksDB, TiDB等项目中。

基本原理

传统的B+树的缺陷就是在访问节点时涉及到了大量的磁盘随机读写,因为你无法保证节点常驻内存,尤其是当B+树管理的索引量很大的时候,这导致数据库读写性能急剧下降。
LSM tree 采取的做法就是通过引入多部件索引来减少磁盘随机读写的需求。在大量插入情况下我们周期性地选取两部分索引进行合并,并且把合并后的有序文件(或内存块)添加到磁盘尾部(或成为新文件),修改节点信息以保证索引树的正确和完善,并且周期性地回收失效索引。因此与其说LSM tree是一种树,不如说它是通过传统索引组织有序文件或内存块的一种方式。
在这里插入图片描述
LSM tree的节点可以分为两种:

  • MemTable: 保存在内存中的部分,一般可以是红黑树、跳跃表,甚至可以是B树。在HBase中使用的是跳表,在SQLite4中使用的是只能追加写入的红黑树。
  • SSTable: 保存在磁盘上的部分,一般由多个内部KeyValue有序的文件组成,它的key和value都是任意的字节数组,并且了提供了按指定key查找和指定范围dekey区间迭代遍历的功能。SSTable内部包含了系列可匹配大小的Block块。关于这些Block块的index存储在SSTable的尾部,用于帮助快速查找。

写操作直接作用于MemTable,因此写入性能接近写内存。每层SSTable文件到达一定条件后,进行合并操作,然后放置到更高层。合并操作在实现上一般的策略驱动、可插件化的。

读写流程

在这里插入图片描述

写流程

  1. 当收到一个写请求时,会先把该条数据记录在 WAL(Write-ahead logging)里面,用作故障恢复。
  2. 当写完 WAL 后,会把该条数据写入内存的 MemTable 里面(删除操作也通过写入实现,会写入一个删除标记;更新则是写入一条新记录)。
  3. 当 Memtable 超过一定的大小后,会在内存里面冻结,变成不可变的 Memtable,同时为了不阻塞写操作需要新生成一个 Memtable 继续提供服务。
  4. 把内存里面不可变的 Memtable 给 flush 到到硬盘上的 SSTable 层中,此步骤也称为 Minor Compaction,这里需要注意在 L0 层的 SSTable 是没有进行合并的,所以这里的 key range 在多个 SSTable 中可能会出现重叠,在层数大于 0 层之后的 SSTable,不存在重叠 key。
  5. 当每层的磁盘上的 SSTable 的体积超过一定的大小或者个数,也会周期的进行合并。此步骤也称为 Major Compaction。这个阶段会真正的清除掉被标记删除掉的数据以及多版本数据的合并,避免浪费空间,注意由于 SSTable 都是有序的,我们可以直接采用 merge sort 进行高效合并。

读流程

  1. 当收到一个读请求的时候,会直接先在内存里面查询,如果查询到就返回。
  2. 内存查询包括服务中的 Memtable 和不可变的 Memtable,也包括对于 SSTable 的缓存 block cache。
  3. 如果内存中没有查询到就会依次下沉查询 SSTable,直到把所有的层次的 SSTable 查询一遍得到最终结果。

写放大、读放大和空间放大

LSM Tree 将随机写转化为顺序写,而作为代价带来了大量的重复写入。由此会引起写放大、读放大和空间放大。

  • 写放大(Write Amplification):
    平均写入 1 个字节,引擎中在数据的声明周期内实际会写入 n 个字节,其写放大率是 n。如果业务方写入速度是 10MB/s,在引擎端或者操作系统层面能观察到的数据写入速度是 30MB/s,系统的写放大率就是 3。写放大过大会制约系统的实际吞吐。对于 SSD 来说,也会导致 SSD 寿命缩短。

以下是 HBase 中的写放大示意图
在这里插入图片描述

  • 读放大(Read Amplification):

一个读请求,系统所需要读 n 个页面来完成查询,其读放大率是 n。逻辑上的读操作可能会命中引擎内部的 cache 或者文件系统 cache,命中不了 cache 就会进行实际的磁盘 IO,命中 cache 的读取操作的代价虽然很低,但是也会消耗 CPU。
以下是 HBase 中的读放大示意图
在这里插入图片描述

  • 空间放大(Space Amplification):
    平均存储 1 个字节的数据,在存储引擎内部所占用的磁盘空间 n 个字节,其空间放大是 n。比如写入 10MB 的数据,磁盘上实际占用了 100MB,这是空间放大率就是 10。空间放大和写放大在调优的时候往往是排斥的,空间放大越大,那么数据可能不需要频繁的 compaction,其写放大就会降低;如果空间放大率设置的小,那么数据就需要频繁的 compaction 来释放存储空间,导致写放大增大

优化

LSM tree 一般从以下几个方面进行优化:

  1. 压缩

SSTable 是可以启用压缩功能的,并且这种压缩不是将整个 SSTable 一起压缩,而是根据 locality 将数据分组,每个组分别压缩,这样的好处当读取数据的时候,我们不需要解压缩整个文件而是解压缩部分 Group 就可以读取。

  1. 缓存

因为 SSTable 在写入磁盘后,除了 Compaction 之外,是不会变化的,所以我可以将 Scan 的 Block 进行缓存,从而提高检索的效率。

  1. Bloom filter

正常情况下,一个读操作是需要读取所有的 SSTable 将结果合并后返回的,但是对于某些 key 而言,有些 SSTable 是根本不包含对应数据的,因此,我们可以对每一个 SSTable 添加 Bloom Filter,因为 Bloom Filter 在判断一个 SSTable 不存在某个 key 的时候,那么就一定不会存在,利用这个特性可以减少不必要的磁盘扫描。

  1. 合并

通过定期合并瘦身, 可以有效的清除无效数据,缩短读取路径,提高磁盘利用空间。但 Compaction 操作是非常消耗 CPU 和磁盘 IO 的,尤其是在业务高峰期,如果发生了 Major Compaction,则会降低整个系统的吞吐量,这也是在使用一些 NoSQL 数据库时,比如 Hbase,常常会禁用 Major Compaction,并在凌晨业务低峰期进行合并的原因。

ref:https://popesaga.github.io/2020/09/25/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E5%92%8C%E7%AE%97%E6%B3%95%EF%BC%9ALSM%20tree/#%E5%86%99%E6%94%BE%E5%A4%A7%E3%80%81%E8%AF%BB%E6%94%BE%E5%A4%A7%E5%92%8C%E7%A9%BA%E9%97%B4%E6%94%BE%E5%A4%A7

相关文章:

【LSM tree 】Log-structured merge-tree 一种分层、有序、面向磁盘的数据结构

文章目录 前言基本原理读写流程写流程读流程 写放大、读放大和空间放大优化 前言 LSM Tree 全称是Log-structured merge-tree, 是一种分层,有序,面向磁盘的数据结构。其核心原理是磁盘批量顺序写比随机写性能高很多,可以通过围绕这一原理进行…...

配置OSPF与BFD联动示例

定义 双向转发检测BFD(Bidirectional Forwarding Detection)是一种用于检测转发引擎之间通信故障的检测机制。 BFD对两个系统间的、同一路径上的同一种数据协议的连通性进行检测,这条路径可以是物理链路或逻辑链路,包括隧道。 …...

01到底应该怎么理解“平均负载”

1、如何了解系统的负载情况? 每次发现系统变慢时, 我们通常做的第⼀件事, 就是执⾏top或者uptime命令, 来了解系统的负载情况。 ⽐如像下⾯这样, 我在命令⾏⾥输⼊了uptime命令, 系统也随即给出了结果。 …...

jmeter,动态参数之随机数、随机日期

通过函数助手,执行以下配置: 执行后的结果树: 数据库中也成功添加了数据,对应字段是随机值:...

uniApp常见知识点-问题答案

1、uniApp中如何进行页面跳转? 答案:可以使用 uni.navigateTo、uni.redirectTo 和 uni.reLaunch 等方法进行页面跳转。其中,uni.navigateTo可以实现页面的普通跳转, uni.redirectTo可以实现页面的重定向跳转, uni.reL…...

云原生基础入门概念

文章目录 发现宝藏云原生的概念云原生的关键技术为何选择云原生?云原生的实际应用好书推荐 发现宝藏 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。【宝藏入口】。 云原生的概念 当谈及现…...

一个 tomcat 下如何部署多个项目?附详细步骤

一个tomcat下如何部署多个项目?Linux跟windows系统下的步骤都差不多,以下linux系统下部署为例。windows系统下部署同理。 1 不修改端口,部署多个项目 清楚tomcat目录结构的应该都知道,项目包是放在webapps目录下的,那…...

pycharm强制让terminal停止执行的快捷键

CtrlC即可...

MFC(Microsoft Foundation Classes)中 MessageBox

在MFC(Microsoft Foundation Classes)中,MessageBox是一个常用的对话框类,用于显示消息框并与用户进行交互。MessageBox类提供了多种用法和选项,以下是一些常见的用法和示例说明: 显示简单的消息框&#x…...

如何让.NET应用使用更大的内存

我一直在思考为何Redis这种应用就能独占那么大的内存空间而我开发的应用为何只有4GB大小左右,在此基础上也问了一些大佬,最终还是验证下自己的猜测。 操作系统限制 主要为32位操作系统和64位操作系统。 每个进程自身还分为了用户进程空间和内核进程空…...

【从零开始学习JVM | 第九篇】了解 常见垃圾回收器

前言: 垃圾回收器(Garbage Collector)是现代编程语言中的一项重要技术,它提供了自动内存管理的机制,极大地简化了开发人员对内存分配和释放的繁琐工作。通过垃圾回收器,我们能够更高效地利用计算机的内存资…...

Wordle 游戏实现 - 使用 C++ Qt

标题:Wordle 游戏实现 - 使用 C Qt 摘要: Wordle 是一款文字猜词游戏,玩家需要根据给定的单词猜出正确的答案,并在限定的次数内完成。本文介绍了使用 C 和 Qt 框架实现 Wordle 游戏的基本思路和部分代码示例。 引言:…...

Python 爬虫开发完整环境部署,爬虫核心框架安装

Python 爬虫开发完整环境部署 前言: ​ 关于本篇笔记,参考书籍为 《Python 爬虫开发实战3 》 笔记做出来的一方原因是为了自己对 Python 爬虫加深认知,一方面也想为大家解决在爬虫技术区的一些问题,本篇文章所使用的环境为&#x…...

汽车标定技术(十三)--标定概念再详解

目录 1.概述 2.基于Flash的标定 3.基于RAM的标定 4.AUTOSAR基于指针标定概念 5.小结 1.概述 最近有朋友问到是否用overlay标定完数据就直接写在Flash中,其实不然,是需要关闭overlay然后通过XCP Program指令集或者UDS刷进Flash。 从这里看出&#…...

PostgreSQL常用命令

数据库版本 :9.6.6 注意 :PostgreSQL中的不同类型的权限有 SELECT,INSERT,UPDATE,DELETE,TRUNCATE,REFERENCES,TRIGGER,CREATE,CONNECT,TEMPORARY,EXECUTE 和 USAGE。 1. 登录PG数据库 以管理员身份 postgres 登陆,然后通过 #psql -U postgres #sudo -i -u postgres …...

使用python脚本部署k8s集群

1.环境规划: 节点IP地址操作系统配置脚本运行节点192.168.174.5centos7.92G2核server192.168.174.150centos7.92G2核client1192.168.174.151centos7.92G2核client2192.168.174.152centos7.92G2 2.运行准备: yum install -y python python-pip pip in…...

【C语言】操作符详解(四):结构成员访问操作符

目录 结构成员访问操作符 结构体 结构体的声明 结构体变量的定义和初始化 结构成员访问操作符 结构体成员的直接访问 结构体成员的间接访问 结构成员访问操作符 结构体 ⭐C语言已经提供了内置类型,如: char、short、int、long、float、double等,但…...

【算法】二分法

1、二分法 1.1 二分法原理 每次将查找的范围缩小一半,直到最后找到记录或者找不到记录返回。 要求:采用二分法查找时,数据需是排好序的。 1.2二分法思路 判断某个数是否在数组中存在(例:判断3是否在数组中存在&#…...

2023.12.18 JAVA学习day03,while与for循环

目录 0.switch 判断语句 一.for循环 1.简单练习 2.使用for循环计算1-100求和, 以及偶数求和 3.进阶练习,配合键盘录入与判断使用循环 二.while循环 三种格式的区别: 0.switch 判断语句 switch (表达式) { case 1: 语句体1; break; case …...

使用Pytorch从零开始构建StyleGAN2

这篇博文是关于 StyleGAN2 的,来自论文Analyzing and Improving the Image Quality of StyleGAN,我们将使用 PyTorch 对其进行干净、简单且可读的实现,并尝试尽可能地还原原始论文。 如果您没有阅读 StyleGAN2 论文。或者不知道它是如何工作…...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

ubuntu搭建nfs服务centos挂载访问

在Ubuntu上设置NFS服务器 在Ubuntu上&#xff0c;你可以使用apt包管理器来安装NFS服务器。打开终端并运行&#xff1a; sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享&#xff0c;例如/shared&#xff1a; sudo mkdir /shared sud…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂

蛋白质结合剂&#xff08;如抗体、抑制肽&#xff09;在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上&#xff0c;高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术&#xff0c;但这类方法普遍面临资源消耗巨大、研发周期冗长…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么&#xff1f; WebAssembly&#xff08;WASM&#xff09; 是一种能在现代浏览器中高效运行的二进制指令格式&#xff0c;它不是传统的编程语言&#xff0c;而是一种 低级字节码格式&#xff0c;可由高级语言&#xff08;如 C、C、Rust&am…...

CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云

目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

C++:多态机制详解

目录 一. 多态的概念 1.静态多态&#xff08;编译时多态&#xff09; 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1&#xff09;.协变 2&#xff09;.析构函数的重写 5.override 和 final关键字 1&#…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)

RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发&#xff0c;后来由Pivotal Software Inc.&#xff08;现为VMware子公司&#xff09;接管。RabbitMQ 是一个开源的消息代理和队列服务器&#xff0c;用 Erlang 语言编写。广泛应用于各种分布…...

代码规范和架构【立芯理论一】(2025.06.08)

1、代码规范的目标 代码简洁精炼、美观&#xff0c;可持续性好高效率高复用&#xff0c;可移植性好高内聚&#xff0c;低耦合没有冗余规范性&#xff0c;代码有规可循&#xff0c;可以看出自己当时的思考过程特殊排版&#xff0c;特殊语法&#xff0c;特殊指令&#xff0c;必须…...

规则与人性的天平——由高考迟到事件引发的思考

当那位身着校服的考生在考场关闭1分钟后狂奔而至&#xff0c;他涨红的脸上写满绝望。铁门内秒针划过的弧度&#xff0c;成为改变人生的残酷抛物线。家长声嘶力竭的哀求与考务人员机械的"这是规定"&#xff0c;构成当代中国教育最尖锐的隐喻。 一、刚性规则的必要性 …...