Compaction Filter

CompactionFilter目的

  • CompactionFilter提供了一种在rocksdb进行compaction时候,根据自定义逻辑去删除/修改 key/value对的方法。这种方式可以让用户实现自定义的垃圾收集方法,比如根据业务的ttl属性删除过期keys,或删除一批范围的key,或者更新已存在key的value。

什么时候执行compactionFilter

  • 在rocksdb进行compaction的时候会调用CompactionFilter实例的方法对compaction输入的key执行filter操作,基于compaction filter的结果,compaction过程会决定它的输出keys。
    • 如果结果(filter的实例方法false)是保存这个key,则什么都不会发生
    • 如果结果是过滤掉这个key, 那么key的vlaue会被替换成删除标记(delete marker)。如果compaction的输出等级是bottom level,那么没有删除标记的key/value都会被输出。
    • 如果结果是修改value, 那么value会被替换成修改的值。
    • 如果结果(kRemoveAndSkipUntil)是删除一批范围内的keys, 那么compaction会直接删除[currnt_key, skip_until) 之间的keys直接skip到skip_until指定的key, 而不是通过对每个key的value插入删除标记来实现对key删除。这种方式删除keys的效率高,但是缺点:因为被删除的key没有被插入标记,被skip过的key的老版本key可能会出现,如果你可以确定一个key没有老版本的key,那么使用这种方式是好的。
  • 但是在flush阶段不是执行compactionFilter,虽然flush是一种特殊的compaction.

定期compaction

  • 如果compaction filter存在的话,Rocksdb可以确保固定时间后数据都会经过compaction filter,这就是通过options.periodic_compaction_seconds参数控制,设置为0,则屏蔽该特性。如果使用默认值,rocksdb会将该值设置为30天。当进行compaction时,超过30天的数据都有资格去进行compaction(有些文件可能在compaction中会一直没有被选中),而且被compaction到原来的level中。
  • 如果没有compaction filter的compaction,其只会在合并过程中删除老的key,和保证level的文件大小,但是compaction filter的实现更多时为了根据业务逻辑实现对已有数据的删除/更新等操作。

注意

  • 如果一个compaction的输入中有一个key的多个版本,则compaction filter只在最新版本上调用,如果最新版本key是有删除删除标记的话,则不会被调用。但是,如果一个删除key的删除标记在compaction的输入中不存在,那么该删除key依然会调用compaction filter。

如何实现

  • 用户程序实现CompactionFilter接口,或者CompactionFilterFactory完成自定义操作key/value的逻辑。
options.compaction_filter = new CustomCompactionFilter();
// or
options.compaction_filter_factory.reset(new CustomCompactionFilterFactory());
  • CompactionFilterFactory可以根据条件返回不同的CompactionFilter实例,而且CompactionFilterFactory可以看到Compaction的Context,比如当前是一个full compaction还是manual compaction。参数CompactionFilter::Context提供。

  • 如果实现CompactionFilter,那么需要保证其方法的线程安全,因为并行的sub-compactions会共享这一个CompactionFilter实例。但是实现CompactionFilterFactory返回的的CompactionFilter实例不需要线程安全,因为并行的sub-compactions调用CompactionFilterFactory会返回不同的实例。

  • CompactionFilter里有三个主要接口,每个接口可以让你实现不同的过滤功能:

    • 接口之一Filter, 返回true,代表该key/value会被删除,false会被留下。merge操作的后的key/value在compaction时不会经过该方法调用。
    • FilterMergeOperand在Merge操作时被调用,返回true,表明merge操作会被忽略掉和从compaction的输出中删除,而且当使用TransactionDB时,不要实现该方法。
    • FilterV2对上面两种方法的增强,如果实现这个方法,上面两种方法就不需要实现了。允许修改value,或者从当前key开始删除一批范围内的所有keys。其方法返回结果是枚举类型:Decision::kRemove, kKeep, kChangeValue,kRemoveAndSkipUntil表明了对key/vale的的filter结果。更多请看文档。
virtual bool Filter(int /*level*/, const Slice& /*key*/,
                      const Slice& /*existing_value*/,
                      std::string* /*new_value*/,
                      bool* /*value_changed*/) const {
    return false;
  }
virtual bool FilterMergeOperand(int /*level*/, const Slice& /*key*/,
                                  const Slice& /*operand*/)
 virtual Decision FilterV2(int level, const Slice& key, ValueType value_type,
                            const Slice& existing_value, std::string* new_value,
                            std::string* /*skip_until*/)

compaction分类

  • Full-compaction: 所有数据都参与这次compaction
  • Manual-compaction: 客户端主动调用执行的compaction
  • 如果不是上面两种compaction,那么就是自动发生的compaction。(比如Level-N层文件大小到达了阈值)

注意

  • 在release 6.0版本之前,Rocksdb Snapshot(比如在DB* obeject上调用GetSnapshot())之前的key/value是可以保证不变的,除非compaction filter返回IgnoreSnapshots() = true。但是在6.0之后,当compaction filter开启后,rocksdDb会在任何keys上都执行filter操作,所以snapshot将的无法保证keys视图的一致性,所以要考虑好。

SST文件的Compact

Compact的入口在db/db_impl_compaction_flush.cc的BackgroundCompaction(),我们这里依然以Leveled Compaction为例,Compaction的执行函数在CompactionJob::Run():

RocksDB会将所有的Level计算出score,经过冒泡排序,首先寻找score最高的Level,如果Level的score大于1,则选择这个Level进行Compaction
选择Level-N中尚未被Compaction的文件PickCompaction()
对于Level-0层文件,RocksDB总是选择所有的文件进行Compact执行操作,因为Level-0层的文件之间,可能会有key范围的重叠
对于Level-N层,通过GetOverlappingInputs()选取Level-N+1中与Level-N中重叠的两部分SST文件
RocksDB的CompactionIterator::SeekToFirst()将这两部分文件里所有被删除的且不存在于更高层的Level的key、重复的key、Compaction Filter中过滤的key标记为为无效
将所有有效的key写入新的SST文件
合并结束,利用VersionEdit更新VersionSet,更新统计信息

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容