(二) MdbCluster分散式記憶體資料庫——分散式架構1

smartguy發表於2023-02-15
(二) MdbCluster分散式記憶體資料庫——分散式架構1
 
  分散式架構是MdbCluster的核心關鍵,業界有很多相關的實現,卻很少有文章詳細的解釋每個架構實現背後的細節和這麼做的原因。在MdbCluster整個研發和測試的過程中,我們不斷的遇到各種各樣的問題,分析問題的原因,修改相應的設計和實現,再回歸測試。很多在設計的時候一些頗為得意的trick,卻造成測試時整個系統執行的災難。無數次的推到重來警醒我們——在沒有詳細的測試資料支撐的情況下,不要在設計階段以增加系統複雜度為代價來進行某些想象的最佳化。雖然我們一直知道這是一條真理,但總有忍不住、自作聰明的時候。現實總能一次次地將我們拉回原地——Keep it simple,stupid! 本文試圖總結這一年來我們交的經驗稅,來詳細闡述那些看似簡單架構設計背後的複雜細節。
 
  接我們上一章單節點的架構圖,兩個節點的架構圖如下:

 

  MdbClient與每個節點的MdbAgent建立連線,但只與Master節點進行業務通訊。這個架構本身很簡單,幾乎可以從1-N無限複製,是一個完全的分散式架構,無單點故障。下面我們透過假設讀者的問題,來一步步的介紹整個架構。
  1. 資料是根據什麼策略來進行分片的?
  2. 整個業務的互動流程是怎麼樣的?
  3. 當某個節點狀態和數量發生變化時,其它節點如何感知?
  4. 擴容和縮容時,分片是如何調整的? 
  5. 業務訊息是如何校驗、錯誤訊息如何重定向、超時訊息如何處理?
 
  一、 資料是根據什麼策略來進行分片的?
  關於MdbCluster的Sharding策略,我們直接採用了Redis的策略。Redis Cluster 採用虛擬雜湊槽分割槽,所有的鍵根據雜湊函式對映到 0 ~ 16383 整數槽內,計算公式:slot = CRC16(key) & 16383。每一個節點負責維護一部分槽以及槽所對映的鍵值資料。
 
  
  從我們專案實際使用過程,來說說這個分片規則的好處。
  1. 透過 keys -> slot -> node的對映關係,解決了從表的partitionid到Mdbcluster分片nodeid的對應關係。
  2. 為什麼不是keys->node直接對映?在擴容和縮容的過程中,這種解耦將帶來遷移的便利。利用上圖舉個簡單例子,如果要將節點從5個擴到10個的時候,上述分片策略,只要將node1的slot(1638-3276)挪到node6。node2的slot(4914-6553)挪到node7。依此類推……只要進行5次節點間的資料遷移。但如果是直接對映,分片策略從keys%5->node 轉為 keys%10->node,就會面臨node1->(node2, 3, 4, 5, 6, 7, 8, 9,10)都要挪資料的場景,總共需要遷移的次數為9*5=45。反之,縮容也一樣。
  3. 為什麼slot的數量是16384? 2的14次方。網上有很多說法,但我們的經驗是:在擴縮容做資料遷移的時候,需要對這個slot的資料進行加鎖。如果slot數量太少,鎖定的資料量太大,從而造成遷移過程中業務請求失敗太多。如果slot數量太多,遷移的批次過多,每次遷移的資料條數太少,造成遷移效能受影響。所以這個數字的大小其實是跟業務每張表的資料量有直接關係的。
 
  二、整個業務的互動流程是怎麼樣的?
  

   有兩點需要特別說明,第一是App的驅動到MdbClient是同步請求,有超時管理。這樣做的好處是簡化業務邏輯。其它的環節均為非同步訊息,為了最大化的提高效能。第二是MdbClient到MdbAgent之間具備訊息重定向的能力。這樣做的好處是,在擴縮容的時候,可以減少App側返回錯誤訊息的數量。

 

  

相關文章