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状态的快照以及后续的修改
一个任何时刻的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 --->|