目录

前言

SST 文件结构

Footer

Block

SST 文件写

SST 文件读

NewReader

Seek

总结


前言

Pebble/RocksDB 作为一款高性能 kv 数据库,被 cockroachdb 等 NewSQL 数据库作为存储引擎。Pebble/RocksDB 的高性能一方面得益于其架构,另外与底层的 sst 文件高效的读也不无关系。为什么 sst 文件具有高效的读操作呢?那么从下面三个问题展开本文:

1、sst 文件结构是怎样的?

2、sst 文件怎么写?

3、sst 文件怎么读?

SST 文件结构

由图可见,sst 文件由 Footer 与 Block 两块组成,其中 Footer 可以理解为文件加载的引导数据(Block 的元数据),Block 用来存放 sst 文件的数据与元数据,具体可以分为四种:

名称 占用空间 作用
Data Block 多个 Block 存放用户的数据,kv 对
Index Block 一个 Block Data Block 的索引
Meta Block 多个 Block 存放 BloomFilter、Properity、RangeDel 等元数据
Metaindex Block 一个 Block Meta Block 的索引

Footer

1、pebble/rocksdb sst footer 结构如下

pebble/rocksdb 的 footer 是 53 byte,而 leveldb 文件的 footer 为 48 字节。主要多 checksum type 与 version 两部分。

2、pebble footer 结构体如下

type footer struct {format      TableFormat  // rocksdbv2 or leveldbchecksum    ChecksumTypemetaindexBH BlockHandleindexBH     BlockHandlefooterBH    BlockHandle
}

通过加载 footer,我们可以获取到 metaindexBH,indexBH 等元数据信息。

Block

每个 Block 在落盘时,会在末尾追加 5 个字节:compression type 和 crc。

  • compression type 占用 1 字节,代表压缩类型。
  • crc 占用 4 字节,用来校验 block 数据。

1、block data 部分结构如下

entry 代表 kv 数据;restart point 可以理解为 entrys 的索引(有点跳表的意思,用来通过二分查找快速定位到某个 key 的位置)。

2、block 结构体定义

type blockWriter struct {restartInterval int    // 几个 entry 来生成一个 restart point nEntries        intnextRestart     intbuf             []byterestarts        []uint32    // 索引的 entry 的 offset 值curKey          []bytecurValue        []byteprevKey         []bytetmp             [4]byte
}

每个 restart point 内部,entry 采用前缀压缩。

3、entry 的结构如下

举个例子,假设 restartInterval = 2,插入 <"apple", nil>, <"apricot", nil>,<"abc", "hello">则 datablock 内容如下

0 5 0 a p p l e
2 5 0 r i c o t
0 3 5 a b c h e l l o
0  // restart point int32
16 // restart point
2  // restart length

SST 文件写

writer 维护了 block 和 rangeDelBlock 两个对象,写入流程如下

  1. 根据 key 的类型,若是 RangeDelete 类型,则写入 rangeDelBlock 对象中(也可先进行进行分段为多个 tombstones,最后一起写入)。
  2. 若是其他类型,则添加到 block 对象中,若是 block 到达阈值,则进行 flush,同时更新 meta 信息。
  3. 最后 sst 关闭时,把最后一个 dataBlock、indexBlock、metaBlock、metaIndexBlock、footer 等依次写入文件。

SST 文件读

NewReader

1、从文件的后 53 字节加载 footer 的信息

footer, err := readFooter(f)

2、根据 metaindexBH,加载 metaindex 信息,进而加载 properity、range_del、filterBH 等元数据信息

func (r *Reader) readMetaindex(metaindexBH BlockHandle) error {// 1、根据 metaindexBH,加载元数据 BH 信息b, err := r.readBlock(metaindexBH, nil /* transform */, nil /* readaheadState */)if err != nil {return err}...// 2、根据元数据 BH 信息,加载 rocksdb.properties 元数据信息if bh, ok := meta[metaPropertiesName]; ok {b, err = r.readBlock(bh, nil /* transform */, nil /* readaheadState */)if err != nil {return err}r.propertiesBH = bherr := r.Properties.load(b.Get(), bh.Offset)b.Release()if err != nil {return err}}// 3、根据元数据 BH 信息,加载 rocksdb.range_del 元数据信息if bh, ok := meta[metaRangeDelV2Name]; ok {r.rangeDelBH = bh} else if bh, ok := meta[metaRangeDelName]; ok {r.rangeDelBH = bhif !r.rawTombstones {r.rangeDelTransform = r.transformRangeDelV1}}}

3、把 indexBH 等信息赋值给 reader。

Seek

1、先根据 indexBH 加载 DataBlock 的索引信息。

2、根据 key 查询 DataBlock 索引,找出 key 在哪一个 DataBlock。

3、加载 DataBlock 块,找出 key 对应的 value。

此过程中,若 filterBH 不为空,则会加载 filter 使用 Bloom 过滤器。

总结

1、sst 文件的 datablock 内数据是有序的,通过引入 restarts 实现二分查找。同时每个 restart 内的 entry 共享 key 相同前缀,从而保证了固定大小的 block 下可以存储更多的 kv 对。

2、datablock 间也是有序的,通过引入 indexblock 实现快速定位到 key 在哪一个 datablock 块内。

3、每一次读 block,都是先从 cache 中读,若 miss,再去磁盘里读取,同时放到 cache 中。

4、sst 中保存了 bloom filter 等元数据信息,进一步提升了查询数据速度。

5、range del 墓碑在写入 sst 前,均已经进行分段,读取时,直接构造迭代器使用。

以上等动作,保证了 sst 文件的读操作高性能。

若磁盘空间小,sst 文件还支持压缩,但是 cache 中缓存的 block 数据是没有压缩的。

这篇文章先聊到这里,希望对你有帮助,后面若有时间,再更下

  • 墓碑原理详解
  • 全局迭代器读取详解
  • compaction 详解

Pebble/RocksDB SST 文件详解相关推荐

  1. Linux中/proc目录下文件详解

    Linux中/proc目录下文件详解(一) 声明:可以自由转载本文,但请务必保留本文的完整性. 作者:张子坚 email:zhangzijian@163.com 说明:本文所涉及示例均在fedora ...

  2. Mybatis复习笔记3:映射文件详解

    映射文件详解 参数处理(#和$的区别) #{}:可以获取map中的值或者实体对象属性的值: ${}:可以获取map中的值或者实体对象属性的值: select * from person where i ...

  3. Android - Manifest 文件 详解

    Manifest 文件 详解 本文地址: http://blog.csdn.net/caroline_wendy/article/details/20899281 Manifest可以定义应用程序及其 ...

  4. javaweb web.xml文件详解

    web.xml文件详解 前言:一般的web工程中都会用到web.xml,web.xml主要用来配置,可以方便的开发web工程.web.xml主要用来配置Filter.Listener.Servlet等 ...

  5. oracle控制文件都一样么,Oracle控制文件详解

    一.Oracle控制文件 为二进制文件,初始化大小由CREATEDATABASE指定,可以使用RMAN备份 记录了当前数据库的结构信息,同时也包含数据文件及日志文件的信息以及相关的状态,归档信息等等 ...

  6. linux /proc目录文件详解

    Linux中/proc目录下文件详解(一) /proc文件系统下的多种文件提供的系统信息不是针对某个特定进程的,而是能够在整个系统范围的上下文中使用.可以使用的文件随系统配置的变化而变化.命令proc ...

  7. STM32(Cortex-M3)启动过程+IAR中xcl及icf文件详解

    一:STM32(Cortex-M3)启动过程(入口地址) ARM7和ARM9启动时从绝对地址0X00000000开始执行复位中断程序,即固定了复位后的起始地址,但中断向量表的位置是可变的. Corte ...

  8. /etc/passwd 文件详解

    /etc/passwd  文件详解 /etc/passwd  保存了系统中每一个用户的信息 /etc/passwd 中每个用户的信息占用了一行,也就是说这个文件有多少行,系统就有多少个用户. 要查看系 ...

  9. Linux中/proc目录下文件详解(二)

    Linux中/proc目录下文件详解(二) /proc/mdstat文件 这个文件包含了由md设备驱动程序控制的RAID设备信息. 示例: [root@localhost ~]# cat /proc/ ...

最新文章

  1. 计算机系统的安全需求的需求等级,计算机信息系统安全等级保护 通用技术要求.PDF...
  2. DataReport使用手记
  3. 2018CTF大赛学习
  4. 用ATL的W2A和A2W宏转换Unicode与ANSI字符串
  5. C和C++栈stack
  6. 构造函数 + 原型链继承 + 临摹面向对象模式的canvas动画框架
  7. Java:伪造工厂的闭包以创建域对象
  8. 前端学习(2577):Nuxt解决了什么问题
  9. mpu6050常见问题
  10. 3D图库框架范围与示例
  11. ajax直接调用数据库数据库数据库,AJAX调用mysql数据库简单例子(示例代码)
  12. 鲁大师从服务器获取信息失败怎么办,云服务器 鲁大师
  13. C语言中的逻辑移位和算术移位
  14. 我们学校一牛老师的语录
  15. 隐私合规:检测第三方SDK调用的隐私权限
  16. 解决springboot项目部署时视上传视频太大导致的内存溢出问题
  17. CentOS Linux 续存,在新的 AlmaLinux 9 中发光发热
  18. 职称计算机pptt应用模块,2016年职称计算机考试PowerPoint单选练习题4
  19. python在图片上添加文字 - cv2模块的安装与使用
  20. C#:Krypton控件使用方法详解(第一讲) —— kryptonButton

热门文章

  1. html5图片平铺的代码,jQuery图片平铺效果制作网页背景图片平铺代码
  2. 简述工业机器人示教再现的一般步骤_工业机器人示教与初识编程语言
  3. 最适合程序员口味的10部电影
  4. Python实现NBA文字直播间
  5. iOS-配置AppIcon
  6. python django及运维开发面试题总结
  7. 中小企业数字化转型的痛点分析
  8. 使用Qt创建一个C语言工程
  9. 这么简单的抓包神器?15块钱?两块钱就搞定!
  10. Everything Is Generated In Equal Probability HDU-6595 期望DP