RocksDB压缩策略 #

一、压缩概述 #

1.1 为什么需要压缩 #

text
压缩的作用:
├── 减少存储空间 - 降低磁盘占用
├── 减少IO开销 - 更少的数据读写
├── 提高缓存效率 - 更多数据进入缓存
└── 降低成本 - 减少存储和带宽成本

压缩的代价:
├── CPU开销 - 压缩/解压消耗CPU
├── 延迟增加 - 读写需要压缩/解压
└── 内存占用 - 解压需要临时内存

1.2 支持的压缩算法 #

算法 压缩比 压缩速度 解压速度 适用场景
NoCompression 1.0x 最快 最快 临时数据、内存充足
Snappy ~2.0x 很快 很快 实时数据、低延迟
LZ4 ~2.1x 很快 平衡场景
ZSTD ~2.5-3.0x 中等 存储密集型
Zlib ~2.5-3.5x 中等 存储优先
BZip2 ~3.0-4.0x 很慢 极致压缩

二、压缩配置 #

2.1 全局压缩配置 #

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

int main() {
    rocksdb::Options options;
    options.create_if_missing = true;
    
    // 设置全局压缩算法
    options.compression = rocksdb::CompressionType::kLZ4Compression;
    
    rocksdb::DB* db;
    rocksdb::Status status = rocksdb::DB::Open(options, "/tmp/testdb", &db);
    
    if (status.ok()) {
        std::cout << "Database opened with LZ4 compression" << std::endl;
    }
    
    delete db;
    return 0;
}

2.2 分层压缩配置 #

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

rocksdb::Options GetLayeredCompressionOptions() {
    rocksdb::Options options;
    
    // 不同层级使用不同压缩算法
    std::vector<rocksdb::CompressionType> compression_per_level = {
        rocksdb::CompressionType::kNoCompression,      // L0: 无压缩,写入快
        rocksdb::CompressionType::kLZ4Compression,     // L1: LZ4压缩
        rocksdb::CompressionType::kLZ4Compression,     // L2: LZ4压缩
        rocksdb::CompressionType::kZSTD,               // L3: ZSTD压缩
        rocksdb::CompressionType::kZSTD,               // L4: ZSTD压缩
        rocksdb::CompressionType::kZSTD,               // L5: ZSTD压缩
        rocksdb::CompressionType::kZSTD                // L6: ZSTD压缩
    };
    
    options.compression_per_level = compression_per_level;
    
    return options;
}

2.3 压缩配置选项 #

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

rocksdb::Options GetCompressionOptions() {
    rocksdb::Options options;
    
    // 底层压缩(用于最底层)
    options.bottommost_compression = rocksdb::CompressionType::kZSTD;
    
    // 压缩选项
    rocksdb::CompressionOptions compression_opts;
    compression_opts.window_bits = -14;      // ZSTD窗口大小
    compression_opts.level = 3;              // 压缩级别
    compression_opts.strategy = 0;           // 压缩策略
    compression_opts.max_dict_bytes = 0;     // 字典大小
    compression_opts.zstd_max_train_bytes = 0;
    compression_opts.enabled = true;
    compression_opts.max_dict_buffer_bytes = 0;
    
    options.compression_opts = compression_opts;
    
    return options;
}

三、压缩算法详解 #

3.1 Snappy #

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

// Snappy - Google开发的高速压缩算法
// 特点:压缩速度快,解压更快,压缩比适中
// 适用:实时数据、低延迟场景

rocksdb::Options GetSnappyOptions() {
    rocksdb::Options options;
    options.compression = rocksdb::CompressionType::kSnappyCompression;
    return options;
}

3.2 LZ4 #

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

// LZ4 - 极速压缩算法
// 特点:压缩和解压都很快,压缩比略高于Snappy
// 适用:平衡压缩比和性能的场景

rocksdb::Options GetLZ4Options() {
    rocksdb::Options options;
    options.compression = rocksdb::CompressionType::kLZ4Compression;
    return options;
}

// LZ4HC - LZ4高压缩比版本
// 特点:压缩比更高,但压缩速度较慢
// 适用:写入不频繁,追求压缩比的场景

rocksdb::Options GetLZ4HCOptions() {
    rocksdb::Options options;
    options.compression = rocksdb::CompressionType::kLZ4HCCompression;
    
    // 设置压缩级别(1-12,默认9)
    options.compression_opts.level = 9;
    
    return options;
}

3.3 ZSTD #

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

// ZSTD - Facebook开发的高效压缩算法
// 特点:压缩比高,速度适中
// 适用:存储密集型、冷数据

rocksdb::Options GetZSTDOptions() {
    rocksdb::Options options;
    options.compression = rocksdb::CompressionType::kZSTD;
    
    // 设置压缩级别(1-22,默认3)
    options.compression_opts.level = 3;
    
    return options;
}

// 使用字典训练提高压缩比
rocksdb::Options GetZSTDDictOptions() {
    rocksdb::Options options;
    options.compression = rocksdb::CompressionType::kZSTD;
    
    rocksdb::CompressionOptions compression_opts;
    compression_opts.max_dict_bytes = 112640;           // 字典大小
    compression_opts.zstd_max_train_bytes = 1126400;    // 训练数据大小
    
    options.compression_opts = compression_opts;
    
    return options;
}

3.4 Zlib #

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

// Zlib - 经典压缩算法
// 特点:压缩比高,速度较慢
// 适用:存储优先、写入不频繁

rocksdb::Options GetZlibOptions() {
    rocksdb::Options options;
    options.compression = rocksdb::CompressionType::kZlibCompression;
    
    // 设置压缩级别(1-9,默认-1表示默认级别)
    options.compression_opts.level = 6;
    
    return options;
}

四、压缩策略选择 #

4.1 按场景选择 #

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

// 场景1:实时交易系统 - 低延迟优先
rocksdb::Options GetRealtimeOptions() {
    rocksdb::Options options;
    options.compression = rocksdb::CompressionType::kSnappyCompression;
    return options;
}

// 场景2:日志存储 - 存储优先
rocksdb::Options GetLogStorageOptions() {
    rocksdb::Options options;
    options.compression = rocksdb::CompressionType::kZSTD;
    options.compression_opts.level = 9;
    return options;
}

// 场景3:混合场景 - 平衡配置
rocksdb::Options GetBalancedOptions() {
    rocksdb::Options options;
    
    // L0-L2: 快速压缩
    // L3+: 高压缩比
    options.compression_per_level = {
        rocksdb::CompressionType::kNoCompression,
        rocksdb::CompressionType::kLZ4Compression,
        rocksdb::CompressionType::kLZ4Compression,
        rocksdb::CompressionType::kZSTD,
        rocksdb::CompressionType::kZSTD,
        rocksdb::CompressionType::kZSTD,
        rocksdb::CompressionType::kZSTD
    };
    
    return options;
}

// 场景4:时序数据 - 分层压缩
rocksdb::Options GetTimeSeriesOptions() {
    rocksdb::Options options;
    
    // 新数据(L0-L1): 快速压缩
    // 旧数据(L2+): 高压缩比
    options.compression_per_level = {
        rocksdb::CompressionType::kLZ4Compression,
        rocksdb::CompressionType::kLZ4Compression,
        rocksdb::CompressionType::kZSTD,
        rocksdb::CompressionType::kZSTD,
        rocksdb::CompressionType::kZSTD,
        rocksdb::CompressionType::kZSTD,
        rocksdb::CompressionType::kZSTD
    };
    
    // 底层使用最高压缩
    options.bottommost_compression = rocksdb::CompressionType::kZSTD;
    
    return options;
}

4.2 性能测试对比 #

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

void BenchmarkCompression(rocksdb::CompressionType compression, 
                          const std::string& name,
                          int num_records) {
    std::string db_path = "/tmp/bench_" + name;
    
    rocksdb::Options options;
    options.create_if_missing = true;
    options.compression = compression;
    
    rocksdb::DB* db;
    rocksdb::DB::Open(options, db_path, &db);
    
    // 写入测试
    auto start = std::chrono::high_resolution_clock::now();
    
    for (int i = 0; i < num_records; i++) {
        std::string key = "key_" + std::to_string(i);
        std::string value(1000, 'x');  // 1KB数据
        db->Put(rocksdb::WriteOptions(), key, value);
    }
    
    auto write_end = std::chrono::high_resolution_clock::now();
    
    // 读取测试
    std::string value;
    for (int i = 0; i < num_records; i++) {
        std::string key = "key_" + std::to_string(i);
        db->Get(rocksdb::ReadOptions(), key, &value);
    }
    
    auto read_end = std::chrono::high_resolution_clock::now();
    
    // 获取数据库大小
    uint64_t db_size = 0;
    db->GetIntProperty("rocksdb.total-sst-files-size", &db_size);
    
    // 输出结果
    auto write_ms = std::chrono::duration_cast<std::chrono::milliseconds>(write_end - start).count();
    auto read_ms = std::chrono::duration_cast<std::chrono::milliseconds>(read_end - write_end).count();
    
    std::cout << name << ":" << std::endl;
    std::cout << "  Write: " << write_ms << " ms" << std::endl;
    std::cout << "  Read: " << read_ms << " ms" << std::endl;
    std::cout << "  Size: " << db_size / 1024 / 1024 << " MB" << std::endl;
    
    delete db;
}

五、压缩与Compaction #

5.1 压缩在Compaction中的作用 #

text
Compaction流程中的压缩:

数据写入 → MemTable → Flush → L0 SST (无压缩/轻压缩)
                                      ↓
                              Compaction
                                      ↓
                            L1 SST (LZ4压缩)
                                      ↓
                              Compaction
                                      ↓
                            L2+ SST (ZSTD压缩)

5.2 底层压缩优化 #

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

// 底层压缩配置
rocksdb::Options GetBottommostCompressionOptions() {
    rocksdb::Options options;
    
    // 普通层级压缩
    options.compression = rocksdb::CompressionType::kLZ4Compression;
    
    // 底层(最老数据)使用最高压缩
    options.bottommost_compression = rocksdb::CompressionType::kZSTD;
    
    // 底层压缩选项
    rocksdb::CompressionOptions bottommost_opts;
    bottommost_opts.level = 19;  // ZSTD最高压缩级别
    options.bottommost_compression_opts = bottommost_opts;
    
    return options;
}

六、压缩统计 #

6.1 获取压缩统计信息 #

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

void PrintCompressionStats(rocksdb::DB* db) {
    uint64_t total_sst_size = 0;
    uint64_t uncompressed_size = 0;
    
    db->GetIntProperty("rocksdb.total-sst-files-size", &total_sst_size);
    db->GetIntProperty("rocksdb.estimate-num-keys", &uncompressed_size);
    
    std::cout << "Compression Statistics:" << std::endl;
    std::cout << "  Total SST size: " << total_sst_size / 1024 / 1024 << " MB" << std::endl;
    
    // 各层压缩统计
    for (int level = 0; level < 7; level++) {
        uint64_t level_size = 0;
        std::string prop = "rocksdb.compression-ratio-at-level" + std::to_string(level);
        
        // 注意:需要启用统计
        std::cout << "  Level " << level << " size: " << level_size << std::endl;
    }
}

七、最佳实践 #

7.1 压缩策略建议 #

场景 推荐配置 说明
实时交易 Snappy/LZ4 低延迟优先
日志存储 ZSTD 存储优先
时序数据 分层压缩 新数据快压缩,旧数据高压缩
缓存数据 无压缩 减少CPU开销
混合场景 LZ4 + ZSTD分层 平衡性能和存储

7.2 压缩级别选择 #

cpp
// 压缩级别权衡:
// - 级别越高,压缩比越大,但压缩速度越慢
// - 解压速度通常与级别无关

// ZSTD级别建议:
// 1-3: 快速压缩,适合热数据
// 4-9: 平衡压缩,适合温数据
// 10-22: 高压缩比,适合冷数据

rocksdb::Options GetZSTDFastOptions() {
    rocksdb::Options options;
    options.compression = rocksdb::CompressionType::kZSTD;
    options.compression_opts.level = 1;  // 快速压缩
    return options;
}

rocksdb::Options GetZSTDBalancedOptions() {
    rocksdb::Options options;
    options.compression = rocksdb::CompressionType::kZSTD;
    options.compression_opts.level = 3;  // 默认级别
    return options;
}

rocksdb::Options GetZSTDMaxOptions() {
    rocksdb::Options options;
    options.compression = rocksdb::CompressionType::kZSTD;
    options.compression_opts.level = 19;  // 最高压缩
    return options;
}

八、总结 #

8.1 压缩算法对比 #

算法 压缩比 速度 推荐场景
NoCompression 1.0x 最快 临时数据
Snappy ~2.0x 很快 实时数据
LZ4 ~2.1x 平衡场景
ZSTD ~2.5x 中等 存储密集
Zlib ~3.0x 极致压缩

8.2 关键要点 #

  1. 按场景选择:根据延迟和存储需求选择算法
  2. 分层压缩:不同层级使用不同压缩
  3. 底层优化:最老数据使用最高压缩
  4. 监控效果:关注压缩比和性能影响
  5. 测试验证:实际场景测试选择最优配置

下一步,让我们学习合并操作!

最后更新:2026-03-27