9

【数据挖掘】RocksDB结构介绍

 3 years ago
source link: https://mp.weixin.qq.com/s?__biz=MzU4Mzg4MDU1MA%3D%3D&%3Bmid=2247487706&%3Bidx=1&%3Bsn=daa2c14d469ff6941b43ae8b65191410
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

NbmMR3I.gif!mobile

引言: 前一篇文章已经介绍过,TIDB的核心存储机制为RocksDB,而RocksDB是一个基于日志结构归并树(LSM树)的KV数据存储引擎。那么RocksDB的系统结构究竟如何?他又相较于前辈LevelDB有了何种优化呢?

01

简介

Rocksdb是由facebook基于leveldb开发的,一套基于LSM树结构的数据存储引擎。针对SSD做过相应的特殊化优化处理,能够高速吞吐PB级的数据,又有极高的IO效率。

02

框架

与其他的LSM树结构的KV数据库基本一致,RocksDB也分为了内存区和磁盘区两个部分。下图为RocksDB的基本结构图。

veIzU3f.png!mobile

如图所示,RocksDB的主要部分有:

①ColunFamily(CF):列族,与HBase中的CF类似,由于将相同类的KV对进行分类存储;

② Memtable:数据内存表,上层写入的数据将被直接写入到此表;

③Immutable Memtable:不可变的内存表,在Memtable达到预设阈值时自动转变为Immutable Memtable,开始flush操作;

④ WAL: Write-Ahead Logging,预写日志,用于数据出错恢复;

⑤SST:磁盘存储数据模块。

03

Column Family

其中CF是RocksDB基于leveldb进行扩充的部分。CF的作用在于将不同类型的数据KV对进行区分开,对数据集进行逻辑上的划分,这能够较好地保证数据独立性。

每个CF中可以简单理解为一个LevelDB,每个CF都包含一个MemTable和多个Immutable Memtable,也有独立的Flush机制,但与LevelDB不同的是,CF之间共享同一个WAL,以保证数据的一致性,避免写不同的WAL出现数据错乱的情况。

04

写数据机制

在RocksDB中,与levelDB不同的是,Rocksdb的写流程时可以并行进行。数据在进行写入到数据库中时,首先会构建相应Writer结构,在通过BatchGroup线程完成调度。

biUBjue.png!mobile

现有的写机制主要有两种:

① 一组数据均有作为Leader的Writer写入,即单线程模式,Leader首先写入WAL后,再写入数据到Memtable中;

②作为Leader的Writer写完WAL后,通知其他Writer,Writer接到Leader的信号后开始并行完成自己的数据写入到Memtable中。

ZBJBbyb.png!mobile

05

管道机制

对于多组数据的写入,正常情况下的写入流程为两个WriteGroup依次写入数据,完成数据写入。RocksDB针对这种情况提供了一种Pipeline Write机制,将写数据的流程转化为流水线的形式,提升写数据效率。

正常的写流程分为写WAL和写Memtable。两个写流程串行时,写开销为2*(Twal+Tmem),而如图的流水线形式能够减少第二次的写WAL的开销。实测管道功能的开启能够带来将近20%的性能提升。

nMFRZ3B.png!mobile

06

Flush机制

一个LSM树结构的存储系统flush操作和compact操作时必不可少的部分。当内存中的memtable数据达到阈值大小时将触发flush机制。对于leveldb,整个系统中只有一个memtable,在该memtable满时,将转变为immutable memtable,同时生成一个新的memtable接受上层的写操作,同时将immutable memtable中的数据转变为SSTable结构,写入到磁盘。而Rocksdb相较于leveldb最大的不同点在于,他的memtable数量不只是一个,他一个memtable满时,系统会直接使用新的memtable来接受数据写入,而不会像leveldb一样等待其转变为immutable memTable,如何再生成一个新的memtable。简而言之就是时刻有空的memtable在准备,而不是需要新的memtable才去构建。

bU7bIbJ.png!mobile

如图为rocksdb的flush源码结构,memtable在满时,转变为immutable memTable,随即加入到待flush的链表中,后台flush线程依次处理将其进行转换为SSTable形式,写入到磁盘中的LSM树第0层。

07

Compaction机制

LSM树结构的Compaction机制基本大同小异,RocksDB相较于leveldb所多的有两点:

1.Compaction与Flush不同线程

Compaction与flush采用不同的线程,可以完成这两个流程的异步化处理,这也是采用多个memtable 导致了,这样子flush线程能够更高效率的完成数据写入,而compaction可以对队列上的数据完成合并操作,异步化能够流水线形式的执行任务,提升性能。

2. SubCompaction

对于LSM树磁盘层的L0层,由于其特殊性,导致了同层的数据块有相应的key值重叠的部分,所以在做每次compaction操作中,很大可能涉及到了整层的数据,这会导致一个compaction涉及的数据量巨大,从而阻塞了compaction下层的执行流程,因此,针对这种情况,Rocksdb提供了subCompaction技术,将一个大的compaction扩展为多个小的子合并过程,完成插入操作,流程图如图所示。

RBfmIbe.png!mobile

08

总结

总的来说,Rocksdb基于leveldb主要做了三个方面的改动:

① CF,划分数据逻辑分区

②并行化,多线程,提高吞吐率

③多memtable以及队列化,为多线程提供条件

这些特征使得rocksb在leveldb的基础上,拥有了质的提升,也解决了leveldb的一大痛点,compaction时性能停滞的问题,是一个非常大的性能进步。目前更多的研究也集中于对于memtable的结构以及如何降低LSM树的层次上,后续有空的话,我将带来关于降低LSM树层次的论文框架的简介说明。

往期推荐

qUNz2i.png!mobile

UVv63uu.png!mobile

E7JZbyB.png!mobile

yiaAr2.png!mobile


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK