为什么最近一直在看分布式数据库,因为第六感给我的指示是, 分布式数据库是国产数据库下一个要发力的点, 为什么. 如果作为一个产品经理, 首先一个产品要有用户的画像, 那么什么数据库是可以找到金主"爸爸"的, 分布式数据库,并且这些金主们, 应该都很有钱. 单体数据库能吸引大量资金的时代是要过去了. 一个维护费用低,稳定性强, 扩展能力强并且将之前数据库的"毛病" 都一一扫尽的数据库产品, 银行和金融机构应该是很欢喜的. 这也是一些银行自研分布式数据库,或者使用商用分布式数据库的原因吧.
分布式数据库的存储必然是要和单体数据库的存储模式不一样, 那么看看一些成熟的分布式数据库到底用了那些存储模式,并分析一下到底为什么有利于拓宽眼界, 追上"潮流".
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 空间的使用比实际存储的数据空间要大。