augurier f6580e17c2 | 1 个月前 | ||
---|---|---|---|
.github/workflows | 删除 | 1年前 | |
benchmarks | 删除 | 1年前 | |
cmake | 删除 | 5 年前 | |
db | 删除 | 1 个月前 | |
doc | 删除 | 2 年前 | |
helpers/memenv | 删除 | 2 年前 | |
include/leveldb | 删除 | 1 个月前 | |
issues | 删除 | 2 年前 | |
pics | 删除 | 1 个月前 | |
port | 删除 | 1 个月前 | |
table | 删除 | 1 个月前 | |
test | 删除 | 1 个月前 | |
third_party | 删除 | 1年前 | |
util | 删除 | 1年前 | |
.clang-format | 5 年前 | ||
.gitignore | 2 个月前 | ||
.gitmodules | 4 年前 | ||
AUTHORS | 11 年前 | ||
CMakeLists.txt | 1 个月前 | ||
CONTRIBUTING.md | 2 年前 | ||
LICENSE | 13 年前 | ||
NEWS | 13 年前 | ||
README.md | 1 个月前 | ||
TODO | 12 年前 |
实验总体上分为了两个阶段。第一个阶段修改了key的编码,增加了ttl信息,并只修改memtable中的逻辑,分割简化任务,保证编码、写入与读memtable逻辑的正确性。这可以通过插入少量数据,不触发大小合并进行阶段性测试。
第二个阶段进一步修改sstable中读取与合并的逻辑,并通过最终的测试样例。
考虑到leveldb中key本身附带有额外的信息(seq和type),我们选择将ttl的信息一并存入key中,也便于读写合并过程中直接对key进行逻辑判断,不涉及获取value的额外操作。编码修改如下: internal key中末尾的tag,原本是56位的seq加8位的type,但实际type只需要最后一位表示是否是delete,其余7位为0。为节省空间,我们用倒数第二位表示该键是否有ttl,如果有,则在tag前增加一个64位的时间戳deadTime,表示过期时间。(deadTime并不是一定有,要先依靠存储在固定位置的标识确定,所以放在tag前而非后) lookup key一定需要一个当前时间在查询中进行比较,因此不再设置标识位,仅在tag前加64位的nowTime。
新的put接口多了一个默认参数ttl,当调用时不加这个参数,则这一次写入没有ttl,与原来的leveldb写入逻辑一致。否则需要进行两处的修改:
一是writebatch中信息的记录,这里同样进行编码的修改,8位havettl接可能有的64位deadtime(当前时间+传入的ttl),以及WriteBatch::Iterate中相应的信息解码。
二是memtable::Add中对于key新的编码。
读取分为memtable和sstable两部分,在构建lookupkey时记录了当前时间。
memtable中,迭代器找到原本的位置(即同userkey,seq为查询前最大的那个),这时有了ttl需要新的判断:是否超时。超时的话迭代器继续后移,直到userkey不同了说明没找到,或是找到了没过期的数据。这样就能得到没过期的数据中,seq最大的那条。
...
除了原本提供的测试用例,新增:
GetEarlierData:该样例插入两次key相同但value不同的数据,后一次的ttl短于前一次。在后插入的数据过期,而前插入的未过期时,查询应得到前一次插入的value。
总结几个实验过程中遇到的大bug和设计问题: