bitcask儲存引擎

liaochangjiang發表於2019-02-07

bitcask是一個使用Erlang寫的key-value儲存引擎。Bitcask的起源和一個分散式key-value資料庫 Riak有很密切的關係。在Riak的叢集裡,每個node使用外掛式的儲存引擎,幾乎所有key-value型別的儲存引擎都可以作為單個node節點的儲存引擎。關於Riak的詳細介紹,有機會後面再講。

設計理念

在MySQL和postgresql中,除了儲存在disk上的真正的資料庫資料外,還有額外的日誌檔案,MySQL中是binlog,pg中是wal 檔案。這些日誌檔案在備份、還原、建立從庫的時候非常有用。

在bitcask中的設計中,相對就比較簡單,日誌檔案本身就是資料庫。備份起來也相當簡單,只要把資料目錄的所有檔案拷貝一份,在另一個伺服器上重建索引就行了。簡要說起來有下面幾點:

  • 使用RAM(記憶體)儲存一個雜湊表,雜湊表上的value指向檔案系統上的檔案,以及該key對應的值在該檔案中的具體位置。
  • 無論是插入、更新還是刪除,都是append一條記錄到一個特殊格式的檔案。
  • 每次append記錄之後,更新記憶體裡的那個雜湊表
  • 每個檔案有最大空間限制,這個檔案寫滿之後,寫下一個,寫過的之後永遠不會再改變。
  • 有一個merge程式,用來合併老資料,防止檔案大小無限積累。
  • 讀快取:其他的資料庫系統,比如MySQL,PostgreSql有相當複雜的設計,bitcask沒有相關設計,而是依賴於作業系統核心的檔案系統快取。

優勢

  • 寫操作:由於所有的操作都是append,所以速度是極快的,因為不會涉及到seek(不知道如何用中文表述,手動捂臉)。
  • 讀操作:O(1)複雜度的disk查詢,因為記憶體裡的雜湊表已經明確表名這個值所在的位置了。
  • 設計簡單,很容易理解,這也是一個優勢

詳細解釋

以下內容幾乎全部來自bitcask的paper,很易讀,地址為:basho.com/wp-content/…

一個bitcask例項就是一個目錄,在設計上強制在任意時刻,只有一個作業系統程式可以開啟bitcask進行寫操作,這個程式就可以看作是bitcask服務。在任意時刻,這個目錄中只有一個檔案是active的,只有這個檔案是可以被寫入的。當這個active的檔案大小達到一個臨界值的時候,bitcask就會建立一個新的檔案,用來取代當前的active檔案。被取代的檔案被稱為老檔案,之後永遠都是不可變的,不會再有任何程式往裡面寫入資料。

bitcask儲存引擎

Active檔案寫操作全是append,意味著順序寫入操作不需要disk seeking。每一個記錄的格式如下圖:

bitcask儲存引擎
  • crc:一個檢驗值,在這裡可以忽略
  • tstamp:時間戳
  • ksz: key的大小
  • value_sz : value的大小。

需要注意的是,刪除操作,不過是插入一條value為某個特殊值的記錄。

這些記錄組合起來,就構成了一個bitcask檔案:

bitcask儲存引擎

當append操作完成時,記憶體裡的一個叫做keydir的資料結構就會被更新。一個keydir就是一個簡單的雜湊表,key就是插入資料的key,value指向了插入資料value在檔案系統中的具體位置。

bitcask儲存引擎
  • file_id : 前面說過,bitcask有active檔案,也有老資料檔案,這個file_id就是指向了一個其中的檔案。
  • value_pos : value在該檔案的起始位置。
  • value_sz : value大小

寫入發生時,原來的老資料依然還是儲存在磁碟上,但是新的讀取這個key的請求都會使用keydir上最新的資料。後面會說到,有一個合併程式,最終會刪除不會再使用到的老資料。

讀取操作是很簡單的,根本不需要操作一次的disk seek。從記憶體中的keydir查詢key,從這裡知道了value所在的file_id,位置,大小,然後只要呼叫系統的讀取介面就行了。一般作業系統都還會有自己獨立的disk讀快取,所以這個操作實際上可以更快。

bitcask儲存引擎

現在來說說前面提到的合併操作。其實很簡單,**合併程式遍歷所有的老檔案,產生一個只包含當前最新版本資料的檔案。**這部分完成的時候,還會產生一個hint file,這個檔案本質上和data 檔案一樣,只不過他們儲存的是value所在檔案上的位置,而不是value本身。這個檔案可以加速從目錄檔案重建keydir的過程。

bitcask儲存引擎

當bitcask被一個Erlang程式開啟時,它會檢查同一個VM裡,是不是有另一個Erlang程式在使用這個bitcask,如果是的話,就會和那個程式共享同一個keydir。如果沒有的話,它就會掃描所有的資料檔案,構建一個新的keydir,對於那些有hint file的檔案,這個構建過程會有顯著提高。

總結

我接觸的第一個key-value儲存引擎是redis。redis的所有資料都是裝在記憶體的(每隔一段時間會把資料持久化儲存到磁碟),這意味著redis的讀寫速度都非常快。但是這有一個限制,那就是單機redis儲存的資料不能大於記憶體本身。而bitcask的最大限制是記憶體必須裝得下所有的key,因為bitcask的value是存在磁碟上的。所以相比redis,bitcask的存在意義不是和redis比速度,而是當你的資料用redis存不下的時候,可以考慮稍微損失一丟丟速度,試試bitcask。

關注我的微信公眾號

bitcask儲存引擎

相關文章