軟硬件結合,分佈式數據庫 ZNBase 存儲架構優化實踐

ZNBase 是開放原子開源基金會旗下的首個分佈式數據庫項目,由浪潮大數據團隊開源並捐贈。本文將介紹 ZNBase 的存儲架構,以及 ZNBase 技術團隊在其 KV 存儲引擎基礎上所做的優化實踐。

ZNBase 整體存儲架構

云溪數據庫 ZNBase 採用分層架構,分爲計算層與存儲層,其總體架構如下圖所示:

在 OLTP 場景下,當開發人員向集羣發送 SQL 語句時,數據最終會以鍵值對 KV 的形式對存儲層進行讀寫。每個 ZNBase 節點啓動時,至少會包含一個存儲節點。存儲層默認採用 KV 存儲引擎 RocksDB 負責存儲數據。每個存儲實例都可能包含多個 Range,Range 是最底層的 KV 數據單元。Range 使用 Raft 一致性協議在集羣間進行復制。

爲了支持 HTAP 場景,ZNBase 的行存數據會通過 Raft Learner 同步到列存引擎,存儲層還擴展了矢量接口,通過列式存儲、計算下推、多節點並行計算滿足業務應用的 AP 需求。另外存儲層還擴展了時序接口,可以進行時序數據管理。

接下來將着重介紹 ZNBase 存儲層架構中的 KV 存儲集羣。

RocksDB 引擎

ZNBase 的存儲層默認採用 RocksDB 來存儲數據。RocksDB 是由 Facebook 開源的高性能 KV 存儲引擎,讀寫數據可以是任意字節流,其官方架構如圖所示,是一種 LSM-Tree 的實現:

 RocksDB 寫入流程如下:

1、以 batch 形式先順序寫入 WAL 文件用於故障恢復

2、再寫入內存中的 Memtable,Memtable 默認以 SkipList 形式存儲

3、Memtable 寫滿一定大小,默認 64MB,會轉爲不可變的 Immutable。

4、異步線程會將 Immutable 刷到磁盤 L0 層,變爲 SST 文件。

5、磁盤中使用多層來管理 SST 文件,通過合併過程將上層的 SST 文件落到下層,在合併過程中會進行 GC 清理。

由此可見,RokcsDB 最新的數據是在內存或者上層的 SST 文件裏,所以讀取時優先讀取 Memtable 和 Immutable,再依此讀取各層文件。剛寫入的熱數據,可以更快被讀到。另外 RocksDB 還提供了 Block Cache 進行讀緩存。 

RocksDB 本身是一個 LSM-Tree 架構的高速 KV 存儲引擎,讀寫都會盡量使用內存。RocksDB 提供原子的批量寫入、快照等功能,方便上層實現事務控制。基於 RocksDB 也支持高度安全的 AES 算法對存儲在磁盤上的數據加密,這樣即使磁盤被竊取,磁盤裏的數據也無法被訪問。

由於 RocksDB 採用 LSM-Tree 架構,同樣也存在一定的問題。比如在大數據量下有比較高的讀放大、寫放大、空間放大,性能衰減也比較厲害。爲了提高 ZNBase 在海量數據下的性能表現,ZNBase 團隊結合浪潮的硬件優勢,開發了使用 SPDK 驅動在專用硬件 ZNS SSD 上進行軟硬件融合的存儲引擎;另外爲了更有效的利用內存,獲得更快的讀寫速度,在大內存場景下也開發了準內存引擎的實現。

SPDK + ZNS SSD

固態硬盤(SSD)正在迅速擴展它在數據中心中的份額,相較於傳統存儲介質,新的閃存介質具有性能,耗電,機架空間等等方面的優勢。

而浪潮自研的 ZNS SSD,在容量、壽命、成本、易用性、性能等方面實現飛躍式提升。ZNS SSD 即分區命名空間固態硬盤,可以將 FTL(Flash Translation Layer) 暴露給用戶以充分發揮 SSD 性能。ZNS 技術針對雲場景應用,主適用於大容量空間存儲的數據,例如高清視頻、圖像等。ZNBase 與 ZNS SSD 集成,通過智能數據部署可以實現更好的空間運⽤,獲得降低一倍以上的寫放大;文件可根據生命週期進行數據分區隔離,實現最低化垃圾回收;SST 文件可根據 LSM 分層進行清晰化冷熱數據分離,提升訪問效率;最小化的寫放大可提升讀取性能,減少合併成本和垃圾回收開銷;理論上,ZNS SSD 可帶來 15% 的性能提升和 10% 的成本收益。

 

由於 SSD 本身的物理特性,其數據的訪問相較於傳統介質來說已經非常快了,而性能的瓶頸就是出在計算機與設備連接的接口和協議上面。舉個直觀的例子,我們從北京乘飛機到美國,按照現在的飛行速度,在天上需要 13 個小時。這種情況下,安檢的時間,過海關的時間,候機的時間,加起來 3 個小時,相對於總共的 13+3=16 個小時也不算長。設想如果現在飛機的飛行速度提高了 100 倍,飛行時間從 13 小時縮短至 10 分鐘,這時 3 個小時的地面手續流程就顯得很沒有效率了。換言之,在存儲硬件性能高速發展的今天,存儲軟件協議棧的性能和效率在存儲整體系統中的地位越來越重要。

SPDK (Storage performance development kit) 由 Intel 發起,提供了一組用於編寫高性能、可伸縮、用戶態存儲應用程序的工具和庫。SPDK 的基礎是用戶態、輪詢、異步、無鎖 NVMe 驅動,提供了從用戶空間應用程序到 NVMe 設備的零拷貝、高度並行的訪問。

NVMe 的全稱是 Non-Volatile Memory Express,如果翻譯過來就是非易失性內存主機控制器接口規範,是一種新型的存儲設備接口規範,用於定義硬件接口和傳輸協議,擁有比傳統 SATA SSD 的 AHCI 標準更高的讀寫性能。我們可以把 NVMe 看做一個硬件進步推動軟件革新需求的例子,隨着後續更快的存儲介質投入市場,這種推動力將更爲急迫。 

SPDK 項目也是一種硬件進步推動軟件革新的產物,其目標就是能夠把硬件平臺的計算、網絡、存儲的最新性能進展充分發揮出來。那麼 SPDK 是如何工作的?它超高的性能實際上來自於兩項核心技術:第一個是用戶態運行,第二個是輪詢模式驅動。

首先,將設備驅動代碼運行在用戶態,是和運行在 “內核態” 相對而言的。把設備驅動移出內核空間避免了內核上下文切換與中斷處理,從而節省了大量的 CPU 負擔,允許更多的指令週期用在實際處理數據存儲的工作上。無論存儲算法複雜還是簡單,也無論進行去重(deduplication),加密(encryption),壓縮(compression),還是簡單的塊讀寫,更少的指令週期浪費意味着更好的整體性能。

其次,傳統的中斷式 IO 處理模式,採用的是被動的派發式工作,有 IO 需要處理時就請求一箇中斷,CPU 收到中斷後才進行資源調度來處理 IO。舉一個出租車的例子做類比,傳統磁盤設備的 IO 任務就像出租車乘客,CPU 資源被調度用來處理 IO 中斷就像出租車。當磁盤速度遠慢於 CPU 時,CPU 中斷處理資源充沛,中斷機制是能對這些 IO 任務應對自如的。這就好比是非高峯時段,出租車供大於求,路上總是有空車在掃馬路,乘客隨時都能叫到車。然而,在高峯時段,比如週五傍晚在鬧市區叫車 (不用滴滴或者專車),常常是看到一輛車溜溜的近前來,而後卻發現後座已經有乘客了。需要等待多久,往往是不可預知的。相信你一定見過在路邊滯留,招手攔車的人羣。同樣,當硬盤速度上千倍的提高後,將隨之產生大量 IO 中斷,Linux 內核的中斷驅動式 IO 處理(Interrupt Driven IO Process) 就顯得效率不高了。

而在輪詢模式驅動下,數據包和塊得到迅速派發,等待時間最小化,從而達到低延時、更一致的延時 (抖動變少)、更好的吞吐量的效果。

當然,輪詢模式驅動並不是在所有的情況下都是最高效的 IO 處理方式。對於低速的 SATA HDD,PMD 的處理機制不但給 IO 性能帶來的提升不明顯,反而浪費了 CPU 資源。

準內存引擎

除了採用 SPDK+ZNSSD 軟硬件結合的存儲引擎以外,爲了更有效的利用內存,獲得更快的讀寫速度,ZNBase 在大內存場景下還開發了準內存引擎的實現。

準內存引擎開發的背景源自 RocksDB 的一些侷限性:

1.WAL 的單線程寫模式,不能充分發揮高速設備的性能優勢; 

  1. 讀操作時,有可能需要查找 level 0 層的多個文件及其他層的文件,這也造成了很大的讀放大。尤其是當純隨機寫入後,讀幾乎是要查詢 level0 層的所有文件,導致了讀操作的低效。

  2. 針對第 2 點問題,RocksDB 中依據 level 0 層文件的個數來做前臺寫流控及後臺合併觸發,以此來平衡讀寫的性能。這又導致了性能抖動及不能發揮高速介質性能的問題。 

  3. 合併流程難以控制,容易造成性能抖動及寫放大。

近年來,隨着動態隨機存儲器(DRAM)容量的上升和單位價格的下降,使大量數據在內存中的存儲和處理成爲可能。相對於磁盤,內存的數據讀寫速度要高出幾個數量級,將數據保存在內存中相比從磁盤上訪問能夠極大地提高應用的性能。

針對這一理念,準內存引擎設計原則如下:

  1. 數據儘量存放在內存中,充分利用內存的讀寫性能。

  2. 基於索引與數據分離存儲的思想,索引常駐內存。數據可以根據內存容量,將部分存儲到持久化存儲設備中。

  3. 提升 cpu cache 命中率,通過數據塊的重構(拆解、擴容、縮容)將 Key 相鄰的 KV 數據在內存空間中也相鄰,以提升 key 值遍歷的速度。

  4. 使用異步落盤機制,保證平滑的 IO 速率,消除 IO 瓶頸。

基於 ART 索引的檢索機制,保證數據訪問速度。ART 算法使用基於樂觀鎖的的同步機制,讀操作不阻塞,寫操作使用版本信息的 CAS 原子操作以及重試機制。

由於已通過 Raft Log 實現數據的故障恢復,可以去除 WAL 寫入過程。

 

準內存引擎總體處理流程如下:

  1. 新插入的數據存放在 內存臨時區中的 Memtable 以及 Immutable 中。

  2. 異步線程 Mem-Flush 將 Immutable 中的數據轉存到內存存儲區。

  3. 內存存儲區會盡可能佔用更多的內存空間,用於存放數據。使用 ART 算法索引這些數據。

  4. 內存存儲區內存空間即將不足時,啓用 L1-Flush 後臺線程清理內存存儲區中的數據。

  5. L1-Flush 後臺線程,將該內存存儲區中所有的 KV 數據以及範圍刪除數據進行落盤。由於數據量大且數據有序,因此,直接落盤到 L1 層。落盤前需要保證 L1 層無文件。落盤完成後,創建 L1 層文件向下合併的任務。

準內存引擎採用 ART 算法作爲主索引的實現,可以進行快速的範圍查找,輔助使用 Hash 索引方便進行 Get 查詢。之所以使用 ART 算法,是因爲其在讀寫方面性能均優於 B + 樹、紅黑樹、二叉樹,可比肩哈希表,而 ART 算法比哈希表的優勢是 ART 算法可按順序遍歷所有數據。

參見論文:The Adaptive Radix Tree: ARTful Indexing for Main-Memory Databases

總結

本文爲大家介紹了 ZNBase 基於 RocksDB 的存儲引擎架構,以及 ZNBase 團隊針對 RocksDB 的侷限性,通過開發軟硬件結合的 SPDK+ZNS SSD 存儲引擎、大內存場景下的準內存引擎,大大提高了存儲引擎的讀寫性能。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/hgTwgfcRzMutS7yBTDpA2w