Rocksdb Compaction原理

来源:http://www.cnblogs.com/cchust/archive/2016/10/28/6007486.html
-Advertisement-
Play Games

概述 compaction主要包括兩類:將記憶體中imutable 轉儲到磁碟上sst的過程稱之為flush或者minor compaction;磁碟上的sst文件從低層向高層轉儲的過程稱之為compaction或者是major compaction。對於myrocks來說,compaction過程都 ...


概述

     compaction主要包括兩類:將記憶體中imutable 轉儲到磁碟上sst的過程稱之為flush或者minor compaction;磁碟上的sst文件從低層向高層轉儲的過程稱之為compaction或者是major compaction。對於myrocks來說,compaction過程都由後臺線程觸發,對於minor compaction和major compaction分別對應一組線程,通過參數rocksdb_max_background_flushes和rocksdb_max_background_compactions可以來控制。通過minor compaction,記憶體中的數據不斷地寫入的磁碟,保證有足夠的記憶體來應對新的寫入;而通過major compaction,多層之間的SST文件的重覆數據和無用的數據可以迅速減少,進而減少sst文件占用的磁碟空間。對於讀而言,由於需要訪問的sst文件變少了,也會有性能的提升。由於compaction過程在後臺不斷地做,單位時間內compaction的內容不多,不會影響整體的性能,當然這個可以根據實際的場景對參數進行調整,compaction的整體架構可以參見圖1。瞭解了compaction的基本概念,下麵會詳細介紹compaction的流程,主要包括兩部分flush(minor compaction),compaction(major compaction),對應的入口函數分別是BackgroundFlush和BackgroundCompaction。

rocksdb架構圖.png

                                          圖1

flush(minor-compaction)

      Rockdb中在記憶體的數據都是通過memtable存儲,主要包括兩種形式,active-memtable和immutable-memtable。active-memtable是當前正在提供寫操作的memtable,當active-memtable寫入超過閥值(通過參數wirte_buffer_size控制),會將這個memtable標記為read-only,然後再創建一個新的memtable供新的寫入,這個read-only的memtable就是immutable-memtable。我們所說的flush操作就是將imumutable-memtable 寫入到level0的過程。flush過程以column family為單位進行,一個column family是一組sst文件的集合,在myrocks中一個表可以是一個單獨的column family,也可以多個表共用一個column family。每個column family中可能包含一個或多個immutable-memtable,一個flush線程會抓取column family中所有的immutable-memtable進行merge,然後flush到level0。由於一個線程在flush過程中,新的寫入也源源不斷進來,進而產生新的immutable-memtable,其它flush線程可以新起一個任務進行flush,因此在rocksdb體系下,active-memtable->immutable-memtable->sst文件轉換過程是流水作業,並且flush可以併發執行,相對於levelDB,併發compaction的速度要快很多。通過參數max_write_buffer_number可以控制memtable的總數量,如果寫入非常快,而compaction很慢,會導致memtable數量超過閥值,導致write stall的嚴重後果。另外一個參數是min_write_buffer_number_to_merge,整個參數是控制至少幾個immutable才會觸發flush,預設是1。flush的基本流程如下:

1.遍歷immutable-list,如果沒有其它線程flush,則加入隊列

2.通過迭代器逐一掃描key-value,將key-value寫入到data-block 

3.如果data block大小已經超過block_size(比如16k),或者已經key-value對是最後的一對,則觸發一次block-flush

4.根據壓縮演算法對block進行壓縮,並生成對應的index block記錄(begin_key, last_key, offset)

5.至此若幹個block已經寫入文件,併為每個block生成了indexblock記錄

6.寫入index block,meta block,metaindex block以及footer信息到文件尾

7.將變化sst文件的元信息寫入manifest文件

      flush實質是對memtable中的記錄進行一次有序遍歷,在這個過程中會去掉一些冗餘的記錄,然後以block為單位寫入sst文件,寫入文件時根據壓縮策略確定是否對block進行壓縮。為什麼會有冗餘記錄?這個主要是因為rocksdb中無論是insert,update還是delete,所有的寫入操作都是以append的方式寫入memtable,比如先後對key=1的記錄執行三個操作insert(1),update(1),delete(1),在rocksdb中會產生3條不同記錄。(在innodb中,對於同一個key的操作都是原地更新,只有一條記錄)。實際上delete後這個記錄不應該存在了,所以在合併時,可以幹掉這些冗餘的記錄,比如這裡的insert(1),update(1),這種合併使得flush到level0的sst已經比較緊湊。冗餘記錄主要有以下三種情況:(user_key, op)表示對user_key的操作,比如put,delete等。

1.對於(user_key,put),(user_key,delete),則可以將put刪掉

2.對於(user_key,single-delete),(user_key,put),single-delete保證put,delete成對出現,可以同時將兩條記錄都刪掉。

3.對於(user_key,put1),(user_key,put2),(user_key,put3)可以幹掉比較老的put

對於以上3種情況,都要考慮snapshot,如果要刪除的key在某個snapshot可見,則不能刪除。註意第1種情況,(user_key,delete)這條記錄是不能被刪除的,因為對用戶而言,這條記錄已經不存在了,但由於rocksdb的LSM-tree存儲結構,這個user_key的記錄可能在level0,level1或者levelN,所以(user_key, delete)這條記錄要保留,直到進行最後一層的compaction操作時才能將它幹掉。第2種情況,single-delete是一個特殊的delete操作,這個操作保證了put,delete一定是成對出現的,所以flush時,可以將這兩條記錄同時幹掉。 

compaction(major-compaction)

       我們通常所說的compaction就是major-compaction,sst文件從低level合併到高level的過程,這個過程與flush過程類似,也是通過迭代器將多個sst文件的key進行merge,遍歷key然後創建sst文件。flush的觸發條件是immutable memtable的數量是否超過了min_write_buffer_number_to_merge,而compaction的觸發條件是兩類:文件個數和文件大小。對於level0,觸發條件是sst文件個數,通過參數level0_file_num_compaction_trigger控制,score通過sst文件數目與level0_file_num_compaction_trigger的比值得到。level1-levelN觸發條件是sst文件的大小,通過參數max_bytes_for_level_base和max_bytes_for_level_multiplier來控制每一層最大的容量,score是本層當前的總容量與能存放的最大容量的比值。rocksdb中通過一個任務隊列維護compaction任務流,通過判斷某個level是否滿足compaction條件來加入隊列,然後從隊列中獲取任務來進行compact。compaction的主要流程如下:

1.首先找score最高的level,如果level的score>1,則選擇從這個level進行compaction

2.根據一定的策略,從level中選擇一個sst文件進行compact,對於level0,由於sst文件之間(minkey,maxkey)有重疊,所以可能有多個。

3.從level中選出的文件,我們能計算出(minkey,maxkey)

4.從level+1中選出與(minkey,maxkey)有重疊的sst文件

5.多個sst文件進行歸併排序,合併寫出到sst文件

6.根據壓縮策略,對寫出的sst文件進行壓縮

7.合併結束後,利用VersionEdit更新VersionSet,更新統計信息

     上面的步驟基本介紹了compaction的流程,簡單來說就是選擇某個level的sst文件與level+1中存在重疊的sst文件進行合併,然後將合併後的文件寫入到level+1層的過程。通過判斷每個level的score是否大於1,確定level是否需要compact;對於level中sst文件的選擇,會有幾種策略,預設是選擇文件size較大,包含delete記錄較多的sst文件,這種文件儘快合併有利於縮小空間。關於選擇sst文件的策略可以參考options.h中的CompactionPri的定義。每次會從level中選取一個sst文件與下層compact,但由於level0中可能會有多個sst文件存在重疊的範圍,因此一次compaction可能有多個level0的sst文件參與。rocksdb後臺一般有多個線程執行compact任務,compaction線程不斷地從任務隊列中獲取任務,也會不斷地檢查每個level是否需要compact,然後加入到隊列,因此整體來看,compact過程是併發的,但併發的基本原則是,多個併發任務不會有重疊的key。對於level0來說,由於多個sst文件會存在重疊的key範圍,根據level0,level+1中參與compact的sst文件key範圍進行分區,劃分為多個子任務進行compact,所有子任務併發執行,都執行完成後,整個compact過程結束。另外還有一個問題要說明的是,compact時並不是都需要合併,如果level中的輸入sst文件與level+1中無重疊,則可以直接將文件移到level+1中。 

Universal Compaction

      前面介紹的compaction類型是level compaction,在rocksdb中還有一類compaction,稱之為Univeral Compaction。Univeral模式中,所有的sst文件都可能存在重疊的key範圍。對於R1,R2,R3,...,Rn,每個R是一個sst文件,R1中包含了最新的數據,而Rn包含了最老的數據。合併的前提條件是sst文件數目大於level0_file_num_compaction_trigger,如果沒有達到這個閥值,則不會觸發合併。在滿足前置條件的情況下,按優先順序順序觸發以下合併。

1.如果空間放大超過一定的比例,則所有sst進行一次compaction,所謂的full compaction,通過參數max_size_amplification_percent控制。

2.如果前size(R1)小於size(R2)在一定比例,預設1%,則與R1與R2一起進行compaction,如果(R1+R2)*(100+ratio)%100<R3,則將R3也加入到compaction任務中,依次順序加入sst文件

3.如果第1和第2種情況都沒有compaction,則強制選擇前N個文件進行合併。

      相對於level compaction,Univeral compaction由於每一次合併的文件較多,相對於level compaction的多層合併,寫放大較小,付出的代價是空間放大較大。除了前面介紹的level compaction和univeral compaction,rocksdb還支持一種FIFO的compaction。FIFO顧名思義就是先進先出,這種模式周期性地刪除舊數據。在FIFO模式下,所有文件都在level0,當sst文件總大小超過閥值max_table_files_size,則刪除最老的sst文件。整個compaction是LSM-tree數據結構的核心,也是rocksDB的核心,本文梳理了幾種compaction方式的基本流程,裡面還有很多的細節沒有涉及到,有興趣的同學可以在本文的基礎上仔細閱讀源碼,加深對compaction的理解。

附錄

相關文件:

rocksdb/db/flush_job.cc 

include/rocksdb/universal_compaction.h

rocksdb/db/compaction_job.cc

db/compaction_picker.cc

rocksdb/table/block_based_table_builder.cc

相關介面:

FlushMemTableToOutputFile //flush memtable到level0

FlushJob::Run  //flush memtable 任務

PickMemtablesToFlush //選擇可以flush的immutable-memtable

WriteLevel0Table //刷sst文件到level0

BuildTable //實現創建sst文件

UniversalCompactionPicker::NeedsCompaction //是否需要compact

PickCompaction //需要進行compact的sst文件

PickCompactionUniversalReadAmp //選擇相鄰的sst文件進行合併

NeedsCompaction //判斷文件是否level是否需要compact

LevelCompactionPicker::PickCompaction // 獲取level中sst文件進行compact

LevelCompactionPicker::PickCompactionBySize

IsTrivialMove // 是否可以移動更深的Level,沒有overlap的情況下。

ShouldFormSubcompactions  // 判斷是否可以將compaction任務分片

CompactionJob::Prepare    // 劃分子任務

CompactionJob::Run()      // compaction的具體實現 

BlockBasedTableBuilder::Finish  //生成sst文件

參考文檔

http://rocksdb.org/blog/2016/01/29/compaction_pri.html

http://smalldatum.blogspot.com/2016/02/compaction-priority-in-rocksdb.html

http://rocksdb.org/blog/2016/01/29/compaction_pri.html

https://github.com/facebook/rocksdb/blob/v3.11/include/rocksdb/options.h#L366-L423

http://rocksdb.org/blog/2015/07/23/dynamic-level.html

https://github.com/facebook/rocksdb/wiki/RocksDB-Tuning-Guide

http://alinuxer.sinaapp.com/?p=400

http://dirtysalt.github.io/leveldb.html

http://openinx.github.io/2014/08/17/leveldb-compaction/

http://www.cnblogs.com/KevinT/p/3819134.html

http://luodw.cc/2015/11/04/leveldb-20/

https://askdba.alibaba-inc.com/libary/control/getArticle.do?articleId=72393


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 昨晚有實現一個小功能,就是在MS SQL Server中,檢查字元串是否包含有大小寫字母。通常應用在字元串的複雜度。 DECLARE @s NVARCHAR(40) = N'SDFfgGRYJhhTYUJ' IF LOWER(@s) COLLATE Latin1_General_CS_AS <> @ ...
  • 在SQL Server中啟用CLR,可以執行下麵SQL語句: EXEC sp_configure 'clr enabled'; EXEC sp_configure 'clr enabled' , '1'; RECONFIGURE; ...
  • 1. 找到MySQL的配置文件,一般在MySQL的安裝目錄下,例如我的: C:\Program Files\MySQL\MySQL Server 5.7 ,打開下麵的一個配置文件: my-default.ini ,在最後面添加一行配置: show_compatibility_56 = 1 。 2. ... ...
  • zookeeper的安裝(圖文詳解。。。來點擊哦!) 一、伺服器的配置 三台伺服器: 192.168.83.133 sunshine 192.168.83.134 sunshineMin 192.168.83.135 sunshineMax 在每台伺服器的hosts文件中添加:(命令:vi /etc ...
  • MongoDB的訪問控制能夠有效保證資料庫的安全,訪問控制是指綁定Application監聽的IP地址,設置監聽埠,使用賬戶和密碼登錄 一,訪問控制的參數 1,綁定IP地址 mongod 參數:--bind_ip <ip address> 預設值是所有的IP地址都能訪問,該參數指定MongoDB對 ...
  • 本文出處:http://www.cnblogs.com/wy123/p/6008477.html 關於統計信息對數據行數做預估,之前寫過對非相關列(單獨或者單獨的索引列)進行預估時候的演算法,參考這裡。 今天來寫一下統計信息對於複合索引在預估時候的計算方法和潛在問題。 本文原形來自於是個實際業務問題, ...
  • 問題來源: 今天群里有人問:tableoid欄位在每行都有,而且一個表裡面的值是重覆的,這樣不合理...... 因此做了一些分析: 1)創建了一個表 2)查看該表的所有欄位 包括隱藏的: 可以發現有6個隱藏的欄位,其中cmax xmax cmin xmin都跟事物有關,在PG事物處理相關文章中可以經 ...
  • 1、首先,Redis官方是支持Linux系統的,我這裡不多說,需要的可以參考:http://www.oschina.net/question/12_18065/ 2、Windows 64位下載地址:https://github.com/MSOpenTech/redis/releases 3、下載後的 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...