深入 LevelDB 数据文件 SSTable 的结构

【leveldb】SSTable(十一):存储结构说明 针对SSTable的结构说明,这篇博客已有介绍,可点此链接查看,leveldb整体架构。 本篇是针对SStable结构的进一步扩展介绍说明。系列文章的分析都是基于leveldb 1.22版本分析的。 SSTable文件结构 落地的SSTable文件结构如下图1 图1 其中Data block、Meta block、Metablock index、index block都属于Block, Footer是单独的数据格式。 1.Block结构 图2 2.Footer结构 Footer结构共占用48Byte,组 阅读详情

LevelDB 的键值对内容都存储在扩展名为 sst 的 SSTable 文件中,SSTable 的磁盘文件结构比较复杂,读者在阅读本节之前要做好心理准备。如果有任何看得不明白的地方,一定要在下方的问答区及时提问。

640?wx_fmt=png
图片

SSTable 文件的内容分为 5 个部分,Footer、IndexBlock、MetaIndexBlock、FilterBlock 和 DataBlock。其中存储了键值对内容的就是 DataBlock,存储了布隆过滤器二进制数据的是 FilterBlock,DataBlock 有多个,FilterBlock 也可以有多个,但是通常最多只有 1 个,之所以设计成多个是考虑到扩展性,也许未来会支持其它类型的过滤器。另外 3 个部分为管理块,其中 IndexBlock 记录了 DataBlock 相关的元信息,MetaIndexBlock 记录了过滤器相关的元信息,而 Footer 则指出 IndexBlock 和 MetaIndexBlock 在文件中的偏移量信息,它是元信息的元信息,它位于 sstable 文件的尾部。下面我们至顶向下挨个分析每个结构

Footer 结构

它的占用空间很小只有 48 字节,内部只存了几个字段。下面我们用伪代码来描述一下它的结构

// 定义了数据块的位置和大小
struct BlockHandler {
  varint offset;
  varint size;
}

struct Footer {
  BlockHandler metaIndexHandler;  // MetaIndexBlock的文件偏移量和长度
  BlockHandler indexHandler; // IndexBlock的文件偏移量和长度
  byte[n] padding;  // 内存垫片
  int32 magicHighBits;  // 魔数后32位
  int32 magicLowBits; // 魔数前32位
}

$ echo http://code.google.com/p/leveldb/ | sha1sum
db4775248b80fb57d0ce0768d85bcee39c230b61

Block 结构

除了 Footer 之外,其它部分都是 Block 结构,在名称上也都是以 Block 结尾。所谓的 Block 结构是指除了内部的有效数据外,还会有额外的压缩类型字段和校验码字段。

struct Block {
  byte[] data;
  int8 compressType;
  int32 crcValue;
}

crcValue = crc32(data, compressType)

DataBlock 结构

DataBlock 的大小默认是 4K 字节(压缩前),里面存储了一系列键值对。前面提到 sst 文件里面的 Key 是有序的,这意味着相邻的 Key 会有很大的概率有共同的前缀部分。正是考虑到这一点,DataBlock 在结构上做了优化,这个优化可以显著减少存储空间。

Key = sharedKey + unsharedKey

640?wx_fmt=png
图片

比如基准 Key 是 helloworld,那么 hellouniverse 这个 Key 相对于基准 Key 来说,它的 sharedKey 就是 hello,unsharedKey 就是 universe。

640?wx_fmt=png
图片

DataBlock 中存储的是连续的一系列键值对,它会每隔若干个 Key 设置一个基准 Key。基准 Key 的特点就是它的 sharedKey 部分是空串。基准 Key 的位置,也就是它在块中的偏移量我们称之为「重启点」RestartPoint,在 DataBlock 中会记录所有「重启点」位置。第一个「重启点」的位置是零,也就是 DataBlock 中的第一个 Key。

struct Entry {
  varint sharedKeyLength;
  varint unsharedKeyLength;
  varint valueLength;
  byte[] unsharedKeyContent;
  byte[] valueContent;
}

struct DataBlock {
  Entry[] entries;
  int32 [] restartPointOffsets;
  int32 restartPointCount;
}

一个 DataBlock 的默认大小只有 4K 字节,所以里面包含的键值对数量通常只有几十个。如果单个键值对的内容太大一个 DataBlock 装不下咋整?

这里就必须纠正一下,DataBlock 的大小是 4K 字节,并不是说它的严格大小,而是在追加完最后一条记录之后发现超出了 4K 字节,这时就会再开启一个 DataBlock。这意味着一个 DataBlock 可以大于 4K 字节,如果 value 值非常大,那么相应的 DataBlock 也会非常大。DataBlock 并不会将同一个 Value 值分块存储。

FilterBlock 结构

如果没有开启布隆过滤器,FilterBlock 这个块就是不存在的。FilterBlock 在一个 SSTable 文件中可以存在多个,每个块存放一个过滤器数据。不过就目前 LevelDB 的实现来说它最多只能有一个过滤器,那就是布隆过滤器。

布隆过滤器用于加快 SSTable 磁盘文件的 Key 定位效率。如果没有布隆过滤器,它需要对 SSTable 进行二分查找,Key 如果不在里面,就需要进行多次 IO 读才能确定,查完了才发现原来是一场空。布隆过滤器的作用就是避免在 Key 不存在的时候浪费 IO 操作。通过查询布隆过滤器可以一次性知道 Key 有没有可能在里面。

640?wx_fmt=png
图片

单个布隆过滤器中存放的是一个定长的位图数组,该位图数组中存放了若干个 Key 的指纹信息。这若干个 Key 来源于 DataBlock 中连续的一个范围。FilterBlock 块中存在多个连续的布隆过滤器位图数组,每个数组负责指纹化 SSTable 中的一部分数据。

struct FilterEntry {
  byte[] rawbits;
}

struct FilterBlock {
  FilterEntry[n] filterEntries;
  int32[n] filterEntryOffsets;
  int32 offsetArrayOffset;
  int8 baseLg;  // 分割系数
}

// 每个 Key 占用 10bit 存放指纹信息
options.SetFilterPolicy(levigo.NewBloomFilter(10))

MetaIndexBlock 结构

MetaIndexBlock 存储了前面一系列 FilterBlock 的元信息,它在结构上和 DataBlock 是一样的,只不过里面 Entry 存储的 Key 是带固定前缀的过滤器名称,Value 是对应的 FilterBlock 在文件中的偏移量和长度。

key = "filter." + filterName
// value 定义了数据块的位置和大小
struct BlockHandler {
  varint offset;
  varint size;
}

640?wx_fmt=png
图片

IndexBlock 结构

它和 MetaIndexBlock 结构一样,也存储了一系列键值对,每一个键值对存储的是 DataBlock 的元信息,SSTable 中有几个 DataBlock,IndexBlock 中就有几个键值对。键值对的 Key 是对应 DataBlock 内部最大的 Key,Value 是 DataBlock 的偏移量和长度。不考虑 Key 之间的前缀共享,不考虑「重启点」,它的结构如下图所示

640?wx_fmt=png
图片

SSTable 的结构就讲到这里,下一节我们继续观察日志文件的结构

640?wx_fmt=png

一次点查要翻几本账:LevelDB的内存双表、布隆过滤器、分层SSTable与两级缓存解析 LevelDB以追加写换取高吞吐,读却要跨内存与多层文件找最新版本。本文依据1.23源码,梳理一次点查的完整路径:预写日志与组提交、内部键与快照、跳表MemTable与双表切换、SSTable块结构、分层合并的大小触发与查找触发、L0的三道警戒线、布隆过滤器与两级LRU缓存。复刻实验表明:每键10位过滤器误判率约0.76%,不存在键的读块次数降到约1/120;分层模拟写放大约7.1倍;块缓存命中率取决于热点分布,扫描宜关闭fill_cache。文末给出调优建议、常见误区与RocksDB对照。 阅读详情

相关推荐

LSM树:HBase与LevelDB的存储引擎

LSM树:现代数据库存储引擎的革命性设计 LSM树(Log-Structured Merge Tree)通过将随机写入转换为顺序写入,彻底改变了数据库处理海量数据的方式。其核心设计包括三个关键组件:内存缓冲区MemTable、预写日志WAL和磁盘存储SSTable,通过分层合并策略实现高效写入(比B+树快5-10倍)与查询平衡。工业级实现如LevelDB、HBase和RocksDB展示了LSM树在万亿级数据处理中的卓越性能,同时也发展出多种合并策略(Size-Tiered/Leveled)以适应不同场景。尽

JDT的专栏 1078

Leveldb源码分析--7

6 SSTable之1 SSTable是Leveldb的核心之一,是表数据最终在磁盘上的物理存储。也是体量比较大的模块。 6.1 SSTable的文件组织 作者在文档doc/table_format.txt中描述了表的逻辑结构,如图6.1-1所示。逻辑上可分为两大块,数据存储区Data Block,以及各种Meta信息。 1)文件中的k/v对是有序存储的,并且被划分到连续排列的

sparkliang的专栏 1万+

LevelDB SSTable格式详解

Google开源的LevelDB 对应了Bigtable中的tablet server

levelDB 源码分析之 SSTable

1 SSTable 基本组成 SSTable 是 levelDB 磁盘上存储数据的结构。SSTable 分为不同的层次,其中除了第 0 层的 SSTable 之外,其他各层的 SSTable 中数据的 key 的范围没有任何重叠,并且各个 SSTable 内部数据按照 key 有序排列: 对于 levelDB 中的单个 SSTable,其内部数据也是根据 key 的大小有序排列的。对于 level0 的单个 SSTable ,它是将 memtable 持久化到磁盘中形成的,其格式如下: SSTable

weixin_43374723的博客 1366

手把手教你用6轴IMU跑通LIO-SAM:参数配置与代码修改保姆级教程

本文提供了一套完整的6轴IMU适配LIO-SAM的解决方案,包括参数配置与代码修改的详细步骤。从理解6轴与9轴IMU的关键差异入手,逐步指导如何调整核心配置文件params.yaml、重构utility.h关键函数、优化mapOptimization.cpp的位姿融合逻辑,并给出编译验证与性能调优建议,帮助开发者快速实现6轴IMU在LIO-SAM中的稳定运行。

weixin_28717807的博客 357

Ubuntu 22.04下Realtek R8125网卡驱动安装避坑指南(附DKMS自动编译配置)

本文详细介绍了在Ubuntu 22.04系统上为Realtek R8125 2.5GbE网卡安装驱动的完整流程与避坑指南。针对内核通用驱动r8169的冲突问题,重点讲解了如何通过DKMS(Dynamic Kernel Module Support)实现驱动的持久化自动编译与安装,确保系统内核升级后网卡驱动依然有效。内容包括环境准备、驱动源码获取、DKMS标准配置、驱动冲突解决(设置黑名单)以及日常维护与故障排查方法,旨在为用户提供一个一劳永逸的稳定解决方案。

echo99的专栏 1023

LevelDB存储格式 —— SST文件格式(一)

leveldb是经典的LSM kv存储的代表,本文主要分析其底层数据文件的存储格式,以便之后对LSM的读写,compaction等有更透彻的理解。

cy2018的博客 3738

从零开始:QNX SDP 8.0开发环境搭建与实战入门

本文详细介绍了如何从零开始搭建QNX SDP 8.0开发环境并进行实战入门。内容涵盖许可证获取、环境安装、命令行与IDE工具使用、BSP构建、系统镜像生成,以及编写、编译和运行第一个QNX程序的全过程。旨在帮助嵌入式开发者,特别是汽车电子和工业控制领域的工程师,快速掌握这一实时操作系统(RTOS)的开发基础。

weixin_29163857的博客 642

leveldb学习

为什么80%的码农都做不了架构师?>>> ...

weixin_34050005的博客 92

AI 代码生成工具的质量评估体系

基础需求层包括响应速度(Response Time)和界面友好性(UI Friendliness),期望需求层涵盖智能提示(Smart Suggestions)和个性化配置(Personalization),兴奋需求层则涉及多模态交互(Multimodal Interaction)和代码进化(Code Evolution)。在金融领域,代码审计合规性(Compliance Audit)权重应提升至40%,而在Web开发中,API兼容性(API Compatibility)的权重需达到35%。

2503_92418637的博客 3376

LevelDB 深入解析:SSTable(Table)文件格式与 TableCache 缓存机制

本篇基于 LevelDB 官方源码的核心文件 `db/table_cache.cc`、`db/builder.cc`、`util/filename.cc` 等,系统讲解 LevelDB 持久化存储的两大基石:**SSTable(Sorted String Table,代码中常直接称为 Table)**——磁盘上排序且不可变的键值数据文件;以及 **TableCache**——为这些文件提供内存级加

gitblog_00715的博客 811

100多台物理GPU服务器,每台服务器上有8张GPU卡,组网

计算网用 IB/RoCEv2 保证低延迟高带宽,支撑 800+GPU 的分布式训练;管理网和存储网独立部署,避免干扰核心通信;全链路冗余和规范布线,确保集群稳定运行;搭配 Slurm/K8s 和监控工具,实现高效管理。该方案可支撑千亿参数大模型训练,且具备极强的扩展性,未来可平滑扩容至 200 + 台服务器。

weixin_42795092的博客 2022

levelDB的SSTable和LSM-tree

如果说protocol buffer是google事实上的individual data record 描述语言,那SSTable应该是google最流行的dataset存储、处理和交换方案之一。SSTable是高效存储大量KV数据集合的一个简单抽象,并针对高吞吐量、顺序读写负载等进行了优化。本文阐述SSTable的工作原理,以及levelDB中如何使用SSTable。 SSTable数据格式、索...

varyall的专栏 890

【GPT】Coze使用开放平台接口-【7】Dify 比较篇

coze 用于社交,dify 用来内部构建。抛开工作流,机器人,工具,coze 最大的区别在于可以直接发布到社交媒体上。所以,coze 对操作体验上也花了不少功夫,而 dify 就专注在帮助使用者打磨工作流。coze 各个大模块之前可以联动的机制也比较多,所以侧重点各不相同。

非晓为骁的博客 7615

开篇词:学习系统分析师的好处?核心考点有哪些?

系统分析师备考指南 系统分析师是IT行业的高级专业人才,具备系统分析与设计能力,能指导开发团队工作。学习系统分析师不仅能获得职业晋升的"黄金跳板",还能全面提升技术架构思维和业务理解能力。 核心价值: 职业发展:晋升管理岗位的硬性要求,突破职业天花板 能力提升:构建T型知识结构,培养架构思维和软技能 市场竞争力:成为"业务+技术"桥梁,获得国家级专业认证 考试内容: 计算机基础知识(硬件、操作系统、网络等) 系统分析专业知识(软件工程、架构设计等) 进阶知识(企业信息

数据知道的博客 5945

leveldb源码学习(二)

前台服务员(用户读写线程)只负责接单、记菜单(写内存 memtable),快速接待客人;后厨(后台 BGWork 线程)慢慢洗菜、做菜、整理库存(compaction 文件合并、刷盘);相当于领班判断:后厨空着就安排备菜,后厨忙就先不安排,不让客人等。内存两张表都没找到,才走磁盘,也就是Version优先查 L0:L0 文件 key 区间重叠,需要逐个遍历匹配;L1~Lmax:每层有序不重叠,通过二分快速定位最多一个 SST;逐层从上到下查找(上层更新,下层更旧);

weixin_62490055的博客 206

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

LevelDB 存储引擎实现解析:文件布局、分层合并与 Compaction 回收机制

> **导读**:本文基于 Bitcoin Core 仓库内嵌的 LevelDB 源码([`src/leveldb`](https://link.gitcode.com/i/e9e93524d2a7cf06d03125006e764563) 目录)与核心设计文档 [impl.md](https://link.gitcode.com/i/e9e93524d2a7cf06d03125006e76456

gitblog_00368的博客 417

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

大白话解析LevelDB: Version

在 LevelDB 中,Version 扮演着核心的角色,负责管理和维护数据库的不同版本。LevelDB 是一种基于 LSM-tree(Log-Structured Merge-tree)的键值存储,它通过创建数据的不同“版本”来优化读写操作。

sinat_38293503的博客 1650

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

leveldb深入浅出

leveldb 简介 LevelDB 是一个快速的提供持久化存储的 key/value(byte array) 存储数据库,可以把它理解为一个存储在本地磁盘的超大 map<string, string>。 其局限性有: 不是一个关系型数据库,不支持 sql 查询,不支持索引 不支持进程级别的并发 不支持类似 memcached、redis 的 c/s 架构 leveldb 的整体架...

qq_16205285的博客 654

leveldb代码阅读(13)——数据文件的格式和生成

原文地址:http://www.blogjava.net/sandy/archive/2012/03/12/leveldb4.html leveldb使用SSTable格式来保存数据。 格式为:(当前没有META BLOCK) SSTABLE = |DATA BLOCK1|DATA BLOCK2|...|DATA BLOCK N|META BLOCK1|...|META BLOCK N|

NB_vol_1的专栏 1222

Leveldb源码分析--17

10 Version分析之210.5 Version::UpdateStats()当Get操作直接搜寻memtable没有命中时,就需要调用Version::Get()函数从磁盘load数据文件并查找。如果此次Get不止seek了一个文件,就记录第一个文件到stat并返回。其后leveldb就会调用UpdateStats(stat)。Stat表明在指定key range查找key时,都要先seek

sparkliang的专栏 1万+

LevelDB 核心架构全解析:从 LSM-Tree 到九大组件的源码级实战指南

> 本文基于 [docs/LevelDB/index.md](https://link.gitcode.com/i/c3162ca093e31e3152b0a308a5815e5d) 及其 9 个章节文档编写,系统讲解 Google LevelDB 作为嵌入式 key-value 存储库的 LSM-Tree 架构:磁盘上的 SSTable 如何组织、内存中的 MemTable 如何加速写入、WAL

gitblog_00721的博客 67
上一篇: Golang之轻松化解defer的温柔陷阱
下一篇: 分布式系统技术难题--异地多活
码洞
博客等级 码龄10年 41粉丝 137原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值