作者:徐奇
TiKV 推出了名為“partitioned-raft-kv”的新實驗性功能,該功能採用一種新的架構,不僅可以顯著提高 TiDB 的可擴充套件性,還能提升 TiDB 的寫吞吐量和效能穩定性。
在上一篇文章中,我們介紹了 Partitioned Raft KV 這一新實驗特性帶來的效能和可伸縮性大幅提升。本文我們將為大家介紹為什麼它可以有如此大的優勢。
架構
以下是 TiKV 的架構。
圖 1 TiKV 架構 —— 邏輯資料分割槽
一個 TiKV 叢集由許多資料分割槽(也稱為 Region)組成。每個 Region 負責特定的資料片段,由其起始和結束鍵範圍決定。它在不同的 TiKV 節點上擁有 3 個或更多的副本,並透過 raft 協議進行同步。在舊的 raft 引擎中,每個 TiKV 中只有一個 RocksDB 例項用於儲存所有 Region 的資料。partitioned-raft-KV 特性引入了一個新的物理資料佈局:每個 Region 都有自己的 RocksDB 例項。
圖 2:物理資料佈局比較
舊 Raft KV 引擎面臨的挑戰
"Region" 是 TiKV 中的邏輯規模單元。每個資料訪問和管理操作,如負載均衡、擴充套件和縮小都由 Region 進行分割槽。然而,在當前架構中,它是一個純邏輯概念,物理上沒有清晰的區域邊界。這意味著:
- 當需要將一個 Region 的資料從一個 TiKV 移動到另一個 TiKV(也稱為負載均衡)時,TiKV 需要在巨大的 RocksDB 例項中進行掃描以獲取該 Region 的資料。這造成了讀擴大。
- 當幾個 Region 具有大量的寫流量時,如果它們的鍵範圍分散,那麼很可能會觸發 RocksDB 中的大型壓縮,其中包括其他空閒 Region 的資料。這引入了讀和寫擴大。例如,SST11 是一個 1MB 大小的 SST,只有 region1 的資料,但包含相當大的鍵範圍。當它被選中合併到 L2 時,SST21、SST22 和 SST23 都參與了壓縮,它們包含了 region2、3、4 的資料。TiKV 的規模越大,讀寫擴大越大。
圖 3:不同 Region 之間的壓縮資料
- 沒有 Region 隔離,因此少數熱門 Region 可能會拖慢所有 Region 的效能。
因此,在舊的 raft KV 引擎中,我們可能會遇到以下問題:
- 擴所容的速度很慢,因為需要多次資料掃描。
- 由於 RocksDB 的寫組是單執行緒的,因此寫吞吐量受到限制。
- 由於資料壓縮會不時發生,當 RocksDB 的資料量很大時,使用者流量的延遲不穩定。
Partitioned Raft KV 引擎的改進
- 每個 Region 的資料都是一個專用的 RocksDB 例項,因此只需將 RocksDB 進行 x-copy 以進行 Region 間的負載均衡,避免了讀放大的發生。
- 熱點 Region 的寫入流量只會觸發其自己的 RocksDB 的壓縮,不涉及其他 Region 的資料。因此,它有效地減少了讀和寫放大。
- 在將資料寫入RocksDB時,寫入執行緒之間並不會發生資料同步和鎖爭用,因為每個執行緒都在寫一個不同的 RocksDB 例項。這樣就消除了寫入瓶頸。由於沒有 WAL 日誌,向 RocksDB 的寫入是一個記憶體操作。
- 一個 RocksDB 效能不好並不會影響其他 Region。因此,Region 的效能在儲存層面上是隔離的。
- 現在每個 Region 都支援更大的容量, 預設情況下為 15 GB。和過去 96MB 的 Region 大小限制相比,心跳和記憶體佔用這一類的 Region 開銷降幅高達 99%。
因此,使用 partitioned raft KV,TiDB 在擴充套件或縮小資料方面的速度大約快 5 倍,並且由於壓縮的影響要小得多,其效能總體上更加穩定。
適用範圍
一切看起來都很好。但是還有一個問題。現在我們有更多的 RocksDB 例項,因此它們的 memtable 的記憶體消耗要多得多,這意味著您可能需要額外的 5GB〜10GB 的記憶體開銷才能在記憶體消耗和效能之間達到平衡。因此,當記憶體資源已經非常緊張時,通常不建議開啟此功能。但是,當您在 TiKV 中有額外的記憶體並關心可擴充套件性和寫入效能時,這個功能可能會對您有所幫助。
寫在最後
一些客戶可能會說當前版本的 TiDB 已經足夠好了。所以新功能對他們來說似乎並不重要。但是,如果他們可以在一個叢集中用於多個工作負載,而且每個工作負載都可以得到良好的隔離和 QoS 保證呢?這就是 7.0 版本中的“資源管控”功能。 “partitioned raft KV” 功能旨在最大化硬體效能,與“資源管控”一起使用,我們的客戶將能夠充分利用其硬體資源,並透過將多個工作負載合併到一個叢集中來降低成本。