实验过程记录2
实验过程记录2¶
以下内容来自ChatGPT
修改 LevelDB 的 Compaction 流程以支持 TTL 功能,需要在 Compaction 过程中检查每个键值对的过期时间,避免将已过期的数据写入新的 SSTable 文件。下面是一个详细的步骤指南:
1. 定位 Compaction 逻辑¶
LevelDB 的 Compaction 逻辑位于 db/db_impl.cc 文件中,尤其是在 DoCompactionWork 函数中。此函数负责将不同层级的 SSTable 文件合并,并根据条件将合并后的数据写入新的 SSTable。
2. 修改 Compaction 逻辑以支持 TTL¶
在 DoCompactionWork 中,对每个键值对执行过期时间检查。如果该键值对已过期,则在 Compaction 过程中将其跳过,不写入新的 SSTable 文件。
添加 TTL 检查逻辑:
- 在读取键值对时,解码出过期时间戳。
- 判断当前时间是否超过了该时间戳。如果已过期,则跳过该键值对,不写入新的 SSTable。
例如,在 DoCompactionWork 中类似于以下代码:
Iterator* input = c->input[0]->NewIterator();
for (input->SeekToFirst(); input->Valid(); input->Next()) {
ParsedInternalKey ikey;
if (!ParseInternalKey(input->key(), &ikey)) {
continue;
}
// 检查数据是否过期
if (IsExpired(input->value())) {
continue; // 跳过过期数据
}
// 如果未过期,写入新的 SSTable 文件
builder->Add(input->key(), input->value());
}
IsExpired 辅助函数:
IsExpired函数解析键值对中的过期时间,并与当前时间比较。- 该函数可以像如下实现:
bool IsExpired(const Slice& value) {
uint64_t expiry_time = DecodeExpiryTime(value); // 从 value 中提取出过期时间戳
uint64_t current_time = Env::Default()->NowMicros();
return expiry_time < current_time;
}
解析过期时间戳:
- 实现
DecodeExpiryTime函数,该函数负责解析存储在value中的过期时间戳。 - 例如,如果将
expiry_time编码在value的前 8 字节,可以这样实现:
uint64_t DecodeExpiryTime(const Slice& value) {
if (value.size() < 8) return 0; // 确保有足够空间存储时间戳
uint64_t expiry_time;
memcpy(&expiry_time, value.data(), sizeof(uint64_t));
return expiry_time;
}
在实际使用中,TTL Compaction 可以通过定期触发(例如通过手动调用 CompactRange)或在 MemTable 大小到达一定阈值时触发,从而清理过期数据。
优化 Compaction 频率和性能¶
由于频繁的 Compaction 会影响性能,建议根据过期数据量的多少来决定是否触发 Compaction。可以参考以下优化策略:
- 定期触发 Compaction:例如,每隔一段时间或在写操作达到一定量后触发一次。
- 层级选择:可以选择只对较低层级(如 L0 和 L1)的 SSTable 执行 TTL 清理,以减少高层级的 Compaction 频率。
- 跳过无过期数据的文件:在 Compaction 前预扫描 SSTable,若文件内无过期数据,则不执行 TTL 清理。
通过这些步骤和优化,Compaction 流程将能够有效地清理过期数据,实现 TTL 功能并维持较高的系统性能。
先看一下ld是怎么改的(从最开始):
db/db_impl.cc里面添加了Status DBImpl::Put(const WriteOptions& options, const Slice& key, const Slice& value, uint64_t ttl)
MemTable::Add
MemTable::Get
write_batch.cc
我稍微改了一下compactRange函数 主要是针对最后一层做compaction达到过滤目的 不过这个就要求最后一层不能超过最大的level层数 你看一下能不能给个新函数,改成,单单对这一层合并,不去找下一层的重合key值 然后最后新生成的文件放入当前level,而不是下一个level
他前天晚上的思路: 改成一次性拿到所有文件合并,而不是一层一层合并


改成一次性拿到所有文件合并,而不是一层一层合并
群里的内容:
