从零手写Java版本的LSM Tree (一):LSM Tree 概述

news2025/6/10 13:41:33

🔥 推荐一个高质量的Java LSM Tree开源项目!
https://github.com/brianxiadong/java-lsm-tree
java-lsm-tree 是一个从零实现的Log-Structured Merge Tree,专为高并发写入场景设计。
核心亮点:
⚡ 极致性能:写入速度超过40万ops/秒,完爆传统B+树
🏗️ 完整架构:MemTable跳表 + SSTable + WAL + 布隆过滤器 + 多级压缩
📚 深度教程:12章详细教程,从基础概念到生产优化,每行代码都有注释
🔒 并发安全:读写锁机制,支持高并发场景
💾 数据可靠:WAL写前日志确保崩溃恢复,零数据丢失
适合谁?

  • 想深入理解LSM Tree原理的开发者
  • 需要高写入性能存储引擎的项目
  • 准备数据库/存储系统面试的同学
  • 对分布式存储感兴趣的工程师
    ⭐ 给个Star支持开源!

第1章:LSM Tree 概述

什么是LSM Tree?

Log-Structured Merge Tree (LSM Tree) 是一种专为写密集型工作负载优化的数据结构。它被广泛应用于现代数据库系统中,如LevelDB、RocksDB、Cassandra、HBase等。

简单来说,就是特别适用于写多读少的场景,比如日志、调用链记录等。

核心设计思想

LSM Tree的核心思想是:

  • 将随机写入转换为顺序写入
  • 将写入操作与读取操作分离优化
  • 通过多层存储结构平衡内存和磁盘的使用

LSM Tree vs 传统B+树

我们来对比一下LSM Tree和Mysql使用的传统B+树:

特征B+树LSM Tree
写入性能O(log N) 随机写O(log M) 顺序写 (M << N)
读取性能O(log N)O(log N + K)
空间放大中等
写放大
适用场景读多写少写多读少

LSM Tree 架构概览

系统架构图

容量满
压缩
压缩
压缩
Client 写入请求
WAL 写前日志
Active MemTable
Immutable MemTable
刷盘到 SSTable
Level 0 SSTable文件
Client 读取请求
Level 0 SSTables
Level 1 SSTables
Level N SSTables
Bloom Filter
Compaction Strategy

图表说明: 这个架构图展示了LSM Tree的完整数据流向和组件关系。左侧显示写入路径:客户端写入请求首先写入WAL日志确保持久性,然后存入Active MemTable,当MemTable容量满时转为Immutable状态并刷盘生成SSTable文件。右侧显示读取路径:客户端读取请求会依次查询MemTable和各级SSTable文件。布隆过滤器附加在每个SSTable上用于快速过滤,压缩策略在后台持续优化存储结构。这种设计实现了写入的高性能(顺序写)和读取的合理性能(分层查找)。

很复杂吗?但是当我们一行代码一行代码实现了这个LSM Tree之后,你会发现其实也并不难。

架构层次说明

内存层 (Memory Layer)

  • WAL (Write-Ahead Log): 写前日志,确保数据持久性
  • Active MemTable: 接收新写入的内存表
  • Immutable MemTable: 正在刷盘的只读内存表

磁盘层 (Disk Layer)

  • Level 0: 直接从MemTable刷盘的SSTable文件
  • Level 1-N: 通过压缩生成的分层SSTable文件
  • Bloom Filter: 每个SSTable的布隆过滤器

后台进程 (Background Process)

  • Compaction Strategy: 压缩策略,负责合并和清理SSTable

数据流向

写入路径: Client → WAL → MemTable → SSTable → Compaction

读取路径: Client → MemTable → Immutable → Level 0 → Level 1 → ... → Level N

核心组件详解

1. MemTable (内存表)

  • 作用: 内存中的有序数据结构,接收所有写入操作
  • 实现: 使用跳表 (ConcurrentSkipListMap) 保证有序性和线程安全
  • 容量: 达到阈值时触发刷盘操作

2. Immutable MemTable (不可变内存表)

  • 作用: 正在刷盘的MemTable,只读状态
  • 目的: 避免阻塞新的写入操作
  • 生命周期: 刷盘完成后自动删除

3. SSTable (Sorted String Table)

  • 作用: 磁盘上的不可变有序文件
  • 特点:
    • 数据按键有序存储
    • 包含布隆过滤器
    • 支持快速查找

4. WAL (Write-Ahead Log)

  • 作用: 写前日志,确保数据持久性
  • 格式: 管道分隔的文本格式
  • 恢复: 系统重启时重放日志恢复数据

5. Bloom Filter (布隆过滤器)

  • 作用: 快速判断键是否可能存在
  • 优化: 减少无效的磁盘I/O操作
  • 特点: 无假阴性,有假阳性

6. Compaction Strategy (压缩策略)

  • 作用: 后台合并SSTable文件
  • 目的:
    • 清理过期/删除的数据
    • 控制文件数量
    • 优化查询性能

数据流详解

写入流程

写入WAL日志
写入Active MemTable
MemTable满了?
继续接收写入
转为Immutable MemTable
刷盘到SSTable
删除Immutable MemTable
需要压缩?
触发压缩
完成

写入流程说明: 这个流程图详细展示了LSM Tree的写入过程。每个写入操作首先记录到WAL日志中,这是持久性的第一道保障。然后数据写入Active MemTable,这是一个内存中的有序结构,提供快速的写入性能。当MemTable达到容量阈值时,系统会将其标记为Immutable(不可变),同时创建新的Active MemTable继续接收写入,这样保证了写入操作的连续性。Immutable MemTable随后被刷盘到磁盘上的SSTable文件,完成持久化。最后系统检查是否需要触发压缩操作来优化存储结构。这个流程确保了高写入性能和数据的可靠性。

读取流程

查询Active MemTable
找到?
返回结果
查询Immutable MemTables
找到?
按时间倒序查询SSTables
布隆过滤器判断
可能存在?
跳过文件
查询文件
找到?
还有文件?
返回null

读取流程说明: 这个流程图展示了LSM Tree的分层查找策略。读取操作遵循"新数据优先"的原则,首先查询Active MemTable,因为它包含最新的数据。如果没找到,继续查询Immutable MemTable,这些是正在刷盘但尚未完成的数据。接下来按时间倒序查询SSTable文件,新文件优先查询,因为它们包含更新的数据版本。在查询每个SSTable之前,系统会先使用布隆过滤器快速判断键是否可能存在,这能有效减少无效的磁盘I/O操作。如果布隆过滤器表明键可能存在,才会实际读取文件进行查找。这种分层查找机制平衡了读取性能和存储效率。

性能特征

写入性能优势

  • 顺序写入: WAL和SSTable都是顺序写,充分利用磁盘特性
  • 批量刷盘: MemTable批量写入SSTable,减少I/O次数
  • 无锁写入: 使用并发跳表,减少锁竞争

读取性能考虑

  • 多层查找: 需要查询多个数据源
  • 布隆过滤器: 显著减少无效磁盘访问
  • 缓存友好: 热数据通常在MemTable中

空间使用

  • 写放大: 压缩过程中的数据重写
  • 空间放大: 删除数据的墓碑标记
  • 优化: 定期压缩清理无效数据

实际应用场景

适合的场景

  • 写多读少: 日志系统、监控数据
  • 时序数据: IoT传感器数据、指标收集
  • 缓存系统: 高频写入的缓存更新
  • 事件存储: 审计日志、用户行为跟踪

不适合的场景

  • 读多写少: 传统OLTP应用
  • 复杂查询: 需要复杂SQL的场景
  • 强一致性: 需要ACID事务的场景

核心优势

  1. 高写入吞吐量: 40万+ ops/sec
  2. 低写入延迟: 平均1.8微秒
  3. 良好的扩展性: 数据量增长对写性能影响小
  4. 崩溃恢复: WAL确保数据不丢失
  5. 并发友好: 支持多线程读写

实现挑战

  1. 读放大: 需要查询多个数据源
  2. 空间放大: 压缩前的冗余数据
  3. 压缩开销: 后台压缩消耗CPU/IO
  4. 复杂性: 多组件协调的复杂性

下一步学习

现在你已经了解了LSM Tree的整体架构,接下来我们将深入学习各个组件:

  1. KeyValue数据结构 - 理解基础数据格式
  2. MemTable实现 - 深入跳表和并发控制
  3. SSTable格式 - 磁盘存储的设计细节

思考题

  1. 为什么LSM Tree适合写密集型工作负载?
  2. 布隆过滤器如何提升读取性能?
  3. 压缩策略的作用是什么?

下一章预告: 我们将学习LSM Tree的基础数据结构KeyValue,理解时间戳、删除标记等核心概念。

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

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

相关文章

在Zenodo下载文件 用到googlecolab googledrive

方法&#xff1a;Figshare/Zenodo上的数据/文件下载不下来&#xff1f;尝试利用Google Colab &#xff1a;https://zhuanlan.zhihu.com/p/1898503078782674027 参考&#xff1a; 通过Colab&谷歌云下载Figshare数据&#xff0c;超级实用&#xff01;&#xff01;&#xff0…

【1】跨越技术栈鸿沟:字节跳动开源TRAE AI编程IDE的实战体验

2024年初&#xff0c;人工智能编程工具领域发生了一次静默的变革。当字节跳动宣布退出其TRAE项目&#xff08;一款融合大型语言模型能力的云端AI编程IDE&#xff09;时&#xff0c;技术社区曾短暂叹息。然而这一退场并非终点——通过开源社区的接力&#xff0c;TRAE在WayToAGI等…

高端性能封装正在突破性能壁垒,其芯片集成技术助力人工智能革命。

2024 年&#xff0c;高端封装市场规模为 80 亿美元&#xff0c;预计到 2030 年将超过 280 亿美元&#xff0c;2024-2030 年复合年增长率为 23%。 细分到各个终端市场&#xff0c;最大的高端性能封装市场是“电信和基础设施”&#xff0c;2024 年该市场创造了超过 67% 的收入。…

动态规划-1035.不相交的线-力扣(LeetCode)

一、题目解析 光看题目要求和例图&#xff0c;感觉这题好麻烦&#xff0c;直线不能相交啊&#xff0c;每个数字只属于一条连线啊等等&#xff0c;但我们结合题目所给的信息和例图的内容&#xff0c;这不就是最长公共子序列吗&#xff1f;&#xff0c;我们把最长公共子序列连线起…

网页端 js 读取发票里的二维码信息(图片和PDF格式)

起因 为了实现在报销流程中&#xff0c;发票不能重用的限制&#xff0c;发票上传后&#xff0c;希望能读出发票号&#xff0c;并记录发票号已用&#xff0c;下次不再可用于报销。 基于上面的需求&#xff0c;研究了OCR 的方式和读PDF的方式&#xff0c;实际是可行的&#xff…

MeshGPT 笔记

[2311.15475] MeshGPT: Generating Triangle Meshes with Decoder-Only Transformers https://library.scholarcy.com/try 真正意义上的AI生成三维模型MESHGPT来袭&#xff01;_哔哩哔哩_bilibili GitHub - lucidrains/meshgpt-pytorch: Implementation of MeshGPT, SOTA Me…

Appium下载安装配置保姆教程(图文详解)

目录 一、Appium软件介绍 1.特点 2.工作原理 3.应用场景 二、环境准备 安装 Node.js 安装 Appium 安装 JDK 安装 Android SDK 安装Python及依赖包 三、安装教程 1.Node.js安装 1.1.下载Node 1.2.安装程序 1.3.配置npm仓储和缓存 1.4. 配置环境 1.5.测试Node.j…

qt+vs Generated File下的moc_和ui_文件丢失导致 error LNK2001

qt 5.9.7 vs2013 qt add-in 2.3.2 起因是添加一个新的控件类&#xff0c;直接把源文件拖进VS的项目里&#xff0c;然后VS卡住十秒&#xff0c;然后编译就报一堆 error LNK2001 一看项目的Generated Files下的moc_和ui_文件丢失了一部分&#xff0c;导致编译的时候找不到了。因…

基于stm32F10x 系列微控制器的智能电子琴(附完整项目源码、详细接线及讲解视频)

注&#xff1a;文章末尾网盘链接中自取成品使用演示视频、项目源码、项目文档 所用硬件&#xff1a;STM32F103C8T6、无源蜂鸣器、44矩阵键盘、flash存储模块、OLED显示屏、RGB三色灯、面包板、杜邦线、usb转ttl串口 stm32f103c8t6 面包板 …

高抗扰度汽车光耦合器的特性

晶台光电推出的125℃光耦合器系列产品&#xff08;包括KL357NU、KL3H7U和KL817U&#xff09;&#xff0c;专为高温环境下的汽车应用设计&#xff0c;具备以下核心优势和技术特点&#xff1a; 一、技术特性分析 高温稳定性 采用先进的LED技术和优化的IC设计&#xff0c;确保在…

如何做好一份技术文档?从规划到实践的完整指南

如何做好一份技术文档&#xff1f;从规划到实践的完整指南 &#x1f31f; 嗨&#xff0c;我是IRpickstars&#xff01; &#x1f30c; 总有一行代码&#xff0c;能点亮万千星辰。 &#x1f50d; 在技术的宇宙中&#xff0c;我愿做永不停歇的探索者。 ✨ 用代码丈量世界&…

SQL注入篇-sqlmap的配置和使用

在之前的皮卡丘靶场第五期SQL注入的内容中我们谈到了sqlmap&#xff0c;但是由于很多朋友看不了解命令行格式&#xff0c;所以是纯手动获取数据库信息的 接下来我们就用sqlmap来进行皮卡丘靶场的sql注入学习&#xff0c;链接&#xff1a;https://wwhc.lanzoue.com/ifJY32ybh6vc…

Linux操作系统共享Windows操作系统的文件

目录 一、共享文件 二、挂载 一、共享文件 点击虚拟机选项-设置 点击选项&#xff0c;设置文件夹共享为总是启用&#xff0c;点击添加&#xff0c;可添加需要共享的文件夹 查询是否共享成功 ls /mnt/hgfs 如果显示Download&#xff08;这是我共享的文件夹&#xff09;&…

Redis上篇--知识点总结

Redis上篇–解析 本文大部分知识整理自网上&#xff0c;在正文结束后都会附上参考地址。如果想要深入或者详细学习可以通过文末链接跳转学习。 1. 基本介绍 Redis 是一个开源的、高性能的 内存键值数据库&#xff0c;Redis 的键值对中的 key 就是字符串对象&#xff0c;而 val…

李沐--动手学深度学习--GRU

1.GRU从零开始实现 #9.1.2GRU从零开始实现 import torch from torch import nn from d2l import torch as d2l#首先读取 8.5节中使用的时间机器数据集 batch_size,num_steps 32,35 train_iter,vocab d2l.load_data_time_machine(batch_size,num_steps) #初始化模型参数 def …

EasyRTC音视频实时通话功能在WebRTC与智能硬件整合中的应用与优势

一、WebRTC与智能硬件整合趋势​ 随着物联网和实时通信需求的爆发式增长&#xff0c;WebRTC作为开源实时通信技术&#xff0c;为浏览器与移动应用提供免插件的音视频通信能力&#xff0c;在智能硬件领域的融合应用已成必然趋势。智能硬件不再局限于单一功能&#xff0c;对实时…

【版本控制】GitHub Desktop 入门教程与开源协作全流程解析

目录 0 引言1 GitHub Desktop 入门教程1.1 安装与基础配置1.2 核心功能使用指南仓库管理日常开发流程分支管理 2 GitHub 开源协作流程详解2.1 Fork & Pull Request 模型2.2 完整协作流程步骤步骤 1: Fork&#xff08;创建个人副本&#xff09;步骤 2: Clone&#xff08;克隆…

Android屏幕刷新率与FPS(Frames Per Second) 120hz

Android屏幕刷新率与FPS(Frames Per Second) 120hz 屏幕刷新率是屏幕每秒钟刷新显示内容的次数&#xff0c;单位是赫兹&#xff08;Hz&#xff09;。 60Hz 屏幕&#xff1a;每秒刷新 60 次&#xff0c;每次刷新间隔约 16.67ms 90Hz 屏幕&#xff1a;每秒刷新 90 次&#xff0c;…

【PX4飞控】mavros gps相关话题分析,经纬度海拔获取方法,卫星数锁定状态获取方法

使用 ROS1-Noetic 和 mavros v1.20.1&#xff0c; 携带经纬度海拔的话题主要有三个&#xff1a; /mavros/global_position/raw/fix/mavros/gpsstatus/gps1/raw/mavros/global_position/global 查看 mavros 源码&#xff0c;来分析他们的发布过程。发现前两个话题都对应了同一…

ubuntu中安装conda的后遗症

缘由: 在编译rk3588的sdk时&#xff0c;遇到编译buildroot失败&#xff0c;提示如下&#xff1a; 提示缺失expect&#xff0c;但是实测相关工具是在的&#xff0c;如下显示&#xff1a; 然后查找借助各个ai工具&#xff0c;重新安装相关的工具&#xff0c;依然无解。 解决&am…