RocksDB Compaction #

一、Compaction概述 #

1.1 什么是Compaction #

Compaction是RocksDB的核心维护机制,负责合并SST文件、清理无效数据和优化存储。

text
Compaction的作用:
├── 合并文件 - 将多个SST文件合并
├── 清理数据 - 删除无效的键值对
├── 降低放大 - 减少读放大和空间放大
├── 数据重组 - 优化数据布局
└── 应用压缩 - 对数据进行压缩

1.2 为什么需要Compaction #

text
没有Compaction的问题:

1. 文件数量增长
   - L0文件越来越多
   - 查找需要检查所有文件

2. 空间浪费
   - 旧版本数据未清理
   - 已删除数据占用空间

3. 读性能下降
   - 多层查找
   - 文件数量多

Compaction解决:
- 定期合并文件
- 清理无效数据
- 优化存储结构

二、Compaction类型 #

2.1 Leveled Compaction(默认) #

text
Leveled Compaction流程:

Level N → Level N+1

L0: [a-d] [c-f] [e-h] (文件可能重叠)
        ↓ Compaction
L1: [a-c] [d-f] [g-i] (文件不重叠)

特点:
- 每层大小固定倍数增长
- 文件不重叠
- 写放大较高
- 读放大较低

2.2 Tiered Compaction #

text
Tiered Compaction流程:

Level N文件累积到一定数量后合并

L0: [file1] [file2] [file3] [file4]
                ↓ 累积后合并
L1: [merged_file]

特点:
- 批量合并
- 写放大较低
- 读放大较高
- 空间放大较高

2.3 FIFO Compaction #

text
FIFO Compaction流程:

先进先出,旧数据自动删除

[oldest] → [older] → [newer] → [newest]
    ↓
  删除

特点:
- 适合时序数据
- 自动清理旧数据
- 写放大最低
- 不支持更新删除

2.4 Compaction类型对比 #

类型 写放大 读放大 空间放大 适用场景
Leveled 通用场景
Tiered 写密集型
FIFO 最低 最低 时序数据

三、Leveled Compaction详解 #

3.1 触发条件 #

cpp
#include <rocksdb/options.h>

rocksdb::Options GetCompactionOptions() {
    rocksdb::Options options;
    
    // L0文件数量触发
    options.level0_file_num_compaction_trigger = 4;
    
    // L0文件数量触发写入减速
    options.level0_slowdown_writes_trigger = 20;
    
    // L0文件数量触发写入停止
    options.level0_stop_writes_trigger = 36;
    
    // 层级大小触发
    options.max_bytes_for_level_base = 256 * 1024 * 1024;  // 256MB
    options.max_bytes_for_level_multiplier = 10;
    
    return options;
}

3.2 Compaction过程 #

text
Leveled Compaction过程:

1. 选择Compaction文件
   │
   ▼
2. 确定输入文件
   │ - Level N的选中文件
   │ - Level N+1的重叠文件
   ▼
3. 多路归并排序
   │ - 创建Iterator
   │ - 合并排序
   ▼
4. 生成新SST文件
   │ - 写入Level N+1
   │ - 应用压缩
   ▼
5. 原子更新Version
   │ - 添加新文件
   │ - 删除旧文件
   ▼
6. 完成

3.3 文件选择策略 #

text
文件选择策略:

1. 优先级计算
   - 文件大小
   - 删除数据比例
   - 读取频率

2. L0选择
   - 选择最旧的文件
   - 可能选择多个文件

3. Ln选择
   - 选择超过层级大小限制的文件
   - 考虑文件间的重叠

四、Compaction配置 #

4.1 基本配置 #

cpp
#include <rocksdb/options.h>

rocksdb::Options GetCompactionConfig() {
    rocksdb::Options options;
    
    // Compaction风格
    options.compaction_style = rocksdb::CompactionStyle::kCompactionStyleLevel;
    
    // 后台Compaction线程数
    options.max_background_compactions = 4;
    options.max_background_jobs = 8;
    
    // Compaction触发阈值
    options.level0_file_num_compaction_trigger = 4;
    
    // 层级大小配置
    options.max_bytes_for_level_base = 256 * 1024 * 1024;
    options.max_bytes_for_level_multiplier = 10;
    
    return options;
}

4.2 高级配置 #

cpp
#include <rocksdb/options.h>

rocksdb::Options GetAdvancedCompactionConfig() {
    rocksdb::Options options;
    
    // Compaction优先级
    options.compaction_pri = rocksdb::CompactionPri::kByCompensatedSize;
    
    // 目标文件大小
    options.target_file_size_base = 64 * 1024 * 1024;  // 64MB
    options.target_file_size_multiplier = 1;
    
    // 最大Compaction字节数
    options.max_compaction_bytes = 256 * 1024 * 1024;
    
    // 软链接Compaction
    options.soft_pending_compaction_bytes_limit = 64 * 1024 * 1024 * 1024;
    options.hard_pending_compaction_bytes_limit = 256 * 1024 * 1024 * 1024;
    
    return options;
}

4.3 压缩配置 #

cpp
#include <rocksdb/options.h>

rocksdb::Options GetCompressionConfig() {
    rocksdb::Options options;
    
    // 分层压缩
    options.compression_per_level = {
        rocksdb::CompressionType::kNoCompression,      // L0
        rocksdb::CompressionType::kLZ4Compression,     // L1
        rocksdb::CompressionType::kLZ4Compression,     // L2
        rocksdb::CompressionType::kZSTD,               // L3
        rocksdb::CompressionType::kZSTD,               // L4
        rocksdb::CompressionType::kZSTD,               // L5
        rocksdb::CompressionType::kZSTD                // L6
    };
    
    // 底层压缩
    options.bottommost_compression = rocksdb::CompressionType::kZSTD;
    
    return options;
}

五、手动Compaction #

5.1 CompactRange #

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

void ManualCompaction(rocksdb::DB* db) {
    rocksdb::CompactRangeOptions options;
    
    // 等待Compaction完成
    options.exclusive_manual_compaction = true;
    
    // 压缩到最底层
    options.bottommost_level_compaction = 
        rocksdb::BottommostLevelCompaction::kForce;
    
    // 对整个数据库执行Compaction
    rocksdb::Status status = db->CompactRange(options, nullptr, nullptr);
    
    if (status.ok()) {
        std::cout << "Manual compaction completed!" << std::endl;
    }
}

// 对指定范围执行Compaction
void CompactRange(rocksdb::DB* db, 
                  const std::string& start, 
                  const std::string& end) {
    
    rocksdb::CompactRangeOptions options;
    rocksdb::Slice start_slice(start);
    rocksdb::Slice end_slice(end);
    
    db->CompactRange(options, &start_slice, &end_slice);
}

5.2 CompactFiles #

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

void CompactSpecificFiles(rocksdb::DB* db,
                          int level,
                          const std::vector<std::string>& file_names) {
    
    rocksdb::CompactionOptions options;
    options.compression = rocksdb::CompressionType::kZSTD;
    options.output_file_size_limit = 64 * 1024 * 1024;
    
    rocksdb::Status status = db->CompactFiles(options, file_names, level + 1);
    
    if (status.ok()) {
        std::cout << "Files compacted successfully!" << std::endl;
    }
}

六、Compaction监控 #

6.1 监控指标 #

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

void PrintCompactionStats(rocksdb::DB* db) {
    uint64_t value;
    
    // 待Compaction字节数
    db->GetIntProperty("rocksdb.estimate-pending-compaction-bytes", &value);
    std::cout << "Pending compaction: " << value / 1024 / 1024 << " MB" << std::endl;
    
    // 正在进行的Compaction数量
    db->GetIntProperty("rocksdb.num-running-compactions", &value);
    std::cout << "Running compactions: " << value << std::endl;
    
    // 各层文件数量
    for (int level = 0; level < 7; level++) {
        std::string prop = "rocksdb.num-files-at-level" + std::to_string(level);
        db->GetIntProperty(prop, &value);
        std::cout << "Level " << level << " files: " << value << std::endl;
    }
}

6.2 Compaction统计 #

cpp
#include <rocksdb/statistics.h>

void PrintCompactionStatistics(rocksdb::DB* db) {
    auto stats = db->GetOptions().statistics;
    
    // Compaction写入字节数
    uint64_t bytes_written = stats->getTickerCount(rocksdb::COMPACT_WRITE_BYTES);
    std::cout << "Compaction write: " << bytes_written / 1024 / 1024 << " MB" << std::endl;
    
    // Compaction读取字节数
    uint64_t bytes_read = stats->getTickerCount(rocksdb::COMPACT_READ_BYTES);
    std::cout << "Compaction read: " << bytes_read / 1024 / 1024 << " MB" << std::endl;
    
    // Compaction次数
    uint64_t count = stats->getTickerCount(rocksdb::NUMBER_DB_NEXT);
    std::cout << "Compaction count: " << count << std::endl;
}

七、Compaction优化 #

7.1 性能优化 #

cpp
#include <rocksdb/options.h>

rocksdb::Options GetOptimizedCompactionOptions() {
    rocksdb::Options options;
    
    // 增加后台线程
    options.max_background_compactions = 8;
    options.max_background_jobs = 16;
    
    // 调整触发阈值
    options.level0_file_num_compaction_trigger = 8;
    
    // 增大层级大小
    options.max_bytes_for_level_base = 512 * 1024 * 1024;
    
    // 调整目标文件大小
    options.target_file_size_base = 128 * 1024 * 1024;
    
    return options;
}

7.2 写放大优化 #

cpp
#include <rocksdb/options.h>

rocksdb::Options GetWriteAmplificationOptimized() {
    rocksdb::Options options;
    
    // 使用Tiered Compaction
    options.compaction_style = rocksdb::CompactionStyle::kCompactionStyleUniversal;
    
    // Tiered Compaction配置
    options.level0_file_num_compaction_trigger = 4;
    options.level0_layer_size_compaction_trigger = 2;
    
    return options;
}

7.3 空间优化 #

cpp
#include <rocksdb/options.h>

rocksdb::Options GetSpaceOptimized() {
    rocksdb::Options options;
    
    // 使用Leveled Compaction
    options.compaction_style = rocksdb::CompactionStyle::kCompactionStyleLevel;
    
    // 更频繁的Compaction
    options.level0_file_num_compaction_trigger = 2;
    
    // 启用压缩
    options.compression = rocksdb::CompressionType::kZSTD;
    
    return options;
}

八、Compaction最佳实践 #

8.1 场景配置 #

场景 Compaction风格 配置建议
通用场景 Leveled 默认配置
写密集型 Tiered 减少写放大
时序数据 FIFO 自动清理旧数据
读密集型 Leveled 减少读放大

8.2 调优建议 #

  1. 监控Compaction状态:关注待Compaction字节数
  2. 合理设置线程数:根据CPU核心数配置
  3. 调整触发阈值:平衡写入和Compaction
  4. 选择压缩算法:平衡压缩比和CPU开销
  5. 定期手动Compaction:优化特定范围

九、总结 #

9.1 Compaction关键参数 #

参数 说明
compaction_style Compaction风格
max_background_compactions 后台线程数
level0_file_num_compaction_trigger L0触发阈值
max_bytes_for_level_base 层级基础大小

9.2 关键要点 #

  1. 核心机制:Compaction是LSM-Tree的核心维护机制
  2. 类型选择:根据场景选择合适的Compaction类型
  3. 配置优化:合理配置触发条件和线程数
  4. 监控管理:关注Compaction状态和性能
  5. 手动干预:必要时手动触发Compaction

RocksDB文档系列完成!

最后更新:2026-03-27