概述¶
Rocksdb 对文件系统以及存储介质保持不可预知的态度。文件系统操作不是原子的,并且在系统错误的时候容易出现不一致。即使打开了日志系统,文件系统还是不能在一个不合法的重启中保持一致。POSIX 文件系统不支持原子化的批量操作。因此,无法依赖 RocksDB 的数据存储文件中的元数据文件来构建 RocksDB 重启前的最后的状态。
RocksDB 有一个内建的机制来处理这些 POSIX 文件系统的限制,这个机制就是保存一个名为 MANIFEST 的 ROCKSDB 状态变化的事务日志文件。MANIFEST 文件用于在重启的时候,恢复 rocksdb 到最后一个一致的一致性状态。
术语¶
- MANIFEST 指通过一个事务日志,来追踪 Rocksdb 状态迁移的系统
- Manifest 日志 指一个独立的日志文件,它包含 RocksDB 的状态快照/版本
- CURRENT 指最后的 Manifest 日志
如何工作?¶
MANIFEST 是一个 RocksDB 状态变更的事务日志。MANIFEST 由 manifest 日志文件以及最后的 manifest 文件指针组成。Manifest 日志是滚动日志文件,命名方式为 MANIFEST-(seq number)。seq number 总是递增。CURRENT 是一个特殊的文件,用于声明最新的 manifest 日志文件。
在系统(重新)启动的时候,最新的 manifest 日志文件会包含一个一致的 ROCKSDB 的状态。任何对 RocksDB 状态修改的子序列都会被记录到 manifest 日志文件中。当一个 manifest 日志超过特定的大小,一个新的 manifest 日志文件会更新,且保证刷盘到文件系统。成功更新 CURRENT 文件之后,就的 manifest 文件就会被删掉。
MANIFEST={CURRENT, MANIFEST-<seq-no>*}
CURRENT = 指向当前manifest日志的文件指针
MANIFEST-<seq-no> = 包含RocksDB状态的快照以及后续的修改
版本(version)编辑¶
一个任何时刻的 RocksDB 的特定状态都指向一个版本(version)(换句话说,快照)。任何针对这个版本的修改,都被认为是一个版本编辑。一个版本(或者说一个 rocksDB 的状态快照)由一系列的版本编辑合并构成。本质上来说,一个 manifest 日志文件是一个版本编辑的序列。
版本编辑 = 任何RocksDB状态变更
版本 = {版本编辑*}
manifest日志文件 = {版本,版本编辑*} = {版本编辑*}
版本编辑布局¶
Manifest 日志是一个版本编辑记录的序列。版本编辑记录类型是通过编辑标示号码区分的。
我们使用下列数据类型来进行编码/解码。
数据类型¶
简单数据类型
- VarX - 由 intX 编码的变长字符
- FixedX - 由 intX 编码的定长字符
复杂数据类型
string - 带长度前缀的字符串数据:
+-----------+--------------------+
| size (n) | content of string |
+-----------+--------------------+
|<- Var32 ->|<-- n -->|
版本编辑记录格式¶
版本编辑记录使用下面的格式。解码器通过记录标示号码区分不同类别的记录
+-------------+------ ......... ----------+
| Record ID | Variable size record data |
+-------------+------ .......... ---------+
<-- Var32 --->|<-- varies by type -->
版本编辑记录类型以及布局¶
针对 RocksDB 不同的状态变更,有非常多样的编辑记录。
比较器编辑记录:
记录比较器的名字
+-------------+----------------+
| kComparator | data |
+-------------+----------------+
<-- Var32 --->|<-- String -->|
日志数量编辑记录: 最新的 WAL 日志文件数量
+-------------+----------------+
| kLogNumber | log number |
+-------------+----------------+
<-- Var32 --->|<-- Var64 -->|
上一个文件号编辑记录: 上一个 manifest 文件号
+------------------+----------------+
| kPrevFileNumber | log number |
+------------------+----------------+
<-- Var32 --->|<-- Var64 -->|
下一个文件号编辑记录: 下一个 manifest 文件号:
+------------------+----------------+
| kNextFileNumber | log number |
+------------------+----------------+
<-- Var32 --->|<-- Var64 -->|
最新的 seq number 编辑记录:
rocksdb 最新的 seq number
+------------------+----------------+
| kLastSequence | log number |
+------------------+----------------+
<-- Var32 --->|<-- Var64 -->|
最大的列族编辑记录:
调整允许使用的最大列族数
+---------------------+----------------+
| kMaxColumnFamily | log number |
+---------------------+----------------+
<-- Var32 --->|<-- Var32 -->|
删除文件编辑记录: 把一个文件标记为从数据库中删除
+-----------------+-------------+--------------+
| kDeletedFile | level | file number |
+-----------------+-------------+--------------+
<-- Var32 --->|<-- Var32 -->|<-- Var64 -->|
新文件编辑记录: 把一个文件标记为新加入数据库,并且提供必要的元数据给 ROCKSDB
- 文件编辑记录与压缩信息
+--------------+-------------+--------------+------------+----------------+--------------+----------------+----------------+
| kNewFile4 | level | file number | file size | smallest_key | largest_key | smallest_seqno | largest_seq_no |
+--------------+-------------+--------------+------------+----------------+--------------+----------------+----------------+
|<-- var32 -->|<-- var32 -->|<-- var64 -->|<- var64 ->|<-- String -->|<-- String -->|<-- var64 -->|<-- var64 -->|
+-----------+---------------+-------+------------------+-------+--------------+
|kPathID ---| Path size(n) | path | kNeedCompaction | 1 | value (0/1) |
+-----------+---------------+-------+------------------+-------+--------------+
<- var32 ->|<-- var32 -->|<- n ->|<-- var32 -->|<- 1 ->|<-- 1 -->|
- 文件编辑记录向后兼容
+--------------+-------------+--------------+------------+----------------+--------------+----------------+----------------+
| kNewFile2 | level | file number | file size | smallest_key | largest_key | smallest_seqno | largest_seq_no |
+--------------+-------------+--------------+------------+----------------+--------------+----------------+----------------+
<-- var32 -->|<-- var32 -->|<-- var64 -->|<- var64 ->|<-- String -->|<-- String -->|<-- var64 -->|<-- var64 -->|
- 文件编辑记录与路径信息
+--------------+-------------+--------------+-------------+-------------+----------------+--------------+
| kNewFile3 | level | file number | Path ID | file size | smallest_key | largest_key |
+--------------+-------------+--------------+-------------+-------------+----------------+--------------+
|<-- var32 -->|<-- var32 -->|<-- var64 -->|<-- var32 -->|<-- var64 -->|<-- String -->|<-- String -->|
+----------------+----------------+
| smallest_seqno | largest_seq_no |
+----------------+----------------+
<-- var64 -->|<-- var64 -->|
列族信息编辑记录:
标记列族功能的状态(打开/关闭)
+------------------+----------------+
| kColumnFamily | 0/1 |
+------------------+----------------+
<-- Var32 --->|<-- Var32 -->|
列族增加编辑记录:
增加一个列族
+---------------------+----------------+
| kColumnFamilyAdd | cf name |
+---------------------+----------------+
<-- Var32 --->|<-- String -->|
列族删除编辑记录: 删除所有列族
+---------------------+
| kColumnFamilyDrop |
+---------------------+
<-- Var32 --->|