RocksDB簡介

RocksDB是FaceBook起初作爲實驗性質開發的,旨在充分實現快存上存儲數據的服務能力。由Facebook的Dhruba Borthakur於2012年4月創建的LevelDB的分支,最初的目標是提高服務工作負載的性能,最大限度的發揮閃存和RAM的高度率讀寫性能。

Key和value是任意大小的字節流支持原子的讀和寫。除此外,RocksDB深度支持各種配置,可以在不同的生產環境(純內存、Flash、hard disks or HDFS)中調優,RocksDB針對多核CPU、高效快速存儲(SSD)、I/O bound workload做了優化,支持不同的數據壓縮算法、和生產環境debug的完善工具。

RocksDB的主要設計點是在快存和高服務壓力下性能表現優越,所以該db需要充分挖掘Flash和RAM的讀寫速率。 例如360開源的Pika, 是由360 DBA 和基礎架構組聯合開發的類 Redis 存儲系統,完全支持 Redis 協議,用戶不需要修改任何代碼,就可以將服務遷移至 Pika,Pika底層存儲引擎用的就是Rocksdb。

RocksDB需要支持高效的point lookup和range scan操作,需要支持配置各種參數在高壓力的隨機讀、隨機寫或者二者流量都很大時性能調優,基於LSM樹數據結構( log-structured merge-tree),由C++編寫並官方提供C、C++、Java(官方提供的稱爲RocksJava)三種語言的API,社區提供了不少第三方API,如python、go等。

儘管RocksDB不是一個SQL 數據庫,但是有facebook有修改了代碼的MyRocks存儲引擎作爲MySQL的存儲引擎。和其他的NoSQL類似,RocksDB不提供關係型數據模型、不支持SQL查詢,沒有直接對輔助索引(secondary indexes)支持。

文件介紹:
*.log: 事務日誌用於保存數據操作日誌,可用於數據恢復
*.sst: 數據持久換文件
MANIFEST:數據庫中的 MANIFEST 文件記錄數據庫狀態。壓縮過程會添加新文件並從數據庫中刪除舊文件,並通過將它們記錄在 MANIFEST 文件中使這些操作持久化。
CURRENT:記錄當前正在使用的MANIFEST文件
LOCK:rocksdb自帶的文件鎖,防止兩個進程來打開數據庫。

Rocksdb中引入了ColumnFamily(列族, CF)的概念,所謂列族也就是一系列kv組成的數據集。所有的讀寫操作都需要先指定列族。寫操作先寫WAL,再寫memtable,memtable達到一定閾值後切換爲Immutable Memtable,只能讀不能寫。後臺Flush線程負責按照時間順序將Immu Memtable刷盤,生成level0層的有序文件(SST)。後臺合併線程負責將上層的SST合併生成下層的SST。Manifest負責記錄系統某個時刻SST文件的視圖,Current文件記錄當前最新的Manifest文件名。 每個ColumnFamily有自己的Memtable, SST文件,所有ColumnFamily共享WAL、Current、Manifest文件,用戶可以基於RocksDB構建自己的column families。很多應用程序把RocksDB當做庫(libary),儘管他提供server或者CLI接口。

Memtable
可插拔 memtable,RocksDB 的 memtable 的默認實現是一個 skiplist。skiplist 是一個有序集,當工作負載使用 range-scans 並且交織寫入時,這是一個必要的結構。然而,一些應用程序不交織寫入和掃描,而一些應用程序根本不執行範圍掃描。對於這些應用程序,排序集可能無法提供最佳性能。因此,RocksDB 支持可插拔的 API,允許應用程序提供自己的 memtable 實現。開發庫提供了三個 memtable:skiplist memtable,vector memtable 和前綴散列(prefix-hash) memtable。Vector memtable 適用於將數據批量加載到數據庫中。每個寫入在向量的末尾插入一個新元素; 當它是刷新 memtable 到存儲的時候,向量中的元素被排序並寫出到 L0 中的文件。前綴散列 memtable 允許對 gets,puts 和 scans-within-a-key-prefix 進行有效的處理。

SSTFile(SSTTable)
RocksDB在磁盤上的file結構sstfile由block作爲基本單位組成,一個sstfile結構由多個data block和meta block組成, 其中data block就是數據實體block,meta block爲元數據block, 其中data block就是數據實體block,meta block爲元數據block。 sstfile組成的block有可能被壓縮(compression),不同level也可能使用不同的compression方式。 sstfile如果要遍歷block,會逆序遍歷,從footer開始。
RocksDB是一個嵌入式的K-V(任意字節流)存儲。所有的數據在引擎中是有序存儲,可以支持Get(key)、Put(Key)、Delete(Key)和NewIterator()。RocksDB的基本組成是memtable、sstfile和logfile。memtable是一種內存數據結構,寫請求會先將數據寫到memtable中,然後可選地寫入事務日誌logfile。logfile是一個順序寫的文件。當內存表溢出的時候,數據會flush到sstfile中,然後這個memtable對應的logfile也會安全地被刪除。sstfile中的數據也是有序存儲以方便查找。

RocksDB支持將一個數據庫實例分片爲多個列族。類似HBase,每個DB新建時默認帶一個名爲"default"的列族,如果一個操作沒有攜帶列族信息,則默認使用這個列族。如果WAL開啓,當實例crash再恢復時,RocksDB可以保證用戶一個一致性的視圖。通過WriteBatch API,可以實現跨列族操作的原子性。

寫流程:
rocksdb寫入時,直接以append方式寫到log文件以及memtable,隨即返回,因此非常快速。
memtable/immute memtable觸發閾值後, flush 到Level0 SST,Level0 SST觸發閾值後,經合併操作(compaction)生成level 1 SST, level1 SST 合併操作生成level 2 SST,以此類推,生成level n SST.

讀流程:
按照 memtable --> Level 0 SST–> Level 1 SST --> … -> Level n SST的順序讀取數據。這和記錄的新舊順序是一的。因此只要在當前級別找到記錄,就可以返回。

因爲RocksDB 改自LevelDB,現在來對比下他們優缺點:

LevelDB 特點:
1) LevelDB是一個持久化存儲的KV系統,和Redis這種內存型的KV系統不同,LevelDB不會像Redis一樣狂喫內存,而是將大部分數據存儲到磁盤上。
2) LevleDB在存儲數據時,是根據記錄的key值有序存儲的,就是說相鄰的key值在存儲文件中是依次順序存儲的,而應用可以自定義key大小比較函數。
3) LevelDB支持數據快照(snapshot)功能,使得讀取操作不受寫操作影響,可以在讀操作過程中始終看到一致的數據。
4) LevelDB還支持數據壓縮等操作,這對於減小存儲空間以及增快IO效率都有直接的幫助。

RocksDB 對LevelDB的優化:

  1. 增加了column family,這樣有利於多個不相關的數據集存儲在同一個db中,因爲不同column family的數據是存儲在不同的sst和memtable中,所以一定程度上起到了隔離的作用。
  2. 採用了多線程同時進行compaction的方法,優化了compact的速度。
  3. 增加了merge operator,優化了modify的效率。
  4. 將flush和compaction分開不同的線程池,能有效的加快flush,防止stall。
  5. 增加了對write ahead log(WAL)的特殊管理機制,這樣就能方便管理WAL文件,因爲WAL是binlog文件。

RocksDB的典型場景(低延時訪問):

1)需要存儲用戶的查閱歷史記錄和網站用戶的應用
2)需要快速訪問數據的垃圾檢測應用
3)需要實時scan數據集的圖搜索query
4)需要實時請求Hadoop的應用
5)支持大量寫和刪除操作的消息隊列

參考資料:
https://cloud.tencent.com/developer/news/359358
https://blog.csdn.net/gunri_tianjin/article/details/83444651

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章