1.ROCKSDB 的作用与特点
tikv 服务器将数据写入其内部模块RocksDB中落盘,而不是直接将数据写入磁盘。
RocksDB是一个强大的开源单机存储引擎,可以满足对单机数据存取的需求。这里将rocksdb
简单理解为一个单机的键值映射存储的黑盒子。
RocksDB 针对闪存,SSD存储进行了优化,具有非常低的延迟,并采用了LSM数据结构来存储数据。
具有以下特点:
高性能的键值数据存取引擎。
完善的持久化机制,同时保证了性能和数据安全性。
支持范围查询操作。
专为需要将TB级别的数据存储在本地闪存或RAM的应用服务器设计。
性能随着CPU数量的增加呈线性提升,并对多核系统非常友好。
2.RockSDB的写入和文件组织
RocksDB采用了LSM TREE 的数据结构来存储键值数据。LSM tree 将所有的输入插入,修改,删除
等操作都是作用在内存中,当达到一定数量后,再批量写入磁盘进行持久化。与传统的B+树数据结构不同,
LSM TREE 在合并过程中采取直接插入新数据的方式,避免了随机写入的问题。
LSM TREE 的结构横跨内存和磁盘,包括 memtable, immutable memtable, SSTABLE 等多个组件。
首先数据会通过WAL技术备份到磁盘上,以防止因内存断电而导致数据丢失,设置参数 sync-log=true,
可以确保将WAL持久化到磁盘中。而不是仅保存在操作系统缓存中。
完成WAL后,数据会被写入memtable 中,memtable是一个内存数据结构,保存着尚未持久化到的磁盘的数据。
为了保证数据的有序性,Memtable内部的数据可以使用跳跃表或搜索树等数据结构组织。目的是避免
查询数据时扫描所有的数据。
当memtable 达到一定大小 由 rocksdb 的参数 write_buffer_size 设定。它会转化为 immutable memtable;
immutable memtable 是一个内存中不可修改的数据结构,由于在转存过程中不阻塞写入操作。新的写入
操作将由新的memtable 处理,而不需要等待锁定memtable;
在ROCKSDB中,写入的是插入和删除两种操作。总是读取最后一次操作的内容。
WAL可以理解为一个磁盘(这里的磁盘在ROCKSDB中往往指工业级的PCIe SSD盘)上记流水帐的日志。
由于它是顺序的写,所以速度比较快。写他是因为一开始新数据不是在memtable就是在 immutable memtable中。
这两个地方都是缓存,如果宕机,数据就没有了。所以落盘前必须先写入WAL日志,防止掉电后数据丢失。
当数据从immutable memtable 转存到磁盘后,这些WAL便可以清理了。
WAL的生命周期就是它上面的数据写入磁盘之前的时间。
后台线程会将immutable memtable的内容写入SST 文件落盘。SSTABEL :SORTED String Table;
是LSM TREE 在磁盘上的数据结构。包含了经过排序的键值对集合,同时,关联着这个Memtable 的WAL 也可以被删除。
LSM TREE 使得数据插入和合并非常灵活。
RocksDB 在合并压缩过程中,使用的压缩算法是LZ4;
L0 是刚从内存中落盘的数据,就是immutable memtable直接转存的SST;
除了L0,其他层级都有目标大小,目标大小的设定旨在限制这些层级的数据量,通常采用指数增长的方式。
更新于删除操作都是先打标记,然后通过后台的GC进行进行垃圾回收及合并。
3.ROCKSDB的查询
在ROCKSDB中,查询操作需要顺序读取 memtable,immutable memtable, L0,L1...;
因为数据是按照这个顺序写入的。memtable,immutable memtable,L0 的SST 文件是跳跃表
的数据结构。
L1 以后的SST文件按照键值对的键进行排序。
ROCKSDB的去取效率较低,为了提升读取效率,ROCKSDB使用布隆过滤器。布隆过滤器可以判断相应SST文件
中是否存在要读取的数据。如果布隆过滤器判断不存在,直接跳过该文件。
布隆过滤器是一个很长的二进制向量和一系列随机映射函数的组合。用于判断一个元素是否属于一个集合。
它有一定的误判性。
ROCKSDB 内部有一个模块为块缓存 BLOCK CACHE; 保存经常访问的数据,如果不在这一部分,则从Memtable获取,
如果在块缓存,优先获取缓存中的数据。
4.ROCKSDB的列族
TIKV是通过集成ROCKSDB引擎来实现最基本的数据持久化。ROCKSDB的列族和TIKV的事务支持有关。
列族是从ROCKSDB3.0版本开始引入的,无论什么类型的键值都存储在同一个系统的memtable;
immutable memtable,SST 文件中。在ROCKSDB中每个键值对都对应着一个唯一的列族,每个列族
就是一系列的Memtable,immutable memtable ,SST;如果没有指定列族,键值对将会默认对应到
名为default的列族,这是ROCKSDB实例的默认列族。
TIKV利用列族将用户数据,锁信息和事务的提交信息分别放在不同的列族中进行管理。
列族提供了一种逻辑上对数据库进行分片的方法:
(1)支持跨列族的原子写操作。可以原地执行类似于 Write({cf1,key1,value1},{cf2,key2,value2})
(2)跨列族的一致性视图。
(3)允许对不同的列族进行不同的配置。
(4)可以即时的添加和删除列族。
列族共享WAL文件,但不共享memtable,SST 文件。每个列族都有独立的memtable,immutablememtable,SST文件。