写点什么

RocksDB 在大规模分布式系统应用中的经验

作者:CnosDB
  • 2022 年 8 月 17 日
    内蒙古
  • 本文字数:2901 字

    阅读完需:约 10 分钟

RocksDB在大规模分布式系统应用中的经验

本文主要是讲了一些 RocksDB 在分布式系统中大规模应用时的经验与教训。


RocksDB 是一个高性能的持久键值存储引擎,由 Facebook 在 2012 年创建,基于谷歌的 LevelDB 代码。RocksDB 是基于 LSM 的,对 SSD 进行了优化,被多个数据库当做存储引擎使用,并且被使用在流处理、日志队列服务以及索引服务和 SSD 缓存之上。

引擎架构

MemTable 与 WAL

RocksDB 使用 LSM 作为主要的存储数据结构,每当数据写入到 RocksDB 之中,就会被添加到 MemTable 内存的写缓冲区,以及一个磁盘上的超前写入日志(WAL)。数据会被写入到 WAL 和 MemTable,WAL 是 MemTable 的易失性保护机制。

RocksDB 中 Memtable 的数据结构有三种,分别是 skiplist、hash-skiplist、hash-linklist,跳表的好处在于插入的时候可以保证数据的有序,并且支持二分查找、范围查询。插入和搜索的代价都是 O(log n)。

在达到指定大小之后现有 MemTable 和 WAL 锁定变为不可变,新数据写入新的 MemTable 和 WAL。

SSTable

SSTable 是一种数据结构,当 MemTable 到达一定的上限之后,会 flush 到硬盘上 Sorted String Table (SSTable),并放置在第 0 层(L0),对应的 WAL 空间回收;L0 大小达到上限时,L0 的 SSTable 经过 compaction 落到 L1;Ln:以此类推完成上述操作。

在每一级中,都会使用二进制搜索;而布隆过滤器会消除 SSTable 文件中不必要的检索。

Compaction

Campact 可以翻译成压缩,也可以被称为压实,其作用主要有:清除无效数据;对数据的排序进行优化。而无效数据的产生于 update:标记覆盖与 delete:标记删除。使用 Compact 的好处有:整个文件的批量读写,比较高效;可以并行化操作。

比较几种常见的 Compaction 策略:

● Leveled:leveldb 的方式,SSTable 数量逐层以指数增长,读写放大都比较严重,但是空间放大较低;

● Tired/Universal:Cassandra 与 HBase 的方式,空间放大和读放大严重,但是写放大最小;

● FIFO:删除旧的过期文件,执行轻量级压缩,适用于那些 in-memory 缓存应用。

大家也可以发现,并不存在写放大、读放大和空间放大都很完美的方案;和计算机世界的其他领域一样,数据库也没有银弹。

资源目标的优化

针对于 RocksDB 的问题,很多团队也对齐进行了资源目标的优化,我们选取了两点进行资源目标优化的讨论,分别是写放大和空间放大。

写放大

写放大主要来源于以下几个层面:

● 固态硬盘本身会带来 1.1 到 3 的写入放大;

● 当 4kb/8kb/16kb 大小的页面被写入不到 100 字节的变化时,可能会产生 100 倍的写入放大;

● 不同的 Compaction 策略有不同的写入放大比率。

针对于以上的写放大,有如下优化建议:

● 在写入速率高时,减少写放大;

● 在写入速率低时,积极压缩;

● Value 较大时,可以考虑使用 BlobDB 分离 Key 和 Value。

空间放大

在使用 SSD 时,空间利用率比写入放大率更重要,因为闪存的写入周期和写入开销都不受限制。优化空间放大,可以使用动态分层压缩,每一层大小根据上一层实际大小自动调整,而不是每层都是固定的大小,能够更有效地利用空间。

大规模系统的经验

RocksDB 应用于不同需求的大规模分布式系统的构建,我们也从一下几点去阐述相关经验和改进思路。

资源管理

大规模的分布式系统会将数据划分为 Shard,分布在多个服务器节点上进行存储。同时,一台主机内部可能运行多个 RocksDB 的实例,需要对资源进行管理,包括全局(每台主机)和局部(每个实例)。

需要管理的资源包括:

● 内存:Write buffer、Block cache

● I/O 带宽:Compaction

● 线程:Compaction,最好使用线程池

● 磁盘使用量

● 文件删除频率

并且尽量满足以下要求:每个实例都不能过度使用任何资源;不同实例之间可以设置资源使用的优先级。

WAL

在传统的数据库中,倾向于进行 WAL 的操作,以确保持久性。在分布式场景中,数据有副本,并且进行一致性的校验。如果使用 Paxos 进行副本间的数据同步,那么 WAL 是无用的。同时,可以提供三种不同的 WAL 策略操作:同步写;缓冲异步写;不写。

限制文件删除

有些文件系统能够识别出 SSD,比如 XFS。进行文件删除时,文件系统会向 SSD 发出 TRIM 指令,通常情况下可以提高 SSD 的性能与耐用性,但也可能导致性能问题。TRIM 除了更新 SSD 内部内存中的地址映射,还会触发 SSD 内部的垃圾回收,导致大量的数据移动,提高 IO 延迟。所以文件删除速率需要被限制,防止 Compaction 过程中的多个文件同时被删除。

数据格式的兼容性

大规模分布式系统几乎必须提供在线的滚动升级与回退的功能,所以从底层的数据格式设计上就必须保证向前和向后的兼容性。那么可以采用以下的相关策略:

● 所有版本必须能够理解所有以前写入磁盘的格式

● 未来的格式也应该能够被理解

● 可以考虑使用 ProtocolBuffer 和 Thrift 中的相关技术

● 配置文件配置项的前后兼容性设计

● 做好版本兼容性测试

复制与备份

RocksDB 是一个单节点的存储引擎,所以无论以任何方式进行复制和备份,RocksDB 都要进行相关的支持。两种方式可以支持现有的副本复制:

● 逻辑复制:所有的键值对都可以被读出来,写到数据副本中

○ 支持全数据扫描操作,并最小化对正常读写操作的性能影响

○ 逻辑复制的查询结果,不会进行缓存

○ 在目标端支持批量加载,并进行相应的优化

● 物理复制:直接复制 SSTable 和其他文件。

○ 物理复制的接口应由引擎提供,而不是让用户或者其他应用程序去直接操作数据文件

在逻辑复制的部分是基于既有数据文件的复制,基于文件的复制更适合创建新的副本时的全量复制。而物理复制则为全量复制提供了一个速度更快的选择。

复制的机制还与一致性有关,同时备份也包括逻辑备份和物理备份,与复制的区别是,应用程序需要多个备份。总体而言备份与复制使用的方法与手段相差不多,但从用户易用性的角度出发,存储引擎应当有管理多个备份的功能。

故障的教训

出于性能方面的考虑,用户很可能不使用 SSD 的数据保护(DIF、DIX),存储介质的损坏需要由存储引擎的块校验检测出来。除此之外,复制、备份、数据恢复过程中也可能引入损坏的数据。

数据损坏应当尽早被发现,以减少停机时间和数据损失。一份数据应当在多个主机上进行复制;当检测到 checksum 不匹配时,损坏的副本被断开,并由正确的副本接替;同时,需要至少保证有一个正确的副本。多层校验包括:

● 块:每个 SSTable 块和 WAL 块都有一个附加的校验和,在数据被创建时产生;每次读取数据时都会进行验证,防止损坏数据暴露给用户;

● 文件:每个 SSTable 文件有自己的校验和,校验和记录在 SSTable 的元数据中;

● Handoff:这是一种向文件系统写入数据时同时传下去的校验和,由文件系统的一些机制来进行校验;但是不是所有的文件系统都支持这种校验,所以要提前做好规划。

结语

通过本文,希望大家对 RocksDB 有更好的认知,同时也可以更好的将 RocksDB 应用于各种大规模分布式系统。

参考文献:

RocksDB Github Wiki: https://github.com/facebook/rocksdb/wiki

Evolution of Development Priorities in Key-value Stores Serving Large-scale Applications: The RocksDB Experience: https://www.usenix.org/conference/fast21/presentation/dong

RocksDB 原理及应用: https://zhuanlan.zhihu.com/p/409334218


CnosDB 简介

CnosDB 是一款高性能、高易用性的开源分布式时序数据库,现已正式发布及全部开源。

欢迎关注我们的代码仓库,一键三连🙇🙇🙇:https://github.com/cnosdb/cnosdb

发布于: 刚刚阅读数: 4
用户头像

CnosDB

关注

还未添加个人签名 2022.04.18 加入

CnosDB是一个由社区驱动的开源时间序列数据库,适用于各种时序场景,如服务器/应用程序/性能指标/函数接口调用指标、网络流量/探测器数据、日志/市场交易记录等。代码仓库:https://github.com/cnosdb/cnosdb

评论

发布
暂无评论
RocksDB在大规模分布式系统应用中的经验_时序数据库_CnosDB_InfoQ写作社区