RocksDB缓存策略 #
一、缓存概述 #
1.1 RocksDB缓存层次 #
text
RocksDB缓存层次:
读取请求
│
▼
┌─────────────────┐
│ MemTable │ ← 内存写入缓冲
└────────┬────────┘
│ 未命中
▼
┌─────────────────┐
│ Block Cache │ ← LRU缓存
└────────┬────────┘
│ 未命中
▼
┌─────────────────┐
│ OS Page Cache │ ← 操作系统缓存
└────────┬────────┘
│ 未命中
▼
┌─────────────────┐
│ 磁盘 │
└─────────────────┘
1.2 缓存类型 #
| 缓存类型 | 位置 | 作用 |
|---|---|---|
| MemTable | 内存 | 写入缓冲,最新数据 |
| Block Cache | 内存 | 热数据块缓存 |
| Compressed Cache | 内存 | 压缩块缓存 |
| OS Page Cache | 内核 | 文件系统缓存 |
二、Block Cache #
2.1 创建Block Cache #
cpp
#include <rocksdb/cache.h>
#include <rocksdb/table.h>
// 创建LRU缓存
std::shared_ptr<rocksdb::Cache> CreateBlockCache(size_t capacity) {
return rocksdb::NewLRUCache(
capacity, // 缓存容量
8, // 分片数
false, // 是否使用高优先级
0.0 // 高优先级比例
);
}
// 使用Block Cache
rocksdb::BlockBasedTableOptions table_options;
table_options.block_cache = CreateBlockCache(1024 * 1024 * 1024); // 1GB
rocksdb::Options options;
options.table_factory.reset(
rocksdb::NewBlockBasedTableFactory(table_options)
);
2.2 LRU缓存参数 #
cpp
#include <rocksdb/cache.h>
std::shared_ptr<rocksdb::Cache> CreateOptimizedCache() {
return rocksdb::NewLRUCache(
2 * 1024 * 1024 * 1024, // 容量:2GB
16, // 分片数:16(减少锁竞争)
true, // 使用高优先级队列
0.5 // 高优先级比例:50%
);
}
// 分片数建议:
// - 小缓存:4-8
// - 中等缓存:8-16
// - 大缓存:16-32
2.3 缓存优先级 #
cpp
#include <rocksdb/cache.h>
#include <rocksdb/table.h>
rocksdb::BlockBasedTableOptions GetPriorityCacheOptions() {
rocksdb::BlockBasedTableOptions options;
// 创建带优先级的缓存
options.block_cache = rocksdb::NewLRUCache(
1024 * 1024 * 1024,
8,
true, // 启用高优先级
0.3 // 30%高优先级空间
);
// Pin重要块
options.pin_l0_filter_and_index_blocks_in_cache = true;
options.pin_top_level_index_and_filter = true;
return options;
}
三、压缩块缓存 #
3.1 配置压缩块缓存 #
cpp
#include <rocksdb/cache.h>
#include <rocksdb/table.h>
rocksdb::BlockBasedTableOptions GetCompressedCacheOptions() {
rocksdb::BlockBasedTableOptions options;
// 主缓存(解压后数据)
options.block_cache = rocksdb::NewLRUCache(
2 * 1024 * 1024 * 1024 // 2GB
);
// 压缩块缓存(压缩数据)
options.block_cache_compressed = rocksdb::NewLRUCache(
512 * 1024 * 1024 // 512MB
);
return options;
}
3.2 压缩缓存作用 #
text
压缩块缓存工作流程:
读取请求
│
▼
检查Block Cache(解压数据)
│ 未命中
▼
检查Compressed Cache(压缩数据)
│ 命中
▼
解压数据
│
▼
放入Block Cache
│
▼
返回数据
优点:
- 节省内存空间
- 减少磁盘读取
- 适合压缩比高的场景
四、缓存策略 #
4.1 缓存填充策略 #
cpp
#include <rocksdb/options.h>
// 读取时填充缓存
rocksdb::ReadOptions GetFillCacheOptions() {
rocksdb::ReadOptions options;
options.fill_cache = true; // 默认值
return options;
}
// 大范围扫描不填充缓存
rocksdb::ReadOptions GetNoFillCacheOptions() {
rocksdb::ReadOptions options;
options.fill_cache = false; // 避免污染缓存
return options;
}
4.2 缓存预读 #
cpp
#include <rocksdb/options.h>
rocksdb::ReadOptions GetReadaheadOptions() {
rocksdb::ReadOptions options;
// 设置预读大小
options.readahead_size = 256 * 1024; // 256KB
// 自动预读
options.auto_readahead_size = true;
return options;
}
4.3 缓存Pin策略 #
cpp
#include <rocksdb/table.h>
rocksdb::BlockBasedTableOptions GetPinOptions() {
rocksdb::BlockBasedTableOptions options;
// Pin L0的Filter和Index
options.pin_l0_filter_and_index_blocks_in_cache = true;
// Pin顶层Index和Filter
options.pin_top_level_index_and_filter = true;
return options;
}
五、缓存优化 #
5.1 读密集场景 #
cpp
#include <rocksdb/cache.h>
#include <rocksdb/table.h>
rocksdb::Options GetReadOptimizedOptions() {
rocksdb::Options options;
rocksdb::BlockBasedTableOptions table_options;
// 大容量缓存
table_options.block_cache = rocksdb::NewLRUCache(
4 * 1024 * 1024 * 1024, // 4GB
16
);
// 压缩缓存
table_options.block_cache_compressed = rocksdb::NewLRUCache(
1 * 1024 * 1024 * 1024 // 1GB
);
// Pin重要块
table_options.pin_l0_filter_and_index_blocks_in_cache = true;
// 布隆过滤器
table_options.filter_policy.reset(
rocksdb::NewBloomFilterPolicy(10)
);
options.table_factory.reset(
rocksdb::NewBlockBasedTableFactory(table_options)
);
return options;
}
5.2 写密集场景 #
cpp
#include <rocksdb/options.h>
#include <rocksdb/table.h>
rocksdb::Options GetWriteOptimizedOptions() {
rocksdb::Options options;
// 大MemTable
options.write_buffer_size = 128 * 1024 * 1024;
options.max_write_buffer_number = 8;
// 中等Block Cache
rocksdb::BlockBasedTableOptions table_options;
table_options.block_cache = rocksdb::NewLRUCache(
1 * 1024 * 1024 * 1024 // 1GB
);
options.table_factory.reset(
rocksdb::NewBlockBasedTableFactory(table_options)
);
return options;
}
5.3 内存受限场景 #
cpp
#include <rocksdb/options.h>
#include <rocksdb/table.h>
rocksdb::Options GetMemoryConstrainedOptions() {
rocksdb::Options options;
rocksdb::BlockBasedTableOptions table_options;
// 小缓存
table_options.block_cache = rocksdb::NewLRUCache(
256 * 1024 * 1024 // 256MB
);
// 不使用压缩缓存
table_options.block_cache_compressed = nullptr;
// 高压缩比
options.compression = rocksdb::CompressionType::kZSTD;
options.table_factory.reset(
rocksdb::NewBlockBasedTableFactory(table_options)
);
return options;
}
六、缓存监控 #
6.1 缓存统计 #
cpp
#include <rocksdb/db.h>
#include <rocksdb/cache.h>
#include <iostream>
void PrintCacheStats(rocksdb::DB* db) {
// 获取缓存使用量
uint64_t usage;
db->GetIntProperty("rocksdb.block-cache-usage", &usage);
std::cout << "Block cache usage: " << usage / 1024 / 1024 << " MB" << std::endl;
// Pin使用量
db->GetIntProperty("rocksdb.block-cache-pinned-usage", &usage);
std::cout << "Pinned usage: " << usage / 1024 / 1024 << " MB" << std::endl;
// 缓存容量
auto cache = db->GetOptions().table_factory->GetOptions<rocksdb::BlockBasedTableOptions>()->block_cache;
std::cout << "Cache capacity: " << cache->GetCapacity() / 1024 / 1024 << " MB" << std::endl;
}
6.2 缓存命中率 #
cpp
#include <rocksdb/statistics.h>
#include <iostream>
void PrintCacheHitRate(rocksdb::DB* db) {
auto stats = db->GetOptions().statistics;
uint64_t hits = stats->getTickerCount(rocksdb::BLOCK_CACHE_HIT);
uint64_t misses = stats->getTickerCount(rocksdb::BLOCK_CACHE_MISS);
uint64_t total = hits + misses;
if (total > 0) {
double hit_rate = (double)hits / total * 100;
std::cout << "Block cache hit rate: " << hit_rate << "%" << std::endl;
std::cout << "Hits: " << hits << ", Misses: " << misses << std::endl;
}
// 数据块命中
hits = stats->getTickerCount(rocksdb::BLOCK_CACHE_DATA_HIT);
misses = stats->getTickerCount(rocksdb::BLOCK_CACHE_DATA_MISS);
std::cout << "Data block hit rate: " << (double)hits / (hits + misses) * 100 << "%" << std::endl;
// 索引块命中
hits = stats->getTickerCount(rocksdb::BLOCK_CACHE_INDEX_HIT);
misses = stats->getTickerCount(rocksdb::BLOCK_CACHE_INDEX_MISS);
std::cout << "Index block hit rate: " << (double)hits / (hits + misses) * 100 << "%" << std::endl;
// 过滤器块命中
hits = stats->getTickerCount(rocksdb::BLOCK_CACHE_FILTER_HIT);
misses = stats->getTickerCount(rocksdb::BLOCK_CACHE_FILTER_MISS);
std::cout << "Filter block hit rate: " << (double)hits / (hits + misses) * 100 << "%" << std::endl;
}
七、缓存最佳实践 #
7.1 缓存大小建议 #
| 场景 | Block Cache | 压缩缓存 | 说明 |
|---|---|---|---|
| 读密集 | 50-60%内存 | 10-20% | 大缓存 |
| 写密集 | 20-30%内存 | 5-10% | 中等缓存 |
| 平衡 | 40-50%内存 | 10-15% | 均衡配置 |
| 内存受限 | 30-40%内存 | 不使用 | 小缓存 |
7.2 缓存优化建议 #
- 合理设置大小:根据可用内存和场景
- 监控命中率:关注缓存效果
- 避免污染:大扫描不填充缓存
- Pin重要块:索引和过滤器
- 使用压缩缓存:节省内存空间
八、总结 #
8.1 缓存配置速查 #
| 配置 | 参数 | 说明 |
|---|---|---|
| 缓存容量 | NewLRUCache(capacity) | 设置缓存大小 |
| 分片数 | NewLRUCache(capacity, shards) | 减少锁竞争 |
| 压缩缓存 | block_cache_compressed | 缓存压缩数据 |
| Pin策略 | pin_l0_filter_and_index | Pin重要块 |
| 填充策略 | fill_cache | 是否填充缓存 |
8.2 关键要点 #
- 分层缓存:MemTable → Block Cache → 磁盘
- LRU策略:自动淘汰冷数据
- 优先级:保护重要数据
- 监控优化:持续关注命中率
- 场景配置:根据场景调整
下一步,让我们学习写入优化!
最后更新:2026-03-27