RocksDB資料庫簡介及使用分享
目錄
1 介紹 2
1.1 檔案介紹: 2
2 架構 3
3 特性 4
3.1 Get,Interator(迭代器)和快照 4
3.2 字首迭代器 5
3.3 更新 5
3.4 持久化 5
3.5 ReadOnly 模式 6
3.6 資料庫除錯日誌 6
3.7 事務日誌 6
3.8 Memtable 管道 6
3.9 合併 Merge 操作 7
3.9.1 合併條件 7
4 工具 8
5 應用 9
5.1 初始化 9
5.2 使用 9
5.3 引數配置 10
5.4 檢視資料庫資料 10
- 介紹
RocksDB 專案最開始是在 Facebook 作為一個試驗專案開發的高效的資料庫軟體,可以實現在伺服器負載下快速儲存(特別是快閃記憶體儲存)的資料儲存的全部潛力。它是一個 C++ 庫,可以用於儲存 KV,包括任意大小的位元組流。它支援原子讀寫。提供Java
RocksDB 具有高度靈活的配置設定,可以調整為在各種生產環境(包括純記憶體,快閃記憶體,硬碟或 HDFS)上執行。它支援各種壓縮演算法,並且有生產和除錯環境的各種便利工具。 RocksDB 借用了來自開源 leveldb 專案的核心程式碼,以及來自 Apache HBase 的重要思想。初始程式碼是從開源 leveldb 1.5 fork 的。它還融入了 facebook 團隊在開發 RocksDB 之前的若干程式碼及想法。
-
- 檔案介紹:
圖 1
- *.log: 事務日誌用於儲存資料操作日誌,可用於資料恢復
- *.sst: 資料持久換檔案
- MANIFEST:
資料庫中的 MANIFEST 檔案記錄資料庫狀態。壓縮過程會新增新檔案並從資料庫中刪除舊檔案,並通過將它們記錄在 MANIFEST 檔案中使這些操作持久化。
- CURRENT:記錄當前正在使用的MANIFEST檔案
- LOCK:rocksdb自帶的檔案鎖,防止兩個程序來開啟資料庫。
- 架構
RocksDB 是一個嵌入式 kv 儲存,key 和 value 是任意位元組流。RocksDB 按順序組織所有資料,常用操作是 Get(key) ,Put(key) ,Delete(key) 和 Scan(key) 。
圖 2
- 特性
- Get,Interator(迭代器)和快照
Key 和 value 被視為純位元組流。對 key 或 value 的大小沒有限制。Get API 允許應用程式從資料庫中提取單個 key。MultiGet API 允許應用程式從資料庫中檢索一堆 key。通過 MultiGet 呼叫返回的所有 key-value 彼此一致。
資料庫中的所有資料按照排序順序進行邏輯排列。應用程式可以定義 key 的排序比較方法。Iterator API 允許應用程式對資料庫執行 RangeScan。Iterator 可以尋找指定的 key,然後應用程式可以從該點開始一次掃描一個 key。Iterator API 也可以用於對資料庫中的 key 進行反向迭代。建立 Iterator 時,將建立資料庫的一致時間點檢視。因此,通過 Iterator 返回的所有 key 都來自資料庫的一致檢視。
Snapshot API 允許應用程式建立資料庫的時間點檢視。Get 和 Iterator API 可用於從指定的快照讀取資料。在某種意義上,Snapshot 和 Iterator 都提供了資料庫的時間點檢視,但它們的實現是不同的。短期掃描最好通過迭代器完成,而長時間執行的掃描最好通過快照完成。迭代器對與資料庫的該時間點檢視相對應的所有底層檔案保持引用計數 - 這些檔案在 Iterator 被釋放之前不會被刪除。另一方面,快照不會防止檔案被刪除; 但在壓縮過程中,壓縮程式能夠判斷快照的存在,它不會刪除在任何現有快照中可見的 key。
快照不會在資料庫重新啟動後保持持久化,因此重新載入 RocksDB 庫(通過伺服器重新啟動)會釋放所有預先存在的快照。
-
- 字首迭代器
大多數 LSM 引擎不能支援高效的 RangeScan API,因為它需要檢視每個資料檔案。但大多數應用程式不需要對資料庫中的 key 範圍進行純隨機掃描; 而應用程式通常通過 key 字首進行掃描。RocksDB 使用這個方法來體現了它的優勢。應用程式可以配置 prefix_extractor 以指定 key 字首。RocksDB 使用它來儲存每個 key 字首的 blooms。指定字首(通過 ReadOptions)的迭代器將使用這些 bloom 位來避免查詢不包含具有指定的 key 字首的資料檔案。
-
- 更新
Put API 將單個 key-value 插入資料庫。如果 key 已經存在於資料庫中,則以前的值將被覆蓋。Write API 允許將多個 key-value 原子地插入到資料庫中。資料庫保證要麼單個 Write 呼叫中的所有 key-value 將被插入資料庫,要麼它們都不會插入資料庫。
-
- 持久化
RocksDB 有一個事務日誌。所有 Put 都儲存在稱為 memtable 的記憶體中緩衝區中,並可選擇插入到事務日誌中。每個 Put 都有一組通過 WriteOptions 設定的標誌,它們指定是否將 Put 插入到事務日誌中。WriteOptions 還可以指定在 Put 被提交之前,是否向事務日誌發出 sync 呼叫。在內部,RocksDB 使用批量提交機制將多個事務寫入到事務日誌中,以便它可以使用單個 sync 呼叫提交多個事務。
-
- ReadOnly 模式
資料庫可以以只讀模式開啟,其中資料庫保證應用程式不會修改資料庫中的任何內容。這導致高得多的讀取效能,因為被橫穿的程式碼路徑完全避免了鎖的開銷。
-
- 資料庫除錯日誌
RocksDB 將詳細日誌寫入名為 LOG* 的檔案。這些主要用於除錯和分析正在執行的系統。該日誌可以被配置為以指定的週期滾動。
-
- 事務日誌
RocksDB 將事務儲存到日誌檔案中以防止系統崩潰。在重新啟動時,它會重新處理日誌檔案中記錄的所有事務。日誌檔案可以配置為儲存在與 _sstfile_s 不同的目錄中,比如某些場景,你可能會將所有資料檔案儲存在非永續性快速儲存器中,同時,您可以通過將所有事務日誌放在較慢但持久的儲存上確保不會有資料丟失。
-
- Memtable 管道
RocksDB 支援為資料庫配置任意數量的 memtable。當 memtable 已滿時,它變成不可變的 memtable,後臺執行緒開始將其內容重新整理到儲存。同時,新的寫入繼續累積到新分配的 memtable。如果新分配的 memtable 被填充到其限制,它也被轉換為不可變的 memtable 並被插入到 flush 管道中。後臺執行緒繼續將所有流水線不可變的 memtables 重新整理到儲存。這種流水線提高了 RocksDB 的寫吞吐量,尤其是在慢速儲存裝置上執行時。
-
- 合併 Merge 操作
RocksDB 本地支援三種類型的記錄:Put 記錄,Delete 記錄和 Merge 記錄。當壓縮過程遇到 Merge 記錄時,它呼叫應用程式指定的稱為 Merge 的方法。合併可以將多個 Put 和 Merge 記錄合併成一個。這個強大的功能允許通常執行讀 - 修改 - 寫的應用程式完全避免讀。它允許應用程式將操作意圖記錄為合併記錄,RocksDB 壓縮過程將該意圖延遲應用於原始值。此功能在合併運算子中詳細描述。
-
-
- 合併條件
-
如果是Level-0層,會先算出當前有多少個沒有進行Compact 的檔案個數numfiles, 然後根據這個檔案的個數進行判斷
相關引數 |
值 |
說明 |
level0_file_num_compaction_trigger |
4 |
當有4個未進行Compact的檔案時,達到觸發Compact的條件 |
level0_slowdown_writes_trigger |
20 |
當有20個未進行Compact的檔案時,觸發RocksDB,減慢寫入速度 |
level0_stop_writes_trigger |
24 |
當有24個未進行Compact的檔案時,觸發RocksDB停止寫入檔案,此時會盡快的Compact Level-0層檔案 |
表格 1
Level-1 層 檔案總大小由 max_bytes_for_level_base 引數控制,而 Level-2 層的大小通過: Level_max_bytes[N] = Level_max_bytes[N-1] * max_bytes_for_level_multiplier^(N-1)*max_bytes_for_level_multiplier_additional[N-1] 計算得出
引數 |
值 |
說明 |
max_bytes_for_level_base |
10485760 |
用於指定Level-1 層總大小,超過這個值滿足觸發Compact條件 |
max_bytes_for_level_multiplier |
10 |
每一層最大Bytes 乘法因子 |
max_bytes_for_level_multiplier_addtl[2] |
1 |
Level-2 層總大小調整引數 |
max_bytes_for_level_multiplier_addtl[3] |
1 |
Level-3 層總大小調整引數 |
max_bytes_for_level_multiplier_addtl[4] |
1 |
Level-4 層總大小調整引數 |
max_bytes_for_level_multiplier_addtl[5] |
1 |
Level-5 層總大小調整引數 |
max_bytes_for_level_multiplier_addtl[6] |
1 |
Level-6 層總大小調整引數 |
表格 2
對於Level-0層檔案,RocksDB總是選擇所有的檔案進行Compact操作,因為Level-0層的檔案之間,可能會有key範圍的重疊。
對於Level-N (N>1)層的檔案,會先按照檔案大小排序(氣泡排序),選出最大的檔案,並計算這個檔案Key 的起止範圍,通過這個範圍查詢Level-N+1層檔案,把選出的Level-N 檔案和Level-N+1 檔案做為輸入,並且在Level-N+1新建一個或多個SST檔案作為輸出。
可以通過設定max_background_compactions 大於1 來使用並行Compact,不過這個並行Compact 不能作用到Level-0層。
- 工具
sst_dump 工具可以匯出 sst 檔案中的所有鍵值對。ldb 工具可以 put,get,scan 資料庫的內容。ldb 也可以dump MANIFEST 內容、更改資料庫的配置級別數或用於手動壓縮資料庫。也可以對資料庫進行修復(ldb repair –db=資料庫路徑)
- 應用
Rocksdb在oJmw中作為嵌入式資料庫使用,呼叫Java介面,需要引入rocksdbjni-版本號.jar包。
-
- 初始化
RocksDB.loadLibrary();//載入jni
RocksDB db = RocksDB.open(options, db_path_not_found)//開啟資料庫
-
- 使用
- 單條插入
db.put("hello".getBytes(), "world".getBytes());
- 批量插入
try (final WriteOptions writeOpt = new WriteOptions()) { for (int i = 10; i <= 19; ++i) { try (final WriteBatch batch = new WriteBatch()) { for (int j = 10; j <= 19; ++j) { batch.put(String.format("%dx%d", i, j).getBytes(), String.format("%d", i * j).getBytes()); } db.write(writeOpt, batch); } }
- 查詢
value = db.get("world".getBytes());
- 迭代器查詢
try (final RocksIterator iterator = db.newIterator()) { for (iterator.seekToLast(); iterator.isValid(); iterator.prev()) { values.add(iterator.value ()); }}
-
- 引數配置
介面 |
描述 |
T setCreateIfMissing(boolean flag); |
如果資料庫不存在則建立 |
T setCreateMissingColumnFamilies(boolean flag); |
如果表不存在則建立 |
T setErrorIfExists(boolean errorIfExists); |
如果為真則在資料庫open 時會丟擲異常 |
T setLogger(Logger logger); |
設定日誌,可以指定到自己的日誌系統 |
T setMaxOpenFiles(int maxOpenFiles); |
指定最大檔案開啟數量 |
T setMaxTotalWalSize(long maxTotalWalSize); |
設定事務日誌最大值 |
T setUseFsync(boolean useFsync); |
設定資料元資料同步下盤 |
setDbPaths(final Collection<DbPath> dbPaths); |
設定資料庫路徑, [{"/flash_path", 10GB}, {"/hard_drive", 2TB}] 越新的資料,越靠前 |
T setDbWriteBufferSize(long dbWriteBufferSize); |
設定資料庫快取 |
-
- 檢視資料庫資料
檢視資料庫資訊兩種方式,一種是通過rocksdb提供的ldb工具,一種是利用postman工具通過http請求,來檢視