RocksDB部分优化设计

前言


RocksDB作为单例数据存储引擎,它能支持良好的数据吞吐量,同样可以很好地作为大型分布式系统元数据的持久化存储。RocksDB作为存储框架,其内部在设计实现中有着许多与分布式存储系统相似的地方,例如包括数据索引,数据限流等等。比本文,笔者将简单聊聊RocksDB内部一些精妙的设计实现。

RocksDB部分功能设计


笔者这里简单挑选了以下5个设计点:

  • Auto RateLimiter,自适应限流器,相比较于平常我们往往对IO操作做指定速率的限制,RocksDB在这里实现了自适应的限流器,自适应调整的做法弥补了指定限流速率做法的不足之处。
  • Bulkloading by ingesting external SST file,大批量数据的离线导入。当我们有大量的数据准备写入系统时,我们有额外离线写入SST文件的方式,而非调用PUT操作一次次将记录写入,前者比后者高效不少。
  • Bloom Filter,布隆过滤器,用以判断待查询key是否存在于所查询的SST文件内。
  • Hash index to speed up point lookup,哈希索引加速数据key的查找,在RocksDB的SST文件内,额外设计了哈希索引增加查询效率,相比较于原先的二分查找方式。
  • Indexing SST Files for Better Lookup Performance,添加SST索引提升key查找速度。和上一点提高在一个SST文件内的key查找,这里的索引指的跨SST文件间的。

下面我们逐一对上述功能设计做简单阐述。

Auto RateLimiter


RocksDB内部为了避免后台IO写入操作过快导致潜在对于用户Put操作的影响,于是设计了RateLimiter限流功能。限流器的设计在很多其它分布式系统内也比较常见,不过RocksDB在这里实现了更为智能化一些的RateLimiter。这个RateLimiter不是使用一个固定传入的限流值做流控,而是给定一个Rate的上界,下界。

当当前限定的Rate Limiter速率值被打破时(低于或高于当前值),则进行Rate Limiter在给定的range范围内的速率调整。

Bulkloading by ingesting external SST file


当用户需要进行大规模数据导入的时候,如果我们还是采用按照一条条记录PUT写入的方式做处理时,会引发大量的操作,而且还会影响到其它用户的PUT写入操作。

因此在RocksDB中,它支持预先离线写入K-V值到SST文件的方式,然后再将这些SST文件添加到RocksDB内部,这其中的过程包括SST sequence number号的生成,metadata block数据的关联,LSM树的重新组织等等。

Bloom Filter


为了快速查找某个key是否存在于某个SST文件内,RocksDB会为每个SST文件单独存有对应的Bloom Filter内容文件。SST文件的key会经过哈希算法,被转化为多个位值表示。这些位值对应的Bloom Filter下标数组为将被标为1。key判断查找的时候就通过数组位值是否全为1来判断key是否存在于SST文件内。

每个SST文件对应的Bloom Filter内容会在初始时加载到内存中,然后后续key的判断在内存中的Bloom Filter内进行判断。

扫描二维码关注公众号,回复: 8652572 查看本文章

哈希索引加速数据key的查找


在传统方式下,RocksDB对一个SST文件进行key查找时采用的是二分查找的方式。为了加速对于key的查找,RocksDB内部在SST文件内添加了额外的结构来支持哈希索性。简单的解释就是哈希索性会通过key给出对应实际key的索性位置,然后系统根据key索性提供的位置信息进行实际数据的读取。哈希索性带来的主要变化key只要经过一次查找就能找到位置索性信息,而不是进行全局二分查找索性位置。如果此过程中存在多个key到同一个值的情况即哈希冲突的情况,则对这些key进行failback的处理,退回到二分查找的方式。

以下是官网介绍的查找方式图:

1.原始二分查找key的方式
在data段内,相邻的key会被组织在一起分组存放。这里二分查找的位置即每个block段的offset值。
在这里插入图片描述

2.增加了哈希索引查找的方式
在这里插入图片描述

3.哈希索引查找冲突,退回到二分查找方式
在这里插入图片描述

SST文件的索性查找


在RocksDB中,存在定期Compact行为来将低level的SST文件合并到高level的文件内,以此去除无效key,重复key的存放。

Compact行为如下图所示:
在这里插入图片描述
Compact操作后,
在这里插入图片描述

所以有的时候我们需要查询的key并不是在一个SST文件内能被立马查询到,它可能存在于别的SST文件内。在此SST文件组织前提下,我们自然联想到的查找方式是串行逐一进行SST文件的查找。但是这种查询是一种高效的查询方式吗?里面是否存在无效的查找过程呢?

其实SST文件在每个Level段内是有按照key进行排序的,而且上个level段的SST文件也能找到对应下level段的一个位置,如下:

在这里插入图片描述
如上图所示,level1内的file1对应level2的位置在file3,file4间。因此假设我们有个待查询key为280,然后系统发现在level1的file1和file2的key区间都没有包含此key,则它可以在level2中直接缩小范围进行查找,范围段为[file1在level2的上界, file2在level2的下界],也就是说level2的file4,5,6和7这四个文件中进行查找。

通过上下SST文件索引信息的记录,我们可以减少不必要的SST文件查找过程,提升key查找效率。

RocksDB内部有着很多好的设计和实现,笔者今天简单挑选了其中的一小部分做了阐述,更多内容可详见RocksDB官方博客或wiki链接。

引用


[1].https://rocksdb.org/blog/2018/08/23/data-block-hash-index.html . Improving Point-Lookup Using Data Block Hash Index
[2].https://rocksdb.org/blog/2014/04/21/indexing-sst-files-for-better-lookup-performance.html . Indexing SST Files for Better Lookup Performance

发布了373 篇原创文章 · 获赞 403 · 访问量 203万+

猜你喜欢

转载自blog.csdn.net/Androidlushangderen/article/details/102963910