RocksDB項目起源於Facebook的一個實驗項目,該項目旨在開發一個與快速存儲器(尤爲是閃存)存儲數據性能至關的數據庫軟件,以應對高負載服務。
這是一個c++庫,可用於存儲鍵和值,能夠是任意大小的字節流。它支持原子讀和寫。
RocksDB具備高度靈活的配置功能,能夠經過配置使其運行在各類各樣的生產環境,包括純內存,Flash,硬盤或HDFS。它支持各類壓縮算法,並提供了便捷的生產環境維護和調試工具。
RocksDB借鑑了開源項目LevelDB的重要代碼和Apache HBase項目的重要思想。最初的代碼來源於開源項目leveldb 1.5分叉。它借鑑了了Facebook的代碼和思想。linux
RocksDB的主要設計目標是保證存取快速存儲器和高負載服務器更高效,保證充分利用Flash或RAM子系統提供的高速率讀寫,
支持高效的查找和範圍scan,支持高負載的隨機讀、高負載的更新操做或二者的結合。其架構應該支持高併發讀寫和容量大增時系統的一致性。c++
RocksDB內置了用於生產環境中部署和調試的工具和實用程序。大多數主要參數應該是可調整的,以即可以被不一樣的應用程序在不一樣的硬件中使用。。算法
這個軟件的新版本應該是向後兼容的,所以,當升級到新版本時現有的應用程序不須要改變。數據庫
RocksDB是一個嵌入式鍵值存儲器,其中鍵和值是任意的字節流。RocksDB中的全部數據是按序存放的。常見操做包括Get(key), Put(key), Delete(key) and Scan(key)。
RocksDB有三個基本結構:RocksDB memtable,sstfile和logfile。memtable是一個內存數據結構——新數據會插入到memtable和日誌文件(可選)。日誌文件是
順序寫入的,位於磁盤。當memtable寫滿後,數據會被刷新到磁盤上的sstfile文件,同時相應的日誌文件能夠安全地刪除。sstfile中的數據通過排序的,目的
是爲了加快鍵查找。緩存
鍵和值被視爲純字節流.沒有大小的限制。Get接口容許應用程序從數據庫中獲取一個鍵值。MultiGet接口容許應用程序從數據庫中檢索多個鍵值。MultiGet接口返回的key-value對都是相互匹配的。
全部數據庫中的數據都按順序存放。應用程序能夠指定一個key比較方法來定義key的排序順序。迭代器容許應用程序對數據庫進行RangeScan。迭代器能夠先定位一個指定的鍵,而後應用程序就能夠從這個定位點開始一個一個掃描key。迭代器還能夠用來對key作反向迭代。建立迭代器是會建立當前數據庫的一個快照視圖,所以,經過迭代器返回的全部鍵都來自同一個數據庫視圖。
Snapshot容許應用程序建立一個快照視圖。Get和迭代器能夠從一個指定的快照讀取數據。在某種意義上,Snapshot和迭代器都提供了某個時間點上數據庫的快照視圖,但二者的實現是不一樣的。短暫的掃描最好經過迭代器而耗時較長的掃描最好經過快照。迭代器記錄了數據庫當前視圖對應文件——直到迭代器被釋放才刪除這些刪除。
而快照並不能阻止文件刪除;相反,compaction流程知道當前的快照而且不會刪除任何現有快照中的key。
數據庫重啓後,快照將丟失。重載RocksDB(經過服務器重啓)會釋放全部先前的快照。安全
大多數LSM引擎沒法支持一個高效RangeScan,由於它須要查找每個數據文件。但大多數應用程序不會對key進行隨機掃描,而更多的是掃描給定前綴的key。
RocksDB利用了這種優點。應用程序能夠經過prefix_extractor指定一個key的前綴。RocksDB用此來保存每一個key前綴的bloom,指定了前綴(經過ReadOptions)的迭代器將使用bloom二進制位來避免查找不包含指定key前綴的文件。服務器
Put操做向數據庫插入單個key-value。若是鍵已經存在,舊值將被覆蓋。Writer操做容許將多個keys-values原子地插入到數據庫中。數據庫保證同一個Writer操做中的全部keys-values要麼所有出入,要麼都不插入。若是其中任何一個鍵已經存在於數據庫中,舊值將被覆蓋。數據結構
Put操做數據會存儲在內存中的緩衝區稱爲memtable,也會選擇性地插入到事務日誌。每個Put操做都有一組標誌(經過WriteOptions設置),這些標誌指定Put操做數據是否應該插入到事務日誌。WriteOptions也能夠指定在put操做提交前一個同步調用是否寫入事務日誌。
在內部,RocksDB使用batch-commit機制批量寫入事務日誌,這樣它可使用一個同步調用提交多個事務。多線程
RocksDB使用校驗和檢測數據是否正確。每一個塊(一般是4k到128k大小)都有本身的校驗和。一塊數據一旦寫入將不會修改。
RocksDB經過硬件支持動態獲取校驗和的計算結果,以免須要是本身計算校驗和。架構
Compactions能夠刪除同一key的多個副本,副本是應用程序覆蓋現有key是產生的。能夠刪除key。經過配置可讓Compaction也多線程方式運行。
LSM的寫數據的總體吞吐量直接取決於Compaction的速度,特別是當數據存儲在SSD或RAM這種存儲器中。RocksDB能夠處理多個線程併發的omopaction請求。
多線程Compaction場景下寫數據的速率比單線程場景下的速率快10倍。
整個數據庫存儲在一組sstfiles。memtable寫滿時,它的內容會被寫入Level-0層的一個文件中,在此過程當中,重複和被覆蓋的key會被刪除。
一些文件被按期壓縮合並造成更大的文件——這就是所謂的compaction。
RocksDB支持兩種不一樣形式的compaction。廣泛的作法是將全部文件按時間順序保存在L0。compaction選擇幾個彼此相鄰的文件並將它們合併成一個新文件L0。全部文件能夠有重疊的key。
分層形式的compaction將數據存儲在數據庫中的多個層中。最新的數據存儲在L0和最舊的數據存儲在Lmax。L0層中的文件能夠有重疊的key,但其餘層中文件的key不能重疊。一次compaction過程就是選擇Ln層的一個文件及它在Ln+1層的全部重疊文件進行壓縮合並造成Ln+1層的新文件。相比層形式的compaction方法,
廣泛的compaction方法寫數據性能較低,但空間利用率較高。
MANIFEST文件記錄了數據庫的狀態。compaction在添加新文件和從數據庫刪除現有的文件後,會將這些操做記錄到MANIFEST文件。事務日誌是被批量提交到MANIFEST文件中的,目的是爲了減小對MANIFEST文件的重複同步訪問。
一些應用程序可能須要在Compaction過程當中處理某些key。例如,一個支持TTL的數據庫可能刪除過時的key,這能夠經過定義一個Compaction過濾器完成。
若是應用程序想要不斷刪除舊數據,可使用Compaction過濾掉丟棄過時的記錄。RocksDB Compaction過濾器能夠容許應用程序去修改對應key的value或做爲Compaction過程的一部分直接丟棄key。
數據庫能夠在只讀的模式下打開。只讀模式下應用程序不能修改任何數據。這能夠保證更高的讀取性能,由於避免了代碼執行路徑的切換和鎖的使用。
RocksDB的詳細日誌被寫入到名爲LOG*的文件中。這些日誌用於調試和分析運行中的系統。能夠按配置的指定週期記錄日誌。
RocksDB支持snappy,zlib,bzip2 lz4和lz4_hc壓縮算法。對不一樣層的數據能夠配置不一樣的壓縮算法。通常來講,90%的數據保存在Lmax層。
一個典型的安裝多是L0-L2層不配置壓縮算法,中間層用snappy壓縮算法,而Lmax層採用zlib壓縮。
RocksDB將事務日誌保存在logfile文件中以防止系統崩潰。系統啓動時會從新處理日誌文件。logfile和_sstfile_s能夠存放在不一樣目錄下,好比下面的場景,
當你但願將全部數據文件存儲在非持久但快速的存儲設備中,同時把事務日誌保存在存取速度慢但持久的存儲設備中。
RocksDB支持全量備份和增量備份。RocksDB是一個LSM數據庫引擎,所以一旦被建立,數據文件從不會被覆蓋,這使得獲取某個時間點數據庫快照很容易。DisableFileDeletions接口能夠禁止RocksDB刪除數據文件。Comopaction進行中,數據庫中的廢棄數據不會被刪除。備份接口GetLiveFiles / GetSortedWalFiles能夠提取數據庫中現有文件並將數據複製到備份位置。
備份完成後,EnableFileDeletions接口可使能數據文件刪除功能;數據庫如今就能夠回收不須要的全部文件。
增量備份和複製須要可以識別數據庫的最近修改。GetUpdatesSince接口容許應用程序tail(理解同linux tail命令) RocksDB事務日誌。它能夠接二連三地獲取RocksDB事務日誌並將它們發送帶遠程備份端或遠程複製端。
複製系統一般向Put操做增長元數據,這些元數據能夠用來檢測管道複製中的數據循環,也能夠用於給事務打時間戳和按順序排序事務。
這些元數據只存儲在事務日誌,而不存儲在數據文件中。PutLogData接口用來添加元數據,GetUpdatesSince用於獲取元數據。
RocksDB事務日誌是在數據庫目錄中建立的。再也不須要的日誌文件會被移動到歸檔目錄。歸檔文件目錄存在的緣由是由於一個複製速度較慢的複製流可能須要從日誌文件中檢索過去的事務。
GetSortedWalFiles接口返回事務日誌文件的列表。
RocksDB一個常見的用法是應用程序將數據集劃分爲邏輯分區或分片。這種技術的有利於應用程序保持負載均衡和快速恢復故障。這意味着一個服務器進程必須可以同時操做多個RocksDB數據庫。
這是經過環境變量Env實現的。除此以外,一個線程池與Env相關聯。若是應用程序想要在多個數據庫實例間共享同一個線程池,那麼它應該使用相同的Env對象打開這些數據庫。
一樣,多個數據庫實例能夠共享同一緩存塊。
RocksDB使用LRU緩存塊讀取數據。緩存塊被劃分爲兩個單獨的緩存:第一個緩存數據未壓縮,第二個緩存數據壓縮。若是緩存塊配置了壓縮,那麼數據庫不會在操做系統緩衝區中緩存數據。
表緩存用於存放緩存打開的sstfiles文件描述符。應用程序能夠指定表緩存的最大大小。
LSM數據庫的性能極大地依賴於Compaction算法及其實現。RocksDB支持兩種Compaction壓縮算法:層次類型和廣泛類型的。開發人員能夠開發和測試其餘的Compaction算法。出於這個緣由,RocksDB提供了關閉內置Compaction算法的接口和應用開發者本身Compaction算法的接口。
若是設置了disable_auto_compaction選項,本地Compaction算法將被禁止使用。GetLiveFilesMetaData接口容許外部組件查看數據庫中的每一個數據文件並決定合併和Compaction哪些數據文件。
DeleteFile接口容許應用程序刪除過期的數據文件。
一些應用程序架構以非阻塞方式訪問數據庫的,也就是說數據檢索請求不須要從存儲器讀取數據。RocksDB在塊緩存中緩存了數據庫部分數據,若是應用程序從塊緩存中查找到須要的數據,就從塊緩存中讀取數據;若是在塊緩存中
沒有找到,RocksDB返回適當的錯誤代碼給應用程序。經過錯誤碼,應用程序知道數據檢索調用可能會阻塞存儲IO(也許在一個不一樣的線程上下文中),從而利用普通的Get/Next去獲取數據。。
內存表的默認實現是跳躍表skiplist。skiplist一個有序集合,這種結構有利於進行數據範圍掃描。有些應用程序不交錯寫數據或掃描數據,有些應用程序不作範圍掃面。
對於這些應用程序,有序集合沒法提供最佳性能。出於這個緣由,RocksDB提供可插入接口容許應用程序本身實現內存表。數據庫通常包含三種內存表:跳躍表內存表,向量內存表和prefix-hash內存表。
向量內存表適合批量加載數據。每次都是在向量的末尾插入一個新元素,每當要將內存表中數據寫入到磁盤時,向量中的元素經排序後寫入L0層的文件中。prefix-hash內存表適用於快速gets、puts和按key前綴掃描。
RocksDB支持配置任意數量的memtables。當內存表寫滿後,它將成爲一個不可變的內存表,這時會啓動後臺線程開始將內存表中的數據刷新到磁盤。與此同時,新的數據會被寫入新分配的內存表。若是新分配內存表寫滿到了容量極限,它也轉化成不可變內存表並被插入到輸出管道中。後臺線程繼續將全部管道的不可變內存表刷新到磁盤。這種管道寫數據方式增長了RocksDB寫數據的吞吐量。特別是當操做緩慢的存儲設備時,這種方式更高效。
當內存表被刷新到磁盤時,inline-compaction進程會刪除輸出流中的重複記錄。一樣,後來的刪除操做會隱藏先來的插入操做,此插入操做不會被寫入輸出文件。這個特性下降了磁盤上的數據大小同時增長了數據寫入量。當RocksDB用做生產者消費者隊列尤爲是當隊列中元素存活時間很是短時,這個特性很是重要。
有許多有趣的工具,用於支持生產環境上的數據庫。sst_dump用於轉儲全部keys-values到sst文件中。ldb的工具能夠put、get和scan數據庫的內容。ldb也能夠轉儲MANIFEST文件
的內容,也能夠用來改變數據庫中配置的層數。這能夠用來手動壓縮數據庫。
提供了不少測試數據庫特定特性的單元測試。make check命令運行全部單元測試。這些單元測試用於測試RocksDB的特定特性,
不用於大規模數據正確性的測試場景。db_stress用來測試大規模數據的正確性。
RocksDB性能是經過db_bench作基準測試的。db_bench是RocksDB源代碼的一部分,典型場景的性能測試結果能夠參考wiki。