RocksDB写入优化 #

一、写入性能概述 #

1.1 写入性能影响因素 #

text
写入性能影响因素:

1. WAL写入
   - sync选项影响
   - 磁盘IO速度

2. MemTable
   - 大小和数量
   - Flush速度

3. Compaction
   - 触发频率
   - 后台线程数

4. 锁竞争
   - 并发写入
   - 资源争用

1.2 写入优化目标 #

目标 说明
高吞吐 最大化写入速度
低延迟 减少写入响应时间
稳定性 避免写入抖动
可靠性 保证数据安全

二、WAL优化 #

2.1 sync选项 #

cpp
#include <rocksdb/options.h>

// 高可靠性写入
rocksdb::WriteOptions GetSyncWriteOptions() {
    rocksdb::WriteOptions options;
    options.sync = true;  // 每次写入sync到磁盘
    return options;
}

// 高性能写入
rocksdb::WriteOptions GetAsyncWriteOptions() {
    rocksdb::WriteOptions options;
    options.sync = false;  // 依赖OS刷盘
    return options;
}

// 禁用WAL
rocksdb::WriteOptions GetNoWALOptions() {
    rocksdb::WriteOptions options;
    options.disableWAL = true;  // 不写WAL
    return options;
}

2.2 sync选项性能对比 #

text
sync选项性能对比:

sync = true:
- 每次写入调用fsync
- 延迟:1-10ms
- 吞吐:1K-10K ops/s

sync = false:
- 依赖OS刷盘
- 延迟:0.1-1ms
- 吞吐:10K-100K ops/s

disableWAL = true:
- 不写WAL
- 延迟:0.01-0.1ms
- 吞吐:100K-1M ops/s
- 风险:可能丢失数据

2.3 WAL目录分离 #

cpp
#include <rocksdb/options.h>

rocksdb::Options GetSeparateWALOptions() {
    rocksdb::Options options;
    
    // WAL放在高速磁盘
    options.wal_dir = "/fast_ssd/wal";
    
    // 数据放在大容量磁盘
    // db_dir = "/large_hdd/data";
    
    return options;
}

三、MemTable优化 #

3.1 MemTable大小 #

cpp
#include <rocksdb/options.h>

// 高吞吐配置
rocksdb::Options GetLargeMemTableOptions() {
    rocksdb::Options options;
    
    options.write_buffer_size = 128 * 1024 * 1024;  // 128MB
    options.max_write_buffer_number = 8;
    
    return options;
}

// 低延迟配置
rocksdb::Options GetSmallMemTableOptions() {
    rocksdb::Options options;
    
    options.write_buffer_size = 32 * 1024 * 1024;  // 32MB
    options.max_write_buffer_number = 3;
    
    return options;
}

3.2 MemTable大小影响 #

text
MemTable大小影响:

大MemTable (128MB+):
- 优点:减少Flush频率,高吞吐
- 缺点:Flush时间长,内存占用高

小MemTable (32MB-):
- 优点:Flush快,低延迟
- 缺点:Flush频繁,影响吞吐

建议:
- 高吞吐场景:64-128MB
- 低延迟场景:32-64MB
- 内存受限:16-32MB

3.3 Flush优化 #

cpp
#include <rocksdb/options.h>

rocksdb::Options GetFlushOptions() {
    rocksdb::Options options;
    
    // 增加Flush线程
    options.max_background_flushes = 4;
    
    // 总后台任务数
    options.max_background_jobs = 16;
    
    // 调整触发阈值
    options.level0_file_num_compaction_trigger = 8;
    
    return options;
}

四、批量写入优化 #

4.1 WriteBatch使用 #

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

// 单次写入
void SingleWrites(rocksdb::DB* db, const std::vector<std::string>& keys) {
    for (const auto& key : keys) {
        db->Put(rocksdb::WriteOptions(), key, "value");
    }
}

// 批量写入
void BatchWrites(rocksdb::DB* db, const std::vector<std::string>& keys) {
    rocksdb::WriteBatch batch;
    
    for (const auto& key : keys) {
        batch.Put(key, "value");
    }
    
    db->Write(rocksdb::WriteOptions(), &batch);
}

// 批量写入性能提升:10-100倍

4.2 最优批次大小 #

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

void OptimizedBatchWrite(rocksdb::DB* db, 
                         const std::vector<std::pair<std::string, std::string>>& data,
                         size_t batch_size = 1000) {
    
    rocksdb::WriteBatch batch;
    size_t count = 0;
    
    for (const auto& [key, value] : data) {
        batch.Put(key, value);
        count++;
        
        if (count >= batch_size) {
            db->Write(rocksdb::WriteOptions(), &batch);
            batch.Clear();
            count = 0;
        }
    }
    
    // 写入剩余数据
    if (count > 0) {
        db->Write(rocksdb::WriteOptions(), &batch);
    }
}

// 推荐批次大小:
// - 实时写入:100-1000
// - 批量导入:1000-10000

五、并发写入优化 #

5.1 并发写入配置 #

cpp
#include <rocksdb/options.h>

rocksdb::Options GetConcurrentWriteOptions() {
    rocksdb::Options options;
    
    // 允许并发MemTable写入
    options.allow_concurrent_memtable_write = true;
    
    // MemTable写入线程数
    options.max_write_buffer_number = 8;
    
    // 后台线程
    options.max_background_jobs = 16;
    
    return options;
}

5.2 写入优先级 #

cpp
#include <rocksdb/options.h>

rocksdb::WriteOptions GetLowPriorityOptions() {
    rocksdb::WriteOptions options;
    options.low_pri = true;  // 低优先级写入
    return options;
}

// 使用场景:
// - 后台批量导入
// - 非关键数据写入

六、Compaction优化 #

6.1 减少Compaction干扰 #

cpp
#include <rocksdb/options.h>

rocksdb::Options GetCompactionOptimizedOptions() {
    rocksdb::Options options;
    
    // 增加后台线程
    options.max_background_compactions = 8;
    options.max_background_jobs = 16;
    
    // 调整触发阈值
    options.level0_file_num_compaction_trigger = 8;
    options.level0_slowdown_writes_trigger = 30;
    options.level0_stop_writes_trigger = 50;
    
    // 速率限制
    options.rate_limiter.reset(
        rocksdb::NewGenericRateLimiter(100 * 1024 * 1024)
    );
    
    return options;
}

6.2 使用Tiered Compaction #

cpp
#include <rocksdb/options.h>

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

七、场景优化模板 #

7.1 高吞吐场景 #

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

rocksdb::Options GetHighThroughputOptions() {
    rocksdb::Options options;
    
    // 大MemTable
    options.write_buffer_size = 128 * 1024 * 1024;
    options.max_write_buffer_number = 8;
    
    // 异步写入
    // WriteOptions.sync = false
    
    // 后台线程
    options.max_background_jobs = 16;
    
    // Compaction配置
    options.level0_file_num_compaction_trigger = 8;
    
    // 压缩
    options.compression = rocksdb::CompressionType::kLZ4Compression;
    
    return options;
}

7.2 低延迟场景 #

cpp
#include <rocksdb/options.h>

rocksdb::Options GetLowLatencyOptions() {
    rocksdb::Options options;
    
    // 小MemTable
    options.write_buffer_size = 32 * 1024 * 1024;
    options.max_write_buffer_number = 3;
    
    // 快速Flush
    options.max_background_flushes = 4;
    
    // 快速Compaction
    options.level0_file_num_compaction_trigger = 2;
    
    return options;
}

7.3 批量导入场景 #

cpp
#include <rocksdb/options.h>

rocksdb::Options GetBulkLoadOptions() {
    rocksdb::Options options;
    
    // 大MemTable
    options.write_buffer_size = 256 * 1024 * 1024;
    options.max_write_buffer_number = 8;
    
    // 禁用WAL
    // WriteOptions.disableWAL = true
    
    // 后台线程
    options.max_background_jobs = 16;
    
    // 使用FIFO Compaction
    options.compaction_style = rocksdb::CompactionStyle::kCompactionStyleFIFO;
    
    return options;
}

八、写入监控 #

8.1 写入性能指标 #

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

void PrintWriteStats(rocksdb::DB* db) {
    auto stats = db->GetOptions().statistics;
    
    // 写入次数
    uint64_t writes = stats->getTickerCount(rocksdb::NUMBER_KEYS_WRITTEN);
    std::cout << "Keys written: " << writes << std::endl;
    
    // WAL写入字节数
    uint64_t wal_bytes = stats->getTickerCount(rocksdb::WAL_FILE_BYTES);
    std::cout << "WAL bytes: " << wal_bytes / 1024 / 1024 << " MB" << std::endl;
    
    // WAL sync次数
    uint64_t wal_syncs = stats->getTickerCount(rocksdb::WAL_FILE_SYNCED);
    std::cout << "WAL syncs: " << wal_syncs << std::endl;
    
    // MemTable写入
    uint64_t memtable_bytes = stats->getTickerCount(rocksdb::BYTES_WRITTEN);
    std::cout << "Bytes written: " << memtable_bytes / 1024 / 1024 << " MB" << std::endl;
}

8.2 写入延迟监控 #

cpp
#include <rocksdb/statistics.h>

void PrintWriteLatency(rocksdb::DB* db) {
    auto stats = db->GetOptions().statistics;
    
    // 写入延迟直方图
    auto histogram = stats->getHistogramData(rocksdb::WRITE_STALL);
    
    std::cout << "Write stall:" << std::endl;
    std::cout << "  Count: " << histogram.count << std::endl;
    std::cout << "  Average: " << histogram.average << " us" << std::endl;
    std::cout << "  P50: " << histogram.median << " us" << std::endl;
    std::cout << "  P95: " << histogram.percentile95 << " us" << std::endl;
    std::cout << "  P99: " << histogram.percentile99 << " us" << std::endl;
}

九、最佳实践 #

9.1 写入优化建议 #

场景 sync MemTable 批次大小
关键数据 true 64MB 100-1000
高吞吐 false 128MB 1000-10000
低延迟 false 32MB 1-100
批量导入 disableWAL 256MB 10000+

9.2 优化步骤 #

  1. 确定场景:明确性能目标
  2. 选择配置:使用合适的模板
  3. 使用批量写入:减少IO次数
  4. 监控性能:观察写入指标
  5. 持续调优:迭代优化

十、总结 #

10.1 写入优化要点 #

优化项 方法
WAL sync=false 或 disableWAL
MemTable 调整大小和数量
批量写入 使用WriteBatch
并发 增加线程数
Compaction 调整触发阈值

10.2 关键要点 #

  1. WAL优化:根据可靠性需求选择sync选项
  2. 批量写入:使用WriteBatch减少IO
  3. MemTable配置:根据场景调整大小
  4. 后台线程:增加并行处理能力
  5. 监控调优:持续监控和优化

下一步,让我们学习读取优化!

最后更新:2026-03-27