bitcask存儲引擎

bitcask是一個使用Erlang寫的key-value存儲引擎。Bitcask的起源和一個分佈式key-value數據庫 Riak有很密切的關係。在Riak的集羣裏,每一個node使用插件式的存儲引擎,幾乎全部key-value類型的存儲引擎均可以做爲單個node節點的存儲引擎。關於Riak的詳細介紹,有機會後面再講。node

設計理念

在MySQL和postgresql中,除了保存在disk上的真正的數據庫數據外,還有額外的日誌文件,MySQL中是binlog,pg中是wal 文件。這些日誌文件在備份、還原、創建從庫的時候很是有用。redis

在bitcask中的設計中,相對就比較簡單,日誌文件自己就是數據庫。備份起來也至關簡單,只要把數據目錄的全部文件拷貝一份,在另外一個服務器上重建索引就好了。簡要提及來有下面幾點:sql

  • 使用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文件。被取代的文件被稱爲老文件,以後永遠都是不可變的,不會再有任何進程往裏面寫入數據。緩存

Active文件寫操做全是append,意味着順序寫入操做不須要disk seeking。每個記錄的格式以下圖:bash

  • crc:一個檢驗值,在這裏能夠忽略
  • tstamp:時間戳
  • ksz: key的大小
  • value_sz : value的大小。

須要注意的是,刪除操做,不過是插入一條value爲某個特殊值的記錄。服務器

這些記錄組合起來,就構成了一個bitcask文件:微信

當append操做完成時,內存裏的一個叫作keydir的數據結構就會被更新。一個keydir就是一個簡單的哈希表,key就是插入數據的key,value指向了插入數據value在文件系統中的具體位置。數據結構

  • file_id : 前面說過,bitcask有active文件,也有老數據文件,這個file_id就是指向了一個其中的文件。
  • value_pos : value在該文件的起始位置。
  • value_sz : value大小

寫入發生時,原來的老數據依然仍是保存在磁盤上,可是新的讀取這個key的請求都會使用keydir上最新的數據。後面會說到,有一個合併進程,最終會刪除不會再使用到的老數據。app

讀取操做是很簡單的,根本不須要操做一次的disk seek。從內存中的keydir查詢key,從這裏知道了value所在的file_id,位置,大小,而後只要調用系統的讀取接口就好了。通常操做系統都還會有本身獨立的disk讀緩存,因此這個操做實際上能夠更快。

如今來講說前面提到的合併操做。其實很簡單,**合併進程遍歷全部的老文件,產生一個只包含當前最新版本數據的文件。**這部分完成的時候,還會產生一個hint file,這個文件本質上和data 文件同樣,只不過他們保存的是value所在文件上的位置,而不是value自己。這個文件能夠加速從目錄文件重建keydir的過程。

當bitcask被一個Erlang進程打開時,它會檢查同一個VM裏,是否是有另外一個Erlang進程在使用這個bitcask,若是是的話,就會和那個進程共享同一個keydir。若是沒有的話,它就會掃描全部的數據文件,構建一個新的keydir,對於那些有hint file的文件,這個構建過程會有顯著提升。

總結

我接觸的第一個key-value存儲引擎是redis。redis的全部數據都是裝在內存的(每隔一段時間會把數據持久化保存到磁盤),這意味着redis的讀寫速度都很是快。可是這有一個限制,那就是單機redis存儲的數據不能大於內存自己。而bitcask的最大限制是內存必須裝得下全部的key,由於bitcask的value是存在磁盤上的。因此相比redis,bitcask的存在乎義不是和redis比速度,而是當你的數據用redis存不下的時候,能夠考慮稍微損失一丟丟速度,試試bitcask。

關注個人微信公衆號

相關文章
相關標籤/搜索