diff --git a/README.md b/README.md index 7463265..b41f096 100644 --- a/README.md +++ b/README.md @@ -107,6 +107,24 @@ void DBImpl::CompactRange(const Slice* begin, const Slice* end) { } ``` +在DoCompactionWork函数中判断当前遍历的key所对应的value是否过期:如果已经过期, +就将该kv对应的drop标志设置为true,确保在合并是该kv被丢弃。 +``` + Slice value_ddl = input->value(); + std::string value = value_ddl.ToString(); + size_t pos = value.find_last_of('_'); + if (pos != std::string::npos) { + std::string substring = value.substr(pos + 1); + auto ddl = static_cast(std::stoll(substring)); + auto now = std::chrono::system_clock::now(); + auto timestamp = std::chrono::duration_cast(now.time_since_epoch()).count(); + auto microsecondsTimestamp = static_cast(timestamp); + if (ddl <= microsecondsTimestamp) { + drop = true; + } + } +``` + ## 实验中遇到的问题 ### 1. TTL存储的位置以及存储方式 我们最初的想法是把TTL跟value存储在一起,形式为``,这样Put操作会很简单,仅仅把两个字符串拼接起来即可,但这样的话,在Get操作中时,无法判断从何处分割TTL和value,所以我们决定在TTL和value之间添加一个标志符,存放形式改为``,这样,在Get操作时,只需先找到第一个下划线,下划线前面的为TTL,后面的为value,这样就能把TTL和value区分开来。但还有一个问题,判断条件为:`写入数据的时间+ TTL < 读取数据的时间 `,如果仅存放TTL,虽然在调用get时我们可以获得读取数据的时间,并通过解码value获得TTL,但我们没有办法获得写入数据的时间,所以只能通过在Put操作时,把写入数据的时间也写入value中,这样在Get时,就能获得写入数据的时间,从而判断是否过期。所以,我们又把value的形式改为``,这样,通过两个下划线把TTL、写入时间和value区分开来,就能实现在get操作时判断是否过期。但我们又想到,既然在get操作解码得到TTL和写入时间之后要加在一块,并且TTL和写入时间都是在get操作时与value进行编码,那么我们为什么不在get操作时就把TTL和写入时间加在一起,再与value编码呢,把写入时间+TTL记为DDL,这样就可以把value编码为``,在get操作时,只需解码得到DDL,然后拿当前时间跟DDL作比较,即可知道数据是否过期。