RocksDB - MANIFEST

起因

前一段時(shí)間雌芽,在給用戶升級(jí) TiKV 并重啟的時(shí)候肤舞,突然爆出了大量 “Sst file size mismatch” 的錯(cuò)誤,也就是硬盤上面的 SST 文件跟實(shí)際 MANIFEST 里面的文件大小不一致。通常遇到這個(gè)問(wèn)題,表明 RocksDB 的文件已經(jīng)有問(wèn)題了猾警。

因?yàn)槭谴笈康?SST 都報(bào)了這樣的錯(cuò)誤,所以我們首先懷疑跟 disk 有關(guān)隆敢,看是否是硬件損壞发皿。但通過(guò)觀察系統(tǒng)日志,發(fā)現(xiàn)那段時(shí)間并沒有系統(tǒng)異常拂蝎,而且 disk 做了 raid0穴墅,照理也不應(yīng)該出現(xiàn)如此大規(guī)模的文件損壞,所以我們決定排除温自。剩下的就是懷疑 RocksDB 自己的 bug 了玄货。

于是將這個(gè)問(wèn)題放在了 RocksDB 的群里面,得知在某些新版本內(nèi)核的 XFS 文件系統(tǒng)上面捣作,fallocate 函數(shù)是有 bug 的誉结,這個(gè)就會(huì)導(dǎo)致使用 fallocate 分配的 SST 文件 size 跟實(shí)際 manifest 里面的不一致鹅士。雖然是一個(gè) kernel 的 bug券躁,但 RocksDB 也需要繞過(guò)去,修復(fù)在這個(gè) https://github.com/facebook/rocksdb/pull/2038

但上面出現(xiàn)不一致錯(cuò)誤的 SST 文件并沒有損壞也拜,只是文件末尾多了一些 hole以舒,只要我們從 MANIFEST 文件里面得到這個(gè) SST 實(shí)際的 size,手動(dòng) truncate慢哈,就可以正常使用了蔓钟。為了修復(fù)這些文件,我決定研究一下 manifest 文件卵贱。

MANIFEST

MANIFEST 記錄著 RocksDB 一些狀態(tài)變化的信息滥沫,用來(lái)在重啟的時(shí)候能讓 RocksDB 還原到最近的一致狀態(tài)上面去。

為什么需要 MANIFEST 呢键俱?RocksDB 是一個(gè) key-value storage兰绣,但它實(shí)際的數(shù)據(jù)文件還是會(huì)存放到操作系統(tǒng)的文件系統(tǒng)上面。有些時(shí)候编振,文件系統(tǒng)的操作并不是原子的缀辩,可能因?yàn)橐恍┫到y(tǒng)的問(wèn)題導(dǎo)致出現(xiàn)數(shù)據(jù)不一致的狀態(tài),即使文件系統(tǒng)有 journal log踪央,也不是絕對(duì)安全的臀玄。所以 RocksDB 并不會(huì)將自己的一些 meta 信息存放到自己的 key-value 系統(tǒng)里面,而是使用了單獨(dú)的一個(gè) MANIFEST 文件畅蹂。

MANIFEST 包括一系列的 manifest 文件健无,以及標(biāo)識(shí)最后最新的一個(gè) manifest 文件的 CURRENT 文件。Manifest 文件名的格式類似 MANIFEST-<seq no>魁莉,sequence number 會(huì)一直遞增睬涧,最新的 manifest 文件一定有最大的 sequence number。

我們可以認(rèn)為 MANIFEST 是一個(gè) transaction log旗唁,只要 RocksDB 的狀態(tài)變化畦浓,就會(huì)記錄一下。當(dāng)一個(gè) manifest 文件超過(guò)了配置的最大值的時(shí)候检疫,一個(gè)包含當(dāng)前 RocksDB 狀態(tài)信息的新的 manifest 文件就會(huì)創(chuàng)建讶请,CURRENT 文件會(huì)記錄最新的 manifest 文件信息。當(dāng)所有的更改都 sync 到文件系統(tǒng)之后屎媳,之前老的 manifest 文件就會(huì)被清除夺溢。

MANIFEST = { CURRENT, MANIFEST-<seq-no>* } 
CURRENT = 標(biāo)識(shí)最新的一個(gè) manifest 文件
MANIFEST-<seq no> = 某個(gè) snapshot 的 RocksDB 狀態(tài)以及后續(xù)的更新操作

這里需要注意,一定要設(shè)置 max_manifest_file_size烛谊,不然 RocksDB recover 的時(shí)間會(huì)非常的長(zhǎng)风响。

Version Edit

RocksDB 使用 version 來(lái)表示任意時(shí)間的一個(gè)特定狀態(tài)(其實(shí)就是 snapshot),任何對(duì) version 的改動(dòng)會(huì)被認(rèn)為是一次 version edit丹禀。一個(gè) version 通過(guò)合并一系列的 version edits 來(lái)構(gòu)造状勤。也就是一個(gè) manifest 文件其實(shí)就是包含著一系列 version edits record鞋怀。每一個(gè) record 都會(huì)有一個(gè)唯一的 edit number 來(lái)標(biāo)識(shí)。

Record Format

Version Edit 里面的類型都采用了特定的編碼方式持搜,對(duì)于整形密似,通常是 Var 和 Fixed 兩種,譬如 Var32 就是對(duì) int32 整數(shù)的可變長(zhǎng)度編碼葫盼。

對(duì)于 string 類型残腌,使用 size(n) + content 的方式,size 就是整個(gè) string 的實(shí)際長(zhǎng)度贫导,用 Var32 方式編碼抛猫。

對(duì)于一個(gè) Version edit 記錄來(lái)說(shuō),由 record ID 加上可變長(zhǎng)度的 bytes 組成孩灯,record ID 使用 Var32 編碼邑滨,而后面實(shí)際的 record 數(shù)據(jù)則是需要根據(jù)不同的類型來(lái)實(shí)際進(jìn)行解析。

Record Type

Record 有多重類型钱反,包括 Comparator掖看,Log Number,Previous Manifest File Number 等面哥,譬如對(duì)于 Comparator 來(lái)說(shuō)哎壳,格式就是

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

具體不同 Type 的解析,可以參考 RocksDB 源碼 VersionEdit::DecodeFrom 函數(shù)尚卫,因?yàn)楸容^簡(jiǎn)單归榕,所以這里不再做說(shuō)明。

這里我們重點(diǎn)關(guān)注 record 為 New File 的類型吱涉,因?yàn)樗鼤?huì)記錄實(shí)際的 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      -->|

具體到我們之前出現(xiàn)的問(wèn)題,如果要修復(fù) SST怎爵,就需要在 manifest 文件里面讀取到 New File record特石,然后解析出它實(shí)際的 path 以及對(duì)應(yīng)的 file size,然后將其做 truncate鳖链。

后記

因?yàn)橐粋€(gè) kernel 的 bug姆蘸,我們得以研究了一下 MANIFEST。當(dāng)然因?yàn)?RocksDB 已經(jīng)提交了 PR 去 fix 這個(gè)問(wèn)題芙委,加上現(xiàn)階段用戶那邊除了一臺(tái)機(jī)器有這個(gè) kernel 的 bug逞敷,其他機(jī)器都是沒問(wèn)題的,所以相關(guān) truncate 工具并沒有寫灌侣。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末推捐,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子侧啼,更是在濱河造成了極大的恐慌牛柒,老刑警劉巖愕秫,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異焰络,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)符喝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門闪彼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人协饲,你說(shuō)我怎么就攤上這事畏腕。” “怎么了茉稠?”我有些...
    開封第一講書人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵描馅,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我而线,道長(zhǎng)铭污,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任膀篮,我火速辦了婚禮嘹狞,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘誓竿。我一直安慰自己磅网,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開白布筷屡。 她就那樣靜靜地躺著涧偷,像睡著了一般。 火紅的嫁衣襯著肌膚如雪毙死。 梳的紋絲不亂的頭發(fā)上燎潮,一...
    開封第一講書人閱讀 49,760評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音扼倘,去河邊找鬼跟啤。 笑死,一個(gè)胖子當(dāng)著我的面吹牛唉锌,可吹牛的內(nèi)容都是我干的隅肥。 我是一名探鬼主播,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼袄简,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼腥放!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起绿语,我...
    開封第一講書人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤秃症,失蹤者是張志新(化名)和其女友劉穎候址,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體种柑,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡岗仑,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了聚请。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片荠雕。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖驶赏,靈堂內(nèi)的尸體忽然破棺而出炸卑,到底是詐尸還是另有隱情,我是刑警寧澤煤傍,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布盖文,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜官硝,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望返帕。 院中可真熱鬧,春花似錦篙挽、人聲如沸荆萤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)链韭。三九已至,卻和暖如春煮落,著一層夾襖步出監(jiān)牢的瞬間敞峭,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工蝉仇, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留旋讹,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓轿衔,卻偏偏與公主長(zhǎng)得像沉迹,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子害驹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容