TIDB TIKV数据存储到ROCKSDB探秘 与 ROCKSDB 本尊

2021-07-16 00:00:00 数据 数据库 数据存储 方式 写入

为什么近一直在看分布式数据库,因为第六感给我的指示是, 分布式数据库是国产数据库下一个要发力的点, 为什么.  如果作为一个产品经理, 首先一个产品要有用户的画像, 那么什么数据库是可以找到金主"爸爸"的, 分布式数据库,并且这些金主们, 应该都很有钱.  单体数据库能吸引大量资金的时代是要过去了.  一个维护费用低,稳定性强, 扩展能力强并且将之前数据库的"毛病" 都一一扫尽的数据库产品, 银行和金融机构应该是很欢喜的.  这也是一些银行自研分布式数据库,或者使用商用分布式数据库的原因吧.


分布式数据库的存储必然是要和单体数据库的存储模式不一样, 那么看看一些成熟的分布式数据库到底用了那些存储模式,并分析一下到底为什么有利于拓宽眼界, 追上"潮流".


TIDB 数据库使用的数据存储底层是ROCKSDB,ROCKSDB 是FACKBOOK旗下的一款数据库。TIDB 中的数据存储TIKV 使用了ROCKSDB 作为数据存储的底层架构。所以理解一下TIDB 为什么用ROCKSDB 作为存储有利于理解分布式数据库设计的理念。

以下是key value的数据库在随机写和随机读之间的性能比较.


那么为什么要说上面的那个图, 原因是 ROCKSDB 是LEVELDB 的改进版本


我们分析一下 LEVELDB 是KEY VALUE 存储引擎中的佼佼者, 而ROCKSDB ,继承了leveldb  

1  rocksdb  是一个 LSM TREE 的结构

2  通过 gets  puts  scans 来获取数据(想起了REDIS)

3  数据的过滤方式支持正反方式

改进了

1 高于leveldb 10倍的写速度

2 更低的写放大

3 通过blooms 来进行范围的过滤(这速度应该是很快,BLOOMS 就是未来过滤确认不要的数据)

4 对SSD 磁盘的优化.


那么看完上面的也就很明确了,为什么TIDB的数据写入和读取有保证了,并且为什么TIDB 强烈建议你要用 SSD 磁盘.  因为ROCKSDB 就优化了 闪存数据的写入. (这点还的找时间看)

下图是ROCKSDB 的写入的数据的方式, 写入数据的方式中主要是通过内存来进行缓冲,然后在写入持久化的文件,同时也有日志的结构的方式保证数据库在未写入文件期间FAILOVER的数据完整性的保证。(想起了MONGODB)


图 1


关于memtable 内存中的数据主要有以下的数据存储的方式,不过数据存储的方式很多,而能快速的获取数据才是决定数据存取方式的重点。


1  跳表方式 

这是面对海量数据高效的数据存储方式和高效的数据提取的方式,适合范围数据的提取。这里我们叫 skiplist

2  hash 方式

这也是我们熟悉的数据存储的方式,通过hash标记的方式来进行数据的存储和查询,适合等值和确认值的查找

3  跳表+hash 的方式

ROCKSDB 通过在内存中建立如上的数据存储结构,通过空间换时间的方式来提高数据的写入和查询的速度。

(这也是你不要对 TIDB  KV数据存储引擎内存吝啬的原因之一)。


SST 数据存储方式就需要理解lsm 数据存储的原理了,可以去百度或G以下,很多承载海量数据的数据库都是用这样的方式来进行数据存储的,如Cassandra. 



同时ROCKSDB 在如下方面对数据存储进行了优化:


使用了多线程对数据进行压缩,并且使用了不同的压缩的方法,zlib, snappy两种数据的压缩方法。也对数据的修改进行了合并方式的优化(想想MYSQL中的数据合并写入技术(对于UPDATE频繁操作同一数据行)),对数据的写入和压缩分开,并行操作,使用wal log 提高数据写入的安全性。


那么ROCKSDB 如何快速读取数据,这里主要使用的方式是缓存,上面图1 中

ROCKSDB 在读取数据前会检测数据是否在缓存中 blockcache ,blockcache使用LRU算法,通过blockcache来进行数据的命中和查找。数据写入ROCKSDB 也是先写入memtable, 然后当memtable超过128MB后再写入磁盘。并且memtable是交换使用的,并且大可以产生5个memtable来进行数据的缓冲。



TIDB 的  TIKV 是如何使用ROCKSDB的,根据官方的文档中显示,tikv通过rocksdb 存储了raft log 和 用户数据,在一个TIKV 中会有两个ROCKSDB的instance 来分别存储 RL 和 UD.  这里也可以对这两个部分分别称为 raftdb, kvdb.


kvdb中存储的数据分为四个部分:


1  raft CF : 存储了每个TIDB 的region的元数据,占用的数据存储空间非常小,可以忽略。


2  lock CF :   存储悲观事务的悲观锁,以及分布式事务预写锁,在事务执行完毕后,这些锁会被快速的清理掉。一般来说这个锁的文件比较小,当发现文件快速增大,说明事务大量的在uncommit的模式,等等 commit 或者系统可能已经崩溃或出现BUG


3 write CF: 存储用户数据,这里存储的数据包含用户的数据以及MVCC的元数据,如果一行数据小于255BYTES 则存储在 write CF 中,同时也存主键以及索引的数据。


4    default CF : 大于255BYTES 的数据存储在default CF中。


TIDB TIKV是如何使用ROCKSDB 的读写优势的,这里TIKV使用节点中45%-60%的内存进行数据的缓冲,可以通过storage.blockcache.capacity来进行相关的百分比调节。同时TIKV 写操作也是利用相关的ROCKSDB 的特性,参见上面memtable 部分, 大使用2.5G 来进行数据的内存写驻留。


 TIKV中使用的数据存储引擎虽然是ROCKSDB,但tikv在mvcc中有其自己策略,用户在写入数据时,数据+ commit_ts的时间戳,并且数据的更新和删除都是异步的,将更新和删除的数据做新插入处理,另外一个线程在清理这些无用的数据。所以TIKV 空间的使用比实际存储的数据空间要大。


















相关文章