RocksDB - MANIFEST

起因

前一段时间,在给用户升级 TiKV 并重启的时候,突然爆出了大量 “Sst file size mismatch” 的错误,也就是硬盘上面的 SST 文件跟实际 MANIFEST 里面的文件大小不一致。通常遇到这个问题,表明 RocksDB 的文件已经有问题了。

因为是大批量的 SST 都报了这样的错误,所以我们首先怀疑跟 disk 有关,看是否是硬件损坏。但通过观察系统日志,发现那段时间并没有系统异常,而且 disk 做了 raid0,照理也不应该出现如此大规模的文件损坏,所以我们决定排除。剩下的就是怀疑 RocksDB 自己的 bug 了。

于是将这个问题放在了 RocksDB 的群里面,得知在某些新版本内核的 XFS 文件系统上面,fallocate 函数是有 bug 的,这个就会导致使用 fallocate 分配的 SST 文件 size 跟实际 manifest 里面的不一致。虽然是一个 kernel 的 bug,但 RocksDB 也需要绕过去,修复在这个 https://github.com/facebook/rocksdb/pull/2038

但上面出现不一致错误的 SST 文件并没有损坏,只是文件末尾多了一些 hole,只要我们从 MANIFEST 文件里面得到这个 SST 实际的 size,手动 truncate,就可以正常使用了。为了修复这些文件,我决定研究一下 manifest 文件。

MANIFEST

MANIFEST 记录着 RocksDB 一些状态变化的信息,用来在重启的时候能让 RocksDB 还原到最近的一致状态上面去。

为什么需要 MANIFEST 呢?RocksDB 是一个 key-value storage,但它实际的数据文件还是会存放到操作系统的文件系统上面。有些时候,文件系统的操作并不是原子的,可能因为一些系统的问题导致出现数据不一致的状态,即使文件系统有 journal log,也不是绝对安全的。所以 RocksDB 并不会将自己的一些 meta 信息存放到自己的 key-value 系统里面,而是使用了单独的一个 MANIFEST 文件。

MANIFEST 包括一系列的 manifest 文件,以及标识最后最新的一个 manifest 文件的 CURRENT 文件。Manifest 文件名的格式类似 MANIFEST-<seq no>,sequence number 会一直递增,最新的 manifest 文件一定有最大的 sequence number。

我们可以认为 MANIFEST 是一个 transaction log,只要 RocksDB 的状态变化,就会记录一下。当一个 manifest 文件超过了配置的最大值的时候,一个包含当前 RocksDB 状态信息的新的 manifest 文件就会创建,CURRENT 文件会记录最新的 manifest 文件信息。当所有的更改都 sync 到文件系统之后,之前老的 manifest 文件就会被清除。

MANIFEST = { CURRENT, MANIFEST-<seq-no>* } 
CURRENT = 标识最新的一个 manifest 文件
MANIFEST-<seq no> = 某个 snapshot 的 RocksDB 状态以及后续的更新操作

这里需要注意,一定要设置 max_manifest_file_size,不然 RocksDB recover 的时间会非常的长。

Version Edit

RocksDB 使用 version 来表示任意时间的一个特定状态(其实就是 snapshot),任何对 version 的改动会被认为是一次 version edit。一个 version 通过合并一系列的 version edits 来构造。也就是一个 manifest 文件其实就是包含着一系列 version edits record。每一个 record 都会有一个唯一的 edit number 来标识。

Record Format

Version Edit 里面的类型都采用了特定的编码方式,对于整形,通常是 Var 和 Fixed 两种,譬如 Var32 就是对 int32 整数的可变长度编码。

对于 string 类型,使用 size(n) + content 的方式,size 就是整个 string 的实际长度,用 Var32 方式编码。

对于一个 Version edit 记录来说,由 record ID 加上可变长度的 bytes 组成,record ID 使用 Var32 编码,而后面实际的 record 数据则是需要根据不同的类型来实际进行解析。

Record Type

Record 有多重类型,包括 Comparator,Log Number,Previous Manifest File Number 等,譬如对于 Comparator 来说,格式就是

+-------------+----------------+
| kComparator | data           |
+-------------+----------------+
<-- Var32 --->|<-- String   -->|

具体不同 Type 的解析,可以参考 RocksDB 源码 VersionEdit::DecodeFrom 函数,因为比较简单,所以这里不再做说明。

这里我们重点关注 record 为 New File 的类型,因为它会记录实际的 SST 的信息,譬如 New File Format 4 的格式就是:

+--------------+-------------+--------------+------------+----------------+--------------+----------------+----------------+
| 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      -->|

具体到我们之前出现的问题,如果要修复 SST,就需要在 manifest 文件里面读取到 New File record,然后解析出它实际的 path 以及对应的 file size,然后将其做 truncate。

后记

因为一个 kernel 的 bug,我们得以研究了一下 MANIFEST。当然因为 RocksDB 已经提交了 PR 去 fix 这个问题,加上现阶段用户那边除了一台机器有这个 kernel 的 bug,其他机器都是没问题的,所以相关 truncate 工具并没有写。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容