使用 NovelLSM 为 NVM 重新设计 LSM

最近比较关注 Nonvolatile Memory 相关的技术,也发现业界现在对这块的研究越来越多了,刚好看到了一篇 Redesigning LSMs for Nonvolatile Memory with NoveLSM,讲的是如何在 NVM 上面重新设计和优化 LSM,这一下子就引起了我的兴趣,毕竟我们现在也在基于 RocksDB 构建新的存储引擎,另外也跟一些团队在研究改引擎在 Intel 新的硬件下面的优化,另外在加上作者来自威斯康星大学,自然就有了好好研究一下的想法。

LSM 问题

大家知道,LSM 是现今用的非常广泛的一种技术,很多存储引擎都是基于它来实现的,包括 LevelDB,BigTable,以及我们 TiKV 用的 RocksDB。LSM 对写入很友好,在读上面也有不错的性能,但 LSM 并不是万能的,还是有一些问题,首当其冲的就是写放大以及写放大的带来的操作的 latency 上升。

大家对 LSM 的 insert 流程应该比较熟悉,主要有几个步骤:

  1. 写入到 WAL
  2. 写入到 memtable,通常都是一个 skip list
  3. 当 memtable 满了,就变成 immutable memtable
  4. 一个后台线程会将 immutable memtable flush 到磁盘,放到 Level 0 层
  5. 后台线程继续 compaction,将 Level 0 的 SST 逐层的放到下层

这里会有几个问题,在 4 那一步中,如果写入太快,造成之前的 immutable memtable 还没 flush 到磁盘,就会造成 stall。另外,就是在 5,如果 flush 的太快,compaction 进行的太慢,造成 Level 0 有太多的文件,也会造成 stall。当然,如果 compaction 在其他几层有累积,造成大量的 SST 没法 compaction,也会 stall。这些都会影响 insert 的 latency,而且 insert 的 value size 越大,影响也就越大。为了解决这个问题,Wisckey 提出了将 value 从 LSM 里面分离的思路,很多新的引擎也是这样设计的,但这个不在今天的讨论范围里面,以后再说。

上面是 insert,对于 read 操作来说,譬如对于 point get 来说,也会有几个步骤:

  1. 从 memtable 查找
  2. 从 immutable memtable 查找
  3. 在 Level 0 层的 SST 里面依次查找
  4. 使用 binary search 在后面 Level 查找

虽然对于 read,会有很多优化,譬如增加 bloom filter,以及给 SST 建立 index 便于快速定位,使用 block cache 等。多数时候,如果 cache 能够命中,那么 read 的性能还是能有保证的,但如果没有,我们就需要将 SST 的 block 读出来,并且解压放到 block cache 里面,这个开销也会随着 value 增大而增大。

NovelLSM 采用了一些方法来解决 LSM 遇到的问题,主要是依赖 NVM 超高的吞吐以及很低的延迟特性。NovelLSM 致力于解决几个问题:

  1. 解决序列化,反序列化的开销
  2. 减少 Compaction 的开销
  3. 减少 Logging 的开销
  4. 支持并发读取

解决序列化,反序列化的开销

大家可以把 NVM 当成一个只是比 DRAM 性能慢一点的盘,我们能像操作 memory 那样直接操作 NVM,譬如对某一个 memory 地址直接进行更新,这在 NVM 上面也是能做到的。

所以,NovelLSM 做的第一个优化就是实现了一个 skip list,这个 skip list 是能够直接持久化到 NVM 上面的。当实际的 DRAM 上面的 memtable flush 的时候,会将里面的 key-value 数据直接通过 memcpy 的方式移动到一个 immutable NVM skip list-base memtable 上面。

NovelLSM 会将 NVM 的 skip list 通过 memory map 的方式映射到 memory 上面,在 skip list 上面的节点都是通过基于 root 节点的物理偏移来连接的。所以在遍历这个 skip list 的时候,我们需要知道 root 节点的实际地址,而这个就是根据当前映射的地址加上 root 节点的物理偏移来算出来的。所以我们需要一个地方来保存 root 节点的偏移。

对于 NVM 上面的 skip list 的操作,主要是基于 DAX 的文件系统,以及 Intel 的 NVML 库来进行的。这块大家如果感兴趣,可以考虑研究下 NOVA,这里就不过多说明了。

总的来说,NovelLSM 团队弄了个可持久化的 skip list,操作这个 skip list 就跟通常的 memory skip list 没啥两样,只不过不用担心数据丢失。而且也不需要担心序列化和反序列了。

减少 Compaction 的开销

对于 LSM 来说,如果要减少 compaction 的开销,一个比较好的做法就是增大 memtable 的大小,让 memory 里面能写入更多的数据,这样才 flush 到磁盘的时候就能保证大量的数据是有序的,从而减少后续的 compaction 的开销。但通常,机器的内存是受限的,我们不可能给 memtable 分配太大的内存,另外如果 memtable 过大,相应的 WAL 也需要记录更多的数据,在 recovery 的时候时间也会比较长。

NovelLSM 会创建两个 memtable,一个是 DRAM memtable,而另一个则是 NVM memtable。当有数据写入的时候,NovelLSM 流程如下:

  1. 将 insert 的 key-value 写入到 WAL,同时写入到 DRAM memtable
  2. 如果 DRAM memtable 满了,变成 immutable,后台线程开始 flush 到磁盘
  3. 如果这时候写入太快,compaction 来不及,NovelLSM 会激活 NVM memtable
  4. 新的 key-value 直接写写入到 NVM memtable

因为 NVM 比 DRAM 有更大的空间,所以能存放更多的数据,所以能让后台线程有充分的时间去将 DRAM 和 NVM 的 immutable memtable 进行 flush 以及 compaction,防止前台 stall。而对于 read 操作来说,最近的数据就在 DRAM 和 NVM 的 memtable 上面,然后再是 immutable memtable,最后则是 SST 里面。

减少 Logging 的开销

对于一般的 LSM 实现来说,更新操作都会先写入到 WAL,然后在写入到 DRAM memtable,如果为了性能,都会在写入 WAL 的时候关掉 fsync。

对于 NovelLSM 来说,当更新写入到 NVM memtable 上面的时候,因为这个是直接持久化写入的,所以并不需要写入到 WAL。

当 NovelLSM 需要 recovery 的时候,会将 memtable 直接重新 map 到 memory 里面,同时也通过 WAL 来恢复 DRAM 的 memtable。这里我们就需要注意,一个 key 的不同的版本可能在 DRAM memtable 里面,但更新的版本在 NVM memtable 里面,或者相反。为了保证正确性,NovelLSM 会做如下操作:

  1. 当每次 DRAM memtable 被分配出来的时候,一个新的 WAL 就会生成,所有写入到 DRAM memtable 的数据都会持久化到 WAL 上面。
  2. 当 NVM memtable 被激活写入的时候,我们可以直接将 NVM memtable 当成一个 WAL
  3. NVM memtable 的名字可以就是认为就是 WAL,只不过会有一个更新的 version number

这样恢复起来就很容易了,哪一个 WAL 的 version 最新,里面的 key 就是最新的版本。

支持并发读取

在 read 上面,NovelLSM 通过 read pool 来并发的处理,这样就将 read latency 从通常的 T-MemDRAM + T-MemNVM + T-Imm + T-SST 变成了 max(T-MemDRAM + T-MemNVM, T-Imm, T-SST)T-MemDRAM T-MemNVM是 DRAM 和 NVM memtable 的时间开销,T-Imm 则是 immutable memtable 的开销,而 T-SST 就是 SST 的开销。因为 T-MemDRAMT-MemNVM 小的多,所以这两个仍然是串行执行的。

因为 read 是并行读取的,所以可能会正确性问题,譬如下层的 SST 先读取到了数据,所以 NovelLSM 在读取的时候还是需要一定的约束,如果线程 Ti 在读取 Level i 的时候读取到了数据,那么它仍然需要保证之前的线程在 Level 0 到 Level i - 1 上面已经执行完毕,才会返回。同样,如果一个线程在 Level i 上面查到了数据,那么下面的层就不需要执行了。

当然,NovelLSM 还做了其他优化,譬如给 DRAM 和 NVM 的 memtable 加上了 bloom filter 支持,以及让线程跑到固定的 CPU 上面等。

小结

具体的测试以及效果,大家可以详细看看论文。有时候,对于程序员来说,一个比较悲催的事实是 - 在软件层面上面做了特别多的优化,还不如直接换硬件提升的快。而我个人认为,NVM 是未来的一个趋势,我们要做的就是,提前布局,做好相关的技术储备,这样当真的 NVM 成本降低到能大规模应用的时候,我们能给用户提供非常好的解决方案。如果你对这块很感兴趣,欢迎联系我 tl@pingcap.com

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

推荐阅读更多精彩内容

  • LevelDB是Google传奇工程师Jeff Dean和Sanjay Ghemawat开源的KV存储引擎,无论从...
    CatKang阅读 4,815评论 5 25
  • # LevelDB简单介绍 ------ LevelDB是Google开源的持久化KV单机数据库,具有很高的随机写...
    ClimbYang阅读 517评论 0 0
  • 在先前我们讨论了 RocksDB 的 statistics 和 write stall,但这些只能让我们发现问题,...
    siddontang阅读 8,043评论 2 16
  • 托大了 订到4:20,本来飞常准已提示3:50飞,看了历史k线平均起飞4:08,心里想让你晚点飞,脱口而出4:20...
    掉毛的老公阅读 170评论 0 0
  • 不知是靠近工业区还是地理位置的缘故,从这巴掌大的地方向外眺望,看到的总是灰蒙蒙的边际,天与地仿佛被浆糊黏贴在一起,...
    江汀州阅读 327评论 0 0