一次rocksdb sst overlap的解决

由于我们使用的是tmpfs,blockbased table不能发挥最佳性能,所以把table格式从blockbased table切换成plain table,代码提交上线,一开始新服务在正常跑着,但是程序运行一天后有个实例写异常报错,业务日志如下
原始报错日志
根据日志,较新的sst,358.sst与比较老的117.sst发生了overlap。继续查看rocksdb日志,rocksdb日志,发现某个compaction任务刚结束,生成了358.sst,随后在一致性检查里报错compaction error.
此时有两个怀疑方向,1.又是硬件故障,发生了比特位翻转啥的,2.plain table有什么bug,个人更倾向于2.为了不影响用户,先临时解决问题,找到一个旧版本未报错的数据,再用adaptive table把所有table切回blockbased。同时这个问题显然和读的关系不大,把一部分实例仍保留为plain table,并且摘掉服务发现,屏蔽外界读流量。
后续果然又有实例发生类似报错,
alt text,alt text,新生成的sst,在一致性检查里出现了overlap, 其他报错日志如alt text,alt text等日志。
根据多数实例日志报错位置,对应代码为alt text, 在VersionBuilder::Rep::CheckConsistencyDetails,但是这段代码并没有什么意义,只是结果,而不能看到原因,翻看compaction选文件逻辑,从compaction选file时,打印当时的key range,看看有没有出错,alt text,alt textalt textalt textalt text,这里可以看到files_by_compaction_pri_是个重要变量,alt text,alt text,temp来自VersionStorageInfo::files_变量,继续看这个变量是如何构造的,并且尽量增加一些日志。alt textalt textalt textalt textalt textalt textalt textalt text,至此,基本上能追溯files_的构造过程了,运行,等复现。。。
发现异常,alt text,为什么version存储信息里大量sst的largest key和smallest key相等?
检查自己传入的metadata,确认不是自己传入的问题。
继续翻看入口代码CreateColumnFamilyWithImport,发现调用这个函数时传入的meta信息,居然在后续过程中会被丢掉!rocksdb最终会自己调用GetIngestFileInfo来获取传入sst的smallest key和largest key,简直太不合理了!
alt textalt text,alt textalt text,
在这里加上日志之后,已经实锤了,rocksdb自己调用GetIngestFileInfo后获得的smallest key和largest key完全相等。alt text
再看一下plain table代码,alt text,基本完全实锤了,调用seekToLast之后,没有判断iter的valid或者status,直接拿来就用了。
PR:https://github.com/facebook/rocksdb/pull/11969