RocksDB是Facebook开源的一个高性能持久化KV存储,很少有RocksDB在生产环境来保存数据,在未来,RocksDB也不会像Redis那样直接被使用

但是很多新生代的数据库会选择使用RocksDB来作为存储引擎,例如 MyRocks,就是利用RocksDB来给MySQL做后端存储引擎,取代现有的InnoDB存储引擎,并且MySQL的亲兄弟MariaDB已经可以使用Rocks了,再者说,Flink,Flink的State就是一个KV存储,也就是RocksDB,还包括MongoDB,Cassandra等数据库,都有基于RocksDB的存储引擎

那么,其和Redis有何区别?

两者本质上完全不一致,一个是缓存,一个是存储系统,Reids作为一个内存的缓存,读写的性能在50万次/秒,RocksDB的随机读写性能在20万次/秒,性能不如Redis,但是也是一个量级的了

RocksDB作为一个存储引擎,比起Redis,还需要进行保存在磁盘上,在加上这个桎梏还能做到这种性能,就是价值所在

Rocks在保证数据持久化的前提下,还能如此高的性能,说明其整体架构和存储结构上有过人之处

Rocks对于存储设计了一个非常复杂的数据存储结构,此结构整合了内存和磁盘混合的模式,利用磁盘来保证数据恢复,利用内存提升读写

比如,我们往B+树中写入一条数据,必须按照B+树的排序,按照B+树的排序,写到固定的某个节点下

这样编写方式,导致我们的数据录入的时候,可能导致录入的数据是随机写,RocksDB利用了自身精妙设计,避免了随机写,这就是高性能写入的根本原因

其数据结构为LSM-Tree

如何兼顾的读写性能,LSM-Tree的全称,The Log-Structured Merge-Tree,非常复杂的符合数据结构,包含了WAL 日志 , 跳表 SkipList 分层的有序表SSTable Sorted String Table

下面就是LSM-Tree

图片

本质上比这个图更加的复杂

但是我们简单的复述下存储的流程,假设,收到了一个写请求,比如PUT foo bar,将Key foo的值设置为bar,这条命令会被写入磁盘的WAL日志,顺序写磁盘的操作,性能很好,日志的唯一作用是用于故障恢复,一旦系统宕机,就可以将日志中内存还没有来得及写入磁盘的数据恢复出来,这还是复制状态机的理论

写完日志之后,数据可靠性就解决了,然后希尔内存的MemTable中,这就是跳表,这个写入是一个内存操作,写入后就直接返回成功了,这个写入操作也不校验Key是否存在,而是直接尝试写入

然后写到MemTable的存储上限,一般32M,就转换为Immutable MemTable,然后创建一个新的MemTable,Immutable 利用了不变性,不允许再写入

一旦转换为了Immutable Memtable的话,就存入磁盘文件,利用跳表的有序性,来将保证内存写入文件,是一个有序的顺序写操作,转换为了SSTable

但是这些SSTable本身有序,但是文件之间无序,所以还有一个分层合并机制

SSTable被分为了很多层,越往上,文件数越少,越往里,文件数越多,每层的容量有一个固定的上限

,每层写满了,就会往下一层合并,数据合并了之后,本层的SSTable就可以删除了,合并的时候,也是排序的时候,内部数据有序,方便查找

对于LSM-Tree的查找,查找也是分层查找,先去MemTable和0层,然后依次往下层查找

找到了就直接返回,但是这种方式有利于对数据的加热处理

因为最经常读写的Key大概率在内存中,不用读写磁盘就能完成查找,也不用穿透很多层SStable才能查找到最底层

还能利用布隆过滤器来避免无所谓的查找

总结一下

RocksDB是一个高性能持久化的kv存储,很多新生代的数据库都将其作为存储引擎,RocksDB在保证不错的读性能的前提下,提升了写性能,得益于其数据结构LSM-Tree

LSM-Tree利用混合内存和磁盘的多种数据结构,将随机写转换为顺序写来提升写性能

这种数据结构适合写入性能的优化,适合交易类场景

关于LSM-Tree的删除,如何实现的呢?

必然先去写日志,然后写入删除的缓存,然后同步到实际的SSTable中

发表评论

邮箱地址不会被公开。 必填项已用*标注