项目是按照“Tair LDB基于Prefixkey的范围查找性能优化项目提议方案”的步骤一步步完成的,目前方案中提出的三个重点问题已经全部解决,如下所示:
- 如何获取key的prefix_size问题:Tair LDB基于Prefixkey的范围查找性能优化项目之如何提取key的prefix_size
- 如何建立prefix bloomfilter:Tair LDB基于Prefixkey的范围查找性能优化项目之如何建立prefix bloomfilter
- 如何在get_range过程中使用prefix bloomfilter进行prefix key过滤:Tair LDB基于Prefixkey的范围查找性能优化项目之如何使用prefix bloomfilter进行过滤
虽然已经使用prefix bloomfilter对prefix key进行过滤来提升范围查找的性能,经过实验测试也达到了一定的效果。但是这个问题的解决方案又导致了新问题的产生,即产生了下面两个问题:
问题1. ldb_instance.cpp(客户端和ldb底层交互的接口)中还有类似begin_scan(扫描某一个bucket)的接口。这些scan的key是没有prefixkey的,且编码信息也不完整(并非是前几次文章所说的前面9字节元信息和area信息编码+后面8字节sequence和valueType编码)。如果这时候也按之前的方法提取prefix key必然会产生错误,而且这种情况也不需要prefix key和bloomfilter,因此需要这块需要考虑。
问题2. delete的时候也需要带入prefix的相关信息。 如果不带,那么在get_range的时候,可能会出现已经delete了,但是依然被扫描出来了。 这个怎么理解呢?一开始我也没搞明白,因为觉得delete操作是根据delete标记来判断是否查找到的数据是否是delete过的,如果是就不取就是了,跟prefix key没什么关系。后来在导师的指导下才彻底搞懂,原来自己忽略了一个非常重要的事实:delete和put相同的某个key可能存储在sst不同的block上,甚至在不同的sst文件里。下面是导师的指导:
1. bloomfilter是在sst的block中的。
2. prefix_put时,会在某个sst(比如B)中写入该prefixkey bloomfilter
3. prefix_remove的时候(即delete时),该delete key在其他sst的可能性非常大。 而其它sst中是没有该prefix key的bloomfilter。 而其它sst(比如A)一般会在低层level
4. get_range中用merge iterator遍历时,遍历到A时,先判断prefixkey bloomfilter,结果为无(因为A的prefix bloomfilter中没有存储delete key的prefix,因此这次判断实际上是错误的),则遍历B,判断prefixkey bloomfilter,结果为有。最终结果暴露了本该删除的数据
问题来了就要解决,下面是在导师指导及自己思考下提供的解决方案,方案不唯一,这里提供一个参考。
问题1解决方案
对于类似begin_scan里的key没有prefix的情况,需要在prefix bloomfilter过滤之前进行判断,如果是这种情况的key则不需要经过bloomfilter。对于这个问题,有两种解决方案:
方法1:通过每次操作的option传入参数,这里的option指的是ReadOptions,在里面添加参数bool use_prefix_bloom;默认值是true,然后在begin_scan等方法中在扫描之前设置该参数为false,下面是添加了use_prefix_bloom参数的ReadOptions:
// Options that control read operations
struct ReadOptions {
// If true, all data read from underlying storage will be
// verified against corresponding checksums.
// Default: false
bool verify_checksums;
// Should the data read for this iteration be cached in memory?
// Callers may wish to set this field to false for bulk scans.
// Default: true
bool fill_cache;
// If "snapshot" is non-NULL, read as of the supplied snapshot
// (which must belong to the DB that is being read and which must
// not have been released). If "snapshot" is NULL, use an impliicit
// snapshot of the state at the beginning of this read operation.
// Default: NULL
const Snapshot* snapshot;
bool use_prefix_bloom;
ReadOptions()
: verify_checksums

本文记录了Tair LDB基于Prefixkey的范围查找性能优化项目后遇到的问题及其解决方案。问题包括:无prefixkey的scan接口处理和delete时携带prefix信息。解决方案涉及ReadOptions参数调整、特殊key的识别以及Delete操作中添加Prefix key支持。
4001

被折叠的 条评论
为什么被折叠?



