RocksDB SST文件 #

一、SST文件概述 #

1.1 什么是SST文件 #

SST(Sorted String Table)文件是RocksDB在磁盘上存储数据的格式,是有序的键值对集合。

text
SST文件特点:
├── 有序存储 - 键按字典序排列
├── 不可变 - 一旦写入不再修改
├── 压缩存储 - 支持多种压缩算法
└── 索引结构 - 支持高效查找

1.2 SST文件命名 #

text
文件命名格式:<number>.sst

示例:
000001.sst
000002.sst
000003.sst

文件编号全局唯一,递增分配

二、SST文件结构 #

2.1 整体布局 #

text
┌────────────────────────────────────────────────────┐
│                  Data Block 1                       │
├────────────────────────────────────────────────────┤
│                  Data Block 2                       │
├────────────────────────────────────────────────────┤
│                     ...                             │
├────────────────────────────────────────────────────┤
│                  Data Block N                       │
├────────────────────────────────────────────────────┤
│               Meta Block (Filter)                   │
├────────────────────────────────────────────────────┤
│               Meta Block (Index)                    │
├────────────────────────────────────────────────────┤
│               Meta Index Block                      │
├────────────────────────────────────────────────────┤
│                  Index Block                        │
├────────────────────────────────────────────────────┤
│                   Footer                            │
└────────────────────────────────────────────────────┘

2.2 各部分说明 #

部分 说明
Data Block 存储实际键值对数据
Meta Block 存储元数据(布隆过滤器等)
Meta Index Block 元数据索引
Index Block 数据块索引
Footer 文件元信息,指向各索引块

三、Data Block #

3.1 Data Block结构 #

text
┌────────────────────────────────────────────────────┐
│                   Block Header                      │
│  ┌──────────────────────────────────────────────┐ │
│  │ Block Type (1B) │ Size (2B) │ CRC (4B)       │ │
│  └──────────────────────────────────────────────┘ │
├────────────────────────────────────────────────────┤
│                  KV Entries                         │
│  ┌──────────────────────────────────────────────┐ │
│  │ Entry 1: Shared | Unshared | Value Length    │ │
│  │          Shared Key | Unshared Key | Value   │ │
│  ├──────────────────────────────────────────────┤ │
│  │ Entry 2: ...                                  │ │
│  ├──────────────────────────────────────────────┤ │
│  │ ...                                           │ │
│  └──────────────────────────────────────────────┘ │
├────────────────────────────────────────────────────┤
│                  Restart Points                     │
│  ┌──────────────────────────────────────────────┐ │
│  │ Restart Point 1 | Restart Point 2 | ...      │ │
│  └──────────────────────────────────────────────┘ │
├────────────────────────────────────────────────────┤
│              Restart Points Count (4B)             │
└────────────────────────────────────────────────────┘

3.2 键前缀压缩 #

text
前缀压缩原理:

原始数据:
key1: "user:1001:name"
key2: "user:1001:age"
key3: "user:1001:email"

压缩后存储:
Entry 1: shared=0,  key="user:1001:name",  value="Alice"
Entry 2: shared=11, key="age",             value="25"
Entry 3: shared=11, key="email",           value="alice@example.com"

Restart Points:
- 每16个Entry设置一个Restart Point
- Restart Point处不使用前缀压缩
- 支持二分查找

3.3 Block配置 #

cpp
#include <rocksdb/table.h>

rocksdb::BlockBasedTableOptions GetBlockOptions() {
    rocksdb::BlockBasedTableOptions options;
    
    // Block大小
    options.block_size = 4 * 1024;  // 4KB
    
    // Block大小偏差
    options.block_size_deviation = 10;  // 10%
    
    // Restart Point间隔
    options.block_restart_interval = 16;
    
    // 索引类型
    options.index_type = rocksdb::BlockBasedTableOptions::kBinarySearch;
    
    return options;
}

四、Index Block #

4.1 Index Block结构 #

text
Index Block存储Data Block的索引信息:

┌────────────────────────────────────────────────────┐
│ Index Entry 1                                      │
│  ┌──────────────────────────────────────────────┐ │
│  │ Max Key in Block 1 | Block 1 Offset | Size   │ │
│  └──────────────────────────────────────────────┘ │
├────────────────────────────────────────────────────┤
│ Index Entry 2                                      │
│  ┌──────────────────────────────────────────────┐ │
│  │ Max Key in Block 2 | Block 2 Offset | Size   │ │
│  └──────────────────────────────────────────────┘ │
├────────────────────────────────────────────────────┤
│                    ...                             │
└────────────────────────────────────────────────────┘

查找过程:
1. 二分查找Index Block
2. 定位到目标Data Block
3. 在Data Block内查找

4.2 索引类型 #

cpp
#include <rocksdb/table.h>

// 1. 二分查找索引(默认)
options.index_type = rocksdb::BlockBasedTableOptions::kBinarySearch;

// 2. 哈希索引(适合点查询)
options.index_type = rocksdb::BlockBasedTableOptions::kHashSearch;
options.prefix_extractor.reset(rocksdb::NewFixedPrefixTransform(5));

// 3. 二路搜索索引
options.index_type = rocksdb::BlockBasedTableOptions::kTwoLevelIndexSearch;

五、Filter Block #

5.1 布隆过滤器 #

cpp
#include <rocksdb/table.h>
#include <rocksdb/filter_policy.h>

rocksdb::BlockBasedTableOptions GetFilterOptions() {
    rocksdb::BlockBasedTableOptions options;
    
    // 创建布隆过滤器
    options.filter_policy.reset(
        rocksdb::NewBloomFilterPolicy(10)  // 10 bits per key
    );
    
    // 过滤器位置
    options.optimize_filters_for_memory = false;
    
    // 全键过滤
    options.whole_key_filtering = true;
    
    return options;
}

5.2 Filter Block结构 #

text
Filter Block结构:

┌────────────────────────────────────────────────────┐
│                  Filter Data                        │
│  ┌──────────────────────────────────────────────┐ │
│  │ Bloom Filter Bits Array                      │ │
│  └──────────────────────────────────────────────┘ │
├────────────────────────────────────────────────────┤
│                  Filter Offsets                    │
│  ┌──────────────────────────────────────────────┐ │
│  │ Offset 1 | Offset 2 | ...                    │ │
│  └──────────────────────────────────────────────┘ │
├────────────────────────────────────────────────────┤
│             Filter Offset Array Offset             │
├────────────────────────────────────────────────────┤
│                  Base Log Value                    │
└────────────────────────────────────────────────────┘

5.3 布隆过滤器原理 #

text
布隆过滤器工作原理:

插入:
key → hash1(key), hash2(key), ... → 设置对应bit位

查询:
key → hash1(key), hash2(key), ... → 检查对应bit位

结果:
- 所有bit为1 → 可能存在(需进一步确认)
- 有bit为0   → 一定不存在(直接跳过)

参数:
- bits_per_key: 每个key分配的bit数
- 假阳性率 ≈ (1 - e^(-kn/m))^k
  - k: hash函数数量
  - n: key数量
  - m: bit数组大小

六、Footer #

6.1 Footer结构 #

text
Footer结构(48字节):

┌────────────────────────────────────────────────────┐
│             Meta Index Block Handle                 │
│  ┌──────────────────────────────────────────────┐ │
│  │ Offset (8B) | Size (8B)                      │ │
│  └──────────────────────────────────────────────┘ │
├────────────────────────────────────────────────────┤
│              Index Block Handle                    │
│  ┌──────────────────────────────────────────────┐ │
│  │ Offset (8B) | Size (8B)                      │ │
│  └──────────────────────────────────────────────┘ │
├────────────────────────────────────────────────────┤
│                Padding (4B)                        │
├────────────────────────────────────────────────────┤
│             Checksum Type (1B)                     │
├────────────────────────────────────────────────────┤
│             Magic Number (8B)                      │
│           0x88e241b785f4cff7                       │
└────────────────────────────────────────────────────┘

6.2 Footer作用 #

text
Footer的作用:
1. 定位Index Block
2. 定位Meta Index Block
3. 文件完整性校验
4. 版本识别

七、SST文件读取 #

7.1 读取流程 #

text
读取一个key的流程:

1. 读取Footer
   ↓
2. 获取Index Block位置
   ↓
3. 读取Index Block
   ↓
4. 二分查找定位Data Block
   ↓
5. 检查Filter Block(布隆过滤器)
   ↓
6. 读取Data Block
   ↓
7. 在Data Block内查找key

7.2 Block Cache #

cpp
#include <rocksdb/table.h>
#include <rocksdb/cache.h>

// 配置Block Cache
rocksdb::BlockBasedTableOptions table_options;

// LRU缓存
table_options.block_cache = rocksdb::NewLRUCache(
    1024 * 1024 * 1024,  // 1GB容量
    8                      // 分片数
);

// 压缩块缓存
table_options.block_cache_compressed = rocksdb::NewLRUCache(
    256 * 1024 * 1024  // 256MB
);

options.table_factory.reset(
    rocksdb::NewBlockBasedTableFactory(table_options)
);

八、SST文件工具 #

8.1 sst_dump工具 #

bash
# 查看SST文件信息
sst_dump --file=/path/to/file.sst --command=scan

# 查看文件属性
sst_dump --file=/path/to/file.sst --command=stats

# 导出数据
sst_dump --file=/path/to/file.sst --command=scan --output_format=escaped

# 验证文件
sst_dump --file=/path/to/file.sst --command=verify

8.2 ldb工具 #

bash
# 查看SST文件内容
ldb dump --file=/path/to/file.sst

# 查看数据库所有SST文件
ldb list_file_nums /path/to/db

# 导出整个数据库
ldb dump /path/to/db > dump.txt

九、SST文件管理 #

9.1 文件生命周期 #

text
SST文件生命周期:

1. 创建
   - MemTable Flush
   - Compaction
   - 外部导入

2. 使用
   - 读取数据
   - Compaction输入

3. 删除
   - Compaction完成后
   - 手动清理

9.2 文件统计 #

cpp
#include <rocksdb/db.h>
#include <iostream>

void PrintSSTStats(rocksdb::DB* db) {
    // 各层文件数量
    for (int level = 0; level < 7; level++) {
        uint64_t num_files = 0;
        std::string prop = "rocksdb.num-files-at-level" + std::to_string(level);
        db->GetIntProperty(prop, &num_files);
        std::cout << "Level " << level << ": " << num_files << " files" << std::endl;
    }
    
    // 总SST文件大小
    uint64_t total_size = 0;
    db->GetIntProperty("rocksdb.total-sst-files-size", &total_size);
    std::cout << "Total SST size: " << total_size / 1024 / 1024 << " MB" << std::endl;
}

十、总结 #

10.1 SST文件结构速查 #

部分 大小 作用
Data Block 可变 存储键值对
Filter Block 可变 布隆过滤器
Index Block 可变 数据块索引
Footer 48B 文件元信息

10.2 关键要点 #

  1. 有序存储:键按字典序排列
  2. 前缀压缩:减少键存储空间
  3. 索引结构:支持高效查找
  4. 布隆过滤器:加速不存在键的判断
  5. Block Cache:缓存热数据块

下一步,让我们学习MemTable结构!

最后更新:2026-03-27