暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

浅谈TiKV中的数据持久化存储

在之前的文章中,我们熟悉了TiDB的整体架构,也初步了解了TiDB中各个组件的作用,其中TiKV作为存储引擎的核心功能是数据的持久化。TiKV中数据的持久化本质上依赖于集成在TiKV中的RocksDB来实现,本文着重叙述RocksDB中的数据写入(持久化)及读取机制。

如上图所示,每个TiKV节点上包含两个RocksDB实例,一个RocksDB负责存储用户数据(以region为单位的键值数据),另一个则用于存储Raft日志。

一.  关于RocksDB

RocksDB是一款非常优秀的开源单机存储引擎,针对Flash存储进行优化,延迟极小,使用LSM树存储模型。RocksDB的具体特点包括:

(1)高性能的key-value数据库。

(2)完善的持久化机制,同时保证性能和安全性。

(3)良好的支持范围查询。

(4)为需要存储TB级数据到本地FLASHRAM的应用服务器设计。

(5)针对存储在高速设备的中小键值进行优化,可以存储在FLASH或直接存储在内存。

(6)性能随CPU数量线性提升,对多核系统友好。

二.  RocksDB的写入流程

前面提到RocksDB是基于LSM树来存储数据,LSM树是一种分层存储模型,所有用户插入、删除或修改操作都会先存储到内存中,当操作达到一定的数量后再批量写入到磁盘。LSM数据存储跨越内存和磁盘,它包含几个重要的组件:内存中的MemTableimmutable MemTable以及磁盘上的SST TableSST文件)。

RocksDB的基本写入流程为:

(1)将写入操作以WAL日志的形式写入到磁盘进行持久化(这一步的目的是为了故障恢复)。

(2)将修改的数据写入到内存中的MemTable(如果刷盘前节点故障就可以通过上一步中的WAL来恢复数据)。MemTable是一个内存数据结构,它保存落盘前的数据,一般使用跳跃表或搜索树来保证有序性。

(3)MemTable达到一定的大小后(由write_buffer_size参数控制),数据会自动转存到immutable MemTable中,同时会生成一个新的MemTable负责新数据的写入。immutable MemTable可以解决MemTable自身刷盘引发的写阻塞问题。

(4)默认情况下每生成一个immutable MemTable就会往磁盘上刷写,如果由于写负载很高导致生成immutable MemTableFlush快,可能导致同时会有多个immutable MemTableimmutable MemTable较多时会触发流量控制,受参数write_stall(默认5)影响。

LSM在磁盘存储上是一个分层的组织结构,分为Level 0~Level 4Level 0比较特殊,它是immutable MemTable的完整复制。当Level 0文件达到一定个数(默认为4)时,会向下一层进行合并,此步骤称为compaction,在compaction过程中数据会进行压缩并且排序。每一层都包含多个SST文件,每个文件内部都是排序的键值对数据。每层的文件大小都有一个限制,当文件写满时会自动向下一层合并,依此类推。

RocksDB非常适合于写入频繁的场景,因为写入只需要在磁盘上写WAL日志以及MemTable中写入数据两次IO操作即可,后续的转存及合并动作均由后台进程异步完成。而传统的B+树在写入前需要先通过多次磁盘IO找到需要的数据并写入内存中再进行修改操作,因此LSM树的写入操作更加高效。对于删除操作,LSM树的实现方式同样是在MemTable中写入一条删除操作并在之后进行合并。在读取时,由于是从上往下的顺序读取数据,当在某一层(如Level2)读取到删除操作后,就能够明确此条数据已经被删除,不再往下读取。

三. RocksDB的读取流程

对于数据读取操作,与数据写入恰恰相反,LSM树效率通常不如B+,因为查询可能需要依次访问RocksDB中的Block CacheMemTableimmutable MemTable以及不同LevelSST文件,直到查询到相应的key为止。在具体的SST文件中查询时,由于SST中的数据都是有序存储,首先会判断查找的key是否在SST文件的MINMAX值之间,如果不在会立即跳过相应文件,如果存在则按照二分查找的方式进一步查找数据。同时,为了加速查找,引入布隆过滤器(Bloom Filter来提升查询的性能,它可以快速判断一个值是否不存在。

四. RocksDB中的Column Families

RocksDB中有一个很重要的概念叫列簇(Column Family),简称为CF。不同的列簇有各自独立的Block Cache/MemTable/immutable MemTableSST磁盘文件。通过将不同的表划分到不同的列簇,可以实现RocksDB级别的数据分片能力。目前,RocksDB里面不同列簇的WAL文件仍然是共享的。

文章转载自数据源的技术后花园,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论