LevelDB:Compaction

農歷新年的最后一天,趁著假期看看代碼蒲障,順便做點筆記歹篓。時間上比較倉促瘫证,如有問題/疑問,歡迎指出庄撮。

簡介

LevelDB 的寫操作是 Append-Only 的背捌,新的數(shù)據(jù)寫入后,相應的舊數(shù)據(jù)就過期了洞斯。過期的數(shù)據(jù)需要被 Garbage Collection毡庆,不然數(shù)據(jù)文件的體積會持續(xù)膨脹,這是不可接受的烙如。

LevelDB 通過后臺線程的 compation 來對過期數(shù)據(jù)進行 Garbage Collection么抗。

分析

LevelDB 在執(zhí)行讀操作和寫操作的時候都有可能會調用 MaybeScheduleCompaction 函數(shù),MaybeScheduleCompaction 有可能觸發(fā) compaction亚铁。

  if (have_stat_update && current->UpdateStats(stats)) {
    MaybeScheduleCompaction();
  }
  1. 當本次讀取的數(shù)據(jù)沒有在 MemTable 和 Immutable MemTable 命中蝇刀, 而是從 SST 文件查找時,have_stat_updatetrue 徘溢。(相關代碼
  2. 從 SST 文件查找時吞琐,如果查找的文件多于一個,則記錄下第一個查找的文件然爆,存放在 stats 站粟。(相關代碼
  3. UpdateStats 函數(shù)根據(jù)步驟 2 記錄下的 SST 文件, allowed_seeks (一開始初始化為 2^30)減 1曾雕。當 allowed_seeks <= 0 且當前沒有其它文件等待 compaction 時卒蘸,記錄當前文件為待 compaction 的文件,并返回 true 翻默,否則返回 false。(相關代碼
  • 個人理解

瀏覽代碼的時候恰起,上面 2 和 3 的邏輯讓我不是很好理解修械。自己思考了一下,現(xiàn)在來嘗試回答一下(不一定完全準確)检盼。

LevelDB-多級緩存結構.PNG

LevelDB 的結構肯污,其實就是一個多級緩存的結構《滞鳎看看讀操作的順序就是很好理解這個多級緩存結構蹦渣。

  1. MemTable 是 Immutable MemTable 的緩存。
  2. Immutable MemTable 是 Level 0 的緩存貌亭。
  3. Level0 是 Level1 的緩存柬唯。
  4. Level1 是 Level2 的緩存。
  5. ...

從 SST 文件進行查找時圃庭,首先根據(jù)要查找的 Key 從文件的元數(shù)據(jù)(記錄著每一個 SST 文件 Key 范圍)找出每個 Level 對應的文件(某些 Level 可能沒有對應的文件锄奢,Level0 可能有多個對應文件)失晴。按照文件的新舊排序,就組成這個 Key 對應的一個多級緩存拘央。查找的時候也是按照這個順序涂屁,如果最新的 SST_n 文件命中目標,則直接返回結果灰伟,否則繼續(xù)查找 SST_n-1拆又、SST_n-2 ...

Level-SST-Cache.PNG

這種情況下,我們自然希望大部分請求都能在第一個 SST 文件命中栏账,這樣效率最高帖族。
如果有很多請求不能從第一個查找的文件命中目標,說明发笔,這個文件的 Key 并沒有緩存的價值盟萨,應該把這個文件向下一級 Level 合并掉,這樣可以減少無效的文件查找了讨。

  • 寫操作調用 MaybeScheduleCompaction

寫操作會調用 MakeRoomForWrite 為即將寫入數(shù)據(jù)準備空間捻激。整個邏輯由下面幾個分支組成。(相關代碼

  1. !bg_error_.ok() :后臺任務有錯誤前计,直接返回錯誤胞谭。
  2. allow_delay && versions_->NumLevelFiles(0) >= config::kL0_SlowdownWritesTrigger :正常的寫操作都 allow_delay 都為 true 。Level0 的文件數(shù)量超過了 config::kL0_SlowdownWritesTrigger 男杈,說明有可能寫入太多了丈屹,后臺線程來不及 Compaction,需要減慢寫操作伶棒。LevelDB 減慢寫操作的方法是旺垒,每個寫操作 sleep 1ms。
  3. !force && (mem_->ApproximateMemoryUsage() <= options_.write_buffer_size) :MemTable 還有足夠的空間支持這次寫入肤无,直接返回先蒋。
  4. imm != NULL : 來到這里說明 MemTable 的空間不夠了,且 Immutable MemTable 還存在(沒被 compaction 或 正在被 compaction)宛渐,需要等到compaction 完成竞漾。
  5. versions_->NumLevelFiles(0) >= config::kL0_StopWritesTrigger : Level0 的文件實在太多了,停止寫入操作窥翩,等待 compaction 完成业岁。
  6. 來到這里說明:1. Level0 的文件數(shù)量在正常范圍內;2. Immutable MemTable 已經被 Compact寇蚊;3. MemTable 已經滿了笔时。此時會切換 MemTable,并調用 MaybeScheduleCompaction幔荒。
  • MaybeScheduleCompaction 的實現(xiàn)相關代碼

MaybeScheduleCompaction函數(shù)的實現(xiàn)比較簡單:判斷幾個分支的情況糊闽,最后確定需要 Compaction 則將任務交交給后臺線程梳玫。

  1. bg_compaction_scheduled_ : 后臺線程已經在進行 compaction。
  2. shutting_down_.Acquire_Load() :正在關閉數(shù)據(jù)庫右犹。
  3. !bg_error_.ok() : 后臺任務錯誤提澎。
  4. imm_ == NULL && manual_compaction_ == NULL && !versions_->NeedsCompaction() :不需要 compaction。
  5. 由后臺線程調用 DBImpl::BGWork 進行compaction念链。DBImpl::BGWork 直接調用了 DBImpl::BackgroundCall盼忌。 (相關代碼
  1. 調用 BackgroundCompaction 執(zhí)行 compaction 。
  2. 調用 MaybeScheduleCompaction 嘗試再觸發(fā) compaction掂墓。
  • DBImpl::BackgroundCompaction 的實現(xiàn)相關代碼
  1. 持久化 Immutable MemTable:如果存在 Immutable MemTable谦纱,則調用 CompactMemTable 進行 compaction。一個 Immutable MemTable 被持久化為 Level0 的一個 SST 文件君编。(相關代碼
  2. 非人工觸發(fā)跨嘉,調用 VersionSet::PickCompaction ,獲得一個 Compaction 對象吃嘿。class Compaction 封裝了本次要進行 compaction 的信息祠乃。( class Compaction相關代碼 )。人工觸發(fā)的 compaction 走另一個分支兑燥,暫不討論亮瓷。
  3. VersionSet::PickCompaction 選擇要進行 compaction 的文件的策略有兩種(相關代碼):
    1)size compaction,某一 Level 的數(shù)據(jù)太多了降瞳;
    2)seek compaction嘱支,太多查詢沒有命中第一個 SST 文件。
    另外還有一點要注意的就是 Level0 需要特殊處理挣饥,因為每個文件的 Key 范圍可能是相交的除师。
  4. LevelDB 的 compaction 是 Level_n-1 合并到 Level_n。一些比較特殊的情況扔枫,只需要把 Level_n-1 的文件**移到 ** Level_n 即可馍盟。
  5. 一般的 compaction 分下面幾步:
    1)調用 DoCompactionWork, 執(zhí)行 compaction缠导。
    2)調用 CleanupCompaction唐责,清理已經完成的 compaction 完成。
    3)調用 DeleteObsoleteFiles, 刪除無效文件饥脑。

小結

  1. Compaction 都是通過 MaybeScheduleCompaction函數(shù)觸發(fā)的。
  2. Compaction 是單線程異步完成的雄可。
  3. seek compaction:LevelDB 在 SST 文件查找效率較低時(太多請求不在第一個 SST 文件命中购公,導致 allowed_seeks 小于等于 0)會觸發(fā) compaction。
  4. LevelDB 切換 MemTable 會生成 Immutable MemTable泊交,需要將 Immutable MemTable 持久化乳讥,此時會觸發(fā) compaction柱查。
  5. size compaction :每次執(zhí)行 Compaction 的任務完成后,會嘗試再次調用 MaybeScheduleCompaction 云石。因為有可能 level_n 的這次 compaction 導致 level_n+1 的 size 太大唉工,需要進行 compaction。
  6. Compaction 是單線程異步完成的汹忠,所以淋硝,LevelDB 的寫入速度在一定程度上受限于 compaction 的速度。對于寫入量比較平穩(wěn)的業(yè)務可能影響不大宽菜,但是對于經常有寫入峰值的業(yè)務谣膳,峰值時的寫入請求可能會受影響。
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末铅乡,一起剝皮案震驚了整個濱河市继谚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌阵幸,老刑警劉巖花履,帶你破解...
    沈念sama閱讀 219,110評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異侨嘀,居然都是意外死亡臭挽,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評論 3 395
  • 文/潘曉璐 我一進店門咬腕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來欢峰,“玉大人,你說我怎么就攤上這事涨共∨μ” “怎么了?”我有些...
    開封第一講書人閱讀 165,474評論 0 356
  • 文/不壞的土叔 我叫張陵举反,是天一觀的道長懊直。 經常有香客問我,道長火鼻,這世上最難降的妖魔是什么室囊? 我笑而不...
    開封第一講書人閱讀 58,881評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮魁索,結果婚禮上融撞,老公的妹妹穿的比我還像新娘。我一直安慰自己粗蔚,他們只是感情好尝偎,可當我...
    茶點故事閱讀 67,902評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般致扯。 火紅的嫁衣襯著肌膚如雪肤寝。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,698評論 1 305
  • 那天抖僵,我揣著相機與錄音鲤看,去河邊找鬼。 笑死裆针,一個胖子當著我的面吹牛刨摩,可吹牛的內容都是我干的。 我是一名探鬼主播世吨,決...
    沈念sama閱讀 40,418評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼澡刹,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了耘婚?” 一聲冷哼從身側響起罢浇,我...
    開封第一講書人閱讀 39,332評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎沐祷,沒想到半個月后嚷闭,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,796評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡赖临,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,968評論 3 337
  • 正文 我和宋清朗相戀三年胞锰,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片兢榨。...
    茶點故事閱讀 40,110評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡嗅榕,死狀恐怖,靈堂內的尸體忽然破棺而出吵聪,到底是詐尸還是另有隱情凌那,我是刑警寧澤,帶...
    沈念sama閱讀 35,792評論 5 346
  • 正文 年R本政府宣布吟逝,位于F島的核電站帽蝶,受9級特大地震影響,放射性物質發(fā)生泄漏块攒。R本人自食惡果不足惜励稳,卻給世界環(huán)境...
    茶點故事閱讀 41,455評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望囱井。 院中可真熱鬧麦锯,春花似錦、人聲如沸琅绅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽千扶。三九已至料祠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間澎羞,已是汗流浹背髓绽。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留妆绞,地道東北人顺呕。 一個月前我還...
    沈念sama閱讀 48,348評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像括饶,于是被迫代替她去往敵國和親株茶。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,047評論 2 355

推薦閱讀更多精彩內容