跳转至

实验过程记录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

他前天晚上的思路: 改成一次性拿到所有文件合并,而不是一层一层合并

image-20241103013529378

image-20241103013545055

改成一次性拿到所有文件合并,而不是一层一层合并

群里的内容:

image-20241103013640316