RocksDB 批量导入调优

RocksDB 批量导入数据的最快速度可以达到多少?我们面临这个挑战,因为我们想让我们的客户可以尽快把大量数据导入Rockset,试用Rockset。尽管批量导入数据到LSM tree也是一个比较重要的主题,但是并没有很多文章讨论。在这篇文章里,我将讲诉一些优化技巧,可以提高RocksDB批量导入数据的速度,大概提高20倍左右。虽然我们也需要解决一些分布式的挑战,但是在这片文章中,我将集中讨论RocksDB单台机器的优化。熟悉RocksDB的人对RocksDB的LSM tree结构肯定也很熟悉。

Rockset的写流程包括以下几步:

  1. 首先我们通过分布式日志存储系统来检索文档,一篇文档代表一个已经被编译为二进制的JSON结构。
  2. 对每一个文档来说,我们需要向RocksDB插入大量K-V数据,接下来,我们需要将多列文档转换为多列K-V数据。重要的是,我们同时需要从RocksDB数据库读取数据,确定这个文档是否已经在RocksDB中里面,如果文档已经存在,需要更新secondary index entries。
  3. 最后,我们提交这些KV数据到RocksDB数据库。
image

延迟和吞吐量的取舍

Rockset被设计成一个实时系统,只要用户写入一个文档到Rockset,就必须为它创建索引。我们没有太多时间去构建大量文档数据。这是一个遗憾,因为增加批处理文档的大小可以最大限度的减少每批操作的开销。但是批量导入的时候,没有必要优化单个文档写入的时间,在批量导入数据的时候,可以通过增加每批写操作处理数据的大小,来提高写入数据的吞吐量,通常写操作的数据一般为百MB。

并行写

常规操作,我们使用单线程来执行写流程。这已经足够了,因为RocksDB通过压缩把写进程放入到背景线程里面去,为了应对查询的负载,需要更多的CPU。在最初的批量导入的时候,查询负载并不是特别重要,所有的CPU都忙于写操作,因此,我们并行化了写操作。一旦我们构建了一系列的批处理的文档,我们立刻把这些批处理的文档分发到工作线程组,每一个工作线程各自独立将数据插入到RocksDB数据库里。需要考虑的一个重要设计是去最大程度地减少对共享数据结构地独占访问。否则,一些写线程将会处于等待状态。

避免Memtable

RocksDB提供了一个特性:你可以自己构建SST 文件,然后把他们添加到RocksDB里面,而不需要经过memtable。这个api是IngestExternalFile()。这个特性对于批量导入来说十分有利,因为写线程并不需要同步写数据到memtable。写线程只需要对KV数据排序,然后将数据写入SST文件里就可以了。将SST文件加入到RocksDB里面是一项比较廉价的操作,因为它只需要更新元数据就可以了。

在现在实现的版本里,每一个写线程构建一个SST文件,但是如果存在大量小的文件,那么压缩操作将会比更少数量的大文件慢很多。我们正在研究一个方法,从而可以让每一次批量写操作的所有线程只产生一个大的SST文件。

关闭压缩带来的挑战

RocksDB批量导入数据最常见的建议是关闭压缩,最后执行一次大的压缩。这个方法也是RocksDB官方文章里所提到的方法。毕竟,RocksDB执行压缩的唯一原因是通过牺牲写开销来优化读取。但是,这个建议有两个非常重要的局限性。

在Rockset我们每次写入文档前必须执行一次读取,我们需要执行一次主键查询来检测是否有新的文档还存在数据库里。通过关闭压缩,我们很快出现上千个SST文件。主键查询变成了比较大的缺点,为了避免这种情况,我们在所有的主键上构建了布隆过滤器。因为我们批量导入数据的时候,通常不会有重复数据,所以布隆过滤器能够使我们避免昂贵的主键查询。细心的读者会发现RocksDB本身也有布隆过滤器,但是它是针对每个文件构建的,检查上千个布隆过滤器仍然代价高昂。

第二个问题是最后的压缩操作默认是单线程的,这有一个选项能够使RocksDB变成多线程压缩,这个选项使max_subcompactions。但是增加子压缩的数目并不会起到太大的作用。如果所有文件的级别都为level 0,压缩算法无法为每个子压缩找到良好的边界,而是决定使用单个线程。我们通过首先执行priming压缩来固定子压缩的数目。我们首先压缩少量的问题通过CompactFiles()。而且RocksDB也有些文件处于非0的level上,这个可以决定好的子压缩的边界,从而可以使用多线程压缩。

我们处于Level 0 的文件并没有进行压缩。因为我们不想降低写线程的速度。而且把它们都压缩了,也没有太多好处。最后的压缩会压缩输出文件

结论

通过上述优化,我们可以只用18个核将200GB的未压缩的数据(通过LZ4压缩后,大小为80GB)在52分钟内(70MB/s)导入到RocksDB里。开始的批量导入花费35分钟,最后的压缩花费17分钟。如果不做任何优化,将会花费18个小时。如果只使增加批处理数据的大小和并行写,对RocksDB不做其他操作,将会花费5个小时。需要注意的是,这些数据只是在单机上测得。Rockset可以多机器并行写,这可以达到更高的写吞吐量。

image

RocksDB批量导入数据可以抽象为并行排序,但是数据不能全加载到内存里,另一个约束是排序的时候,我们需要读去一部分数据。这仍然有很多有趣的关于并行排序的工作。我们希望能够调研一些其他的技术,并把这些技术应用到我们的设置中。我们也希望其他RocksDB的用户可以分享他们批量导入数据的技术。

注:本文为翻译。
原文:https://rockset.com/blog/optimizing-bulk-load-in-rocksdb/

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

推荐阅读更多精彩内容