1,介绍
RocksDB是一个用C++实现的、适用于不同存储介质的keys-values存储引擎,目标是实现快速存储。它支持点查找和范围扫描,并提供不同类型的ACID保证。
RocksDB具有高度灵活的配置设置,可以根据不同的生产环境进行调整,包括SSD、硬盘、ramf或远程存储。它支持各种压缩算法以及提供了用于生产支持和调试的良好工具。另一方面,提供足够好的开箱即用功能,并在使用了一些自适应算法。
2,目标
性能
RocksDB的主要设计点是,对于快速存储和服务器工作负载来说,是高性能的。支持高效的点查找和范围扫描。可配置的,以支持高随机读取工作负载、高更新工作负载或两者的组合。它的体系结构支持针对不同工作负载和硬件进行调整。
生产支持
RocksDB的设计使其内置支持工具和实用程序,以帮助在生产环境中进行部署和调试。如果存储引擎还不能自动调整应用程序和硬件,提供了一些参数以允许用户调整性能。
3,架构
RocksDB是一个键值存储接口的存储引擎,其中键和值是任意字节流。RocksDB按顺序组织所有数据,常用操作有Get(key)、NewIterator()、Put(key,val)、Delete(key)和SingleDelete(key)。
RocksDB的三个基本结构是memtable、sstfile和logfile。memtable是一种内存中的数据结构,新的写入被插入memtable中,并且可以选择写入日志文件(也称为Write Ahead Log(WAL))。日志文件是存储上按顺序写入的文件。当内存表填满时,它会被刷新到存储上的sstfile中,相应的日志文件可以安全删除。sstfile中的数据经过排序,以便于查找关键字。
4,功能
列族
RocksDB支持将一个数据库实例分成多个列族。所有的数据库默认创建一个default列族。RocksDB保证用户跨列族的一致视图,包括在启用WAL或启用原子刷新时的崩溃恢复后。它还通过WriteBatch API支持原子跨列系列操作。相当于逻辑分区
更新
PutAPI向数据库插入单个键值。如果key已存在于数据库中,则会覆盖以前的值。WriteAPI允许在数据库中以原子方式插入、更新或删除多个键值。数据库保证单个Write调用中的所有键值都将插入数据库,或者它们都不会插入数据库。如果数据库中已经存在任何这些键,则会覆盖以前的值。DeleteRangeAPI可用于删除范围中的所有键.
查询,迭代器,快照
键和值被视为纯字节流。键或值的大小没有限制。GetAPI允许应用程序从数据库中获取单个键值。MultiGetAPI允许应用程序从数据库中检索一串key。通过MultiGet调用返回的所有键值彼此一致。
数据库中的所有数据都按顺序进行排列。应用程序可以指定键的比较方法,该方法指定键的总顺序。IteratorAPI允许应用程序对数据库进行范围扫描。迭代器可以搜索指定的键,然后应用程序可以从该点开始一次扫描一个键。IteratorAPI还可以用于对数据库中的键进行反向迭代。创建Iterator时,将创建数据库的一个快照视图。因此,通过Iterator返回的所有键都来自数据库的一致视图。
快照API允许应用程序创建数据库某个时间点的视图。Get和IteratorAPI可用于从指定快照读取数据。从某种意义上说,快照和迭代器都提供了数据库的某个时间点视图,但它们的实现不同。短期/前台扫描最好通过迭代器完成,而长期/后台扫描最好通过快照完成。Iterator对与数据库的时间点视图相对应的所有底层文件保持引用计数,这些文件在释放Iterator之前不会被删除。另一方面,快照不会阻止文件删除;相反,压缩过程理解快照的存在,并承诺永远不会删除任何现有快照中可见的key。
快照不会在数据库重新启动时持久化:重新加载RocksDB库(通过服务器重新启动)会释放所有预先存在的快照。
事务
RocksDB支持多操作事务。它支持乐观和悲观模式;
前缀迭代器
大多数LSM树引擎无法支持有效的范围扫描API,因为它需要查看多个数据文件。但是,大多数应用程序不会对数据库中key的范围进行纯随机扫描;相反,应用程序通常在key前缀内扫描。RocksDB利用了这一优势。应用程序可以通过配置Options.prefix_extractor启用基于key前缀的过滤。当Options.prefix_extractor被设置,前缀的哈希也被添加到Bloom中。指定键前缀的Iterator将使用Bloom Filter来避免查找不包含具有指定键前缀的键的数据文件。
多线程Compactions
当正在进行写入,为了提高空间效率、读取(查询)效率和及时删除数据,需要进行Compactions操作。Compactions清理已删除或覆盖的键值,并重新组织数据以提高查询效率。通过配置,Compactions可以使用多个线程。
整个数据库存储在一组sstfiles中。当memtable满时,其将作为一个文件写入LSM树的Level-0(L0)层。RocksDB在将memtable刷新到L0中的文件时,会删除memtable中的重复键和覆盖的键。在Compactions过程中,一些文件会定期读入并合并以形成更大的文件,通常会进入下一个LSM层(如L1,直到Lmax)。
LSM数据库的总写入吞吐量直接取决于Compactions的速度,尤其是当数据存储在SSD或RAM等快速存储中时。RocksDB可以被配置为多个线程处理。据观察,与单线程Compactions相比,当数据库位于SSD上时,使用多线程Compactions时,持续写入速率可能增加多达10倍。
Compactions格式
较新的数据存储在Level-0(L0)中,较旧的数据存储于编号较高的Level中,最高可达Lmax。L0中的文件可能有重复的key,其他层中的单个文件是有序的。
当数据的总大小超过配置的大小(CompactionOptionsFIFO::max_table_files_size)时,将删除最旧的表文件。
可以自定义compaction策略。如果设置了disableautocompact,则禁用本机压缩算法。
Block Cache—-压缩和未压缩的数据
RocksDB使用LRU缓存来为块提供读取服务。块缓存分为两个单独的缓存:第一个缓存未压缩的块,第二个缓存RAM中的压缩块。通过配置压缩块缓存,可以启用直接I/O以防止在OS页面缓存中缓存相同的数据。
Table Cache
表缓存是缓存打开的文件描述符。这些文件描述符用于sstfiles。应用程序可以指定表缓存的最大大小,或者将RocksDB配置为始终打开所有文件,以获得更好的性能。
可插拔的Memtables
RocksDB默认使用skiplist实现memtable。
skiplist memtable,vector memtable,prefix-hash memtable
skiplist是一个排序集合,适合交错写入和范围查找。
vector memtable适合批量插入数据的场景。
prefix-hash memtable适合get,put,key前缀查找