rocksdb

一、概述

RocksDB 改自LevelDB,是一个持久化存储的KV系统,和Redis这种内存型的KV系统不同,LevelDB不会像Redis一样狂吃内存,而是将大部分数据存储到磁盘上。

数据结构:LSM-Tree(Log-Structured-Merge-Tree)。LSM从命名上看,容易望文生义成一个具体的数据结构,一个tree。但LSM并不是一个具体的数据结构,也不是一个tree。LSM是一个数据结构的概念,是一个数据结构的设计思想。

整体结构:主要分为三大块:WAL(disk)→ Memtable(memory) →  SST(disk)

rocksdb

二、读写流程

2.1 写流程

WAL

首先是将这条KV记录以append方式追加到log文件末尾,因为尽管这是一个磁盘读写操作,但是文件的顺序追加写入效率是很高的,所以并不会导致写入速度的降低。

Memtable

如果写入log文件成功,那么将这条KV记录插入内存中的Memtable中,Memtable只是一层封装,其内部其实是一个Key有序的SkipList列表,保证了数据插入查找时log2N复杂度。

rocksdb

Compaction

  1. minor compaction: immutable-memtable 触发阈值后, flush 到Level0 SST。这些磁盘中的文件都是不能修改的,就算有新的写入也不会对原来的文件做变更而是写入到新的位置,这样就将随机写入变成了顺序写入,写效率非常高。随着时间的推移磁盘上面的文件ssttable会越来越多,这个时候就需要通过compaction对文件进行合并来减少文件个数。
  2. major compaction: Level0 SST触发阈值后,经合并操作生成level 1 SST, level1 SST 合并操作生成level 2 SST,以此类推,生成level n SST(每次合并都生成新文件)。通过合并去掉多层之间的SST文件的重复数据和无用的数据,进而减少sst文件占用的磁盘空间,对于读而言,由于需要访问的sst文件变少了,也会有性能的提升。

2.2 读流程

按照 memtable --> Level 0 SST–> Level 1 SST --> … -> Level n SST的顺序读取数据。这和记录的新旧顺序是一致的。因此只要在当前级别找到记录,就可以返回。

三、读优化

很明显,LSM牺牲了一部分读的性能和增加了合并的开销,换取了高效的写性能。那LSM为什么要这么做?实际上,这就关系到对于磁盘写已经没有什么优化手段了,而对于磁盘读,不论硬件还是软件上都有优化的空间。通过多种优化后,读性能虽然仍是下降,但可以控制在可接受范围内。

Compaction : ①LSM每次都是顺序写入,不修改,一直保持生成新文件,这样不仅会造成空间浪费,而且也会降低读的性能。所以rocksdb后台多线程周期性的进行不同Level的SST文件合并,清理重复数据和无用数据;②而且SST文件内部数据是排序的,在合并不同Level上的SST文件时类似merge-join(归并连接),这样大部分的数据查询可以二分查找的方式找到。

Bloom filter : 每个SST文件在生成的时候,都会创建一个或多个对应的bloom filter,当在读数据的时候,可以快速判断出数据是否可能在SST文件中。于是我就可以不用二分查找,而只需简单的计算几次就能知道数据是否在某个小集合里啦。效率得到了提升,但付出的是空间代价。

 

 

上一篇:分布式数据库(十九):数据库的存储引擎


下一篇:解决jenssegers/mongodb无法连接带密码的mongodb数据库问题