【另類見解】一致性哈希就能解決分庫分表問題了?

開局一問:分庫分錶行爲中,一致性哈希到底用處大不大?

裝 B 腦圖

現在是大數據的時代,其中一個體現就是數據量非常龐大。當然大數據的概念絕非是數據量就可以定義的,我自己給大數據下的定義是:無處不在的大量數據,這些數據是要經過收集,加工,轉化,然後輸出具有業務意義的數據,比如:現在人物畫像。

迴歸主題,那到底什麼樣的場景下才開始分庫分表呢:

這裏多囉嗦一句,如果你的分庫分表存儲最終還是落在一個物理磁盤上,其實整體 IO 的提高並不明顯,應該把分出的庫(分區表)散落在多個物理磁盤,利用並行 IO 來提高性能。

設計到分庫分表策略,我建議選擇有業務意義的鍵值作爲分的依據。舉個例子,拿用戶信息來說,如果業務中多數是根據用戶 ID 來取用戶信息的場景,那應該利用用戶 id 作爲分的策略主鍵。

接下來的部分就以用戶信息的場景來舉例說明。

分庫分錶行爲屬於變動性行爲,因爲,隨着數據量的不斷增大,分庫分表的策略會隨着改變,最簡單的例子,現在分了 10 個表,當數據量到達 10 個表的巔峯容量時候,就需要繼續分,這就是變動因子。最致命的是這個變動因子會影響已有數據的定位。

現在有很多緩存的應用場景和分庫分表思想類似,但是卻又有本質的區別,因爲緩存數據不需要持久化,所以就算是定位錯了,重新加載即可,數據庫可就不一樣了

簡單哈希有用嗎?

分庫分表最簡單的策略就是對業務數據鍵取模(%),以餘數來作爲導向。帶來的問題也顯而易見:

所以真實的落地項目中,用簡單哈希分庫分表的很少,這就誕生了簡單哈希無用論。

一致性哈希

一致性哈希算法在 1997 年由麻省理工學院提出的一種分佈式哈希(DHT)實現算法,設計目標是爲了解決因特網中的熱點 (Hot spot) 問題。一致性 hash 算法提出了在動態變化的 Cache 環境中,斷定哈希算法好壞的四個定義:

  1. 平衡性 (Balance):平衡性是指哈希的結果可以儘量分佈到全部的緩衝中去,這樣可使得全部的緩衝空間都獲得利用。不少哈希算法都可以知足這一條件。

  2. 單調性 (Monotonicity):單調性是指若是已經有一些內容經過哈希分派到了相應的緩衝中,又有新的緩衝加入到系統中。哈希的結果應可以保證原有已分配的內容能夠被映射到原有的或者新的緩衝中去,而不會被映射到舊的緩衝集合中的其餘緩衝區。

  3. 分散性 (Spread):在分佈式環境中,終端有可能看不到全部的緩衝,而是隻能看到其中的一部分。當終端但願經過哈希過程將內容映射到緩衝上時,因爲不一樣終端所見的緩衝範圍有可能不一樣,從而致使哈希的結果不一致,最終的結果是相同的內容被不一樣的終端映射到不一樣的緩衝區中。這種狀況顯然是應該避免的,由於它致使相同內容被存儲到不一樣緩衝中去,下降了系統存儲的效率。分散性的定義就是上述狀況發生的嚴重程度。好的哈希算法應可以儘可能避免不一致的狀況發生,也就是儘可能下降分散性。

  4. 負載 (Load):負載問題其實是從另外一個角度看待分散性問題。既然不一樣的終端可能將相同的內容映射到不一樣的緩衝區中,那麼對於一個特定的緩衝區而言,也可能被不一樣的用戶映射爲不一樣 的內容。與分散性同樣,這種狀況也是應當避免的,所以好的哈希算法應可以儘可能下降緩衝的負荷。

看完上邊這幾條比較官方的介紹應該大體瞭解了一致性哈希的特性,用作分庫分表場景下也無可厚非,對比簡單哈希,它要好很多。

其實,一致性哈希算法也是使用取模的方法,但是它把分母擴大到了 2^32,縱觀所有的業務場景,能把數據庫(表)分到 2 的 32 次方個的也是個 “人才” 了。一致性哈希把 2 的 32 次方想象成一個圓形,這個圓形上有 2^32 個點。具體的一致性哈希請移步這裏

分佈式緩存

一致性哈希雖然解決了一些問題,但是數據傾斜問題依然存在,爲了使數據最大程度上平均分佈,所以引入了虛擬哈希節點的玩法:對同一個物理服務器節點,通過不同的哈希算法或者其他手段得到多個不同的哈希值,均勻分佈在哈希環上。

其實一致性哈希環點的個數沒有必要是 2 的 32 次方個,我覺得只要足夠大得支撐將來業務的擴展即可,同時能滿足最大平均分配的原則。

共識算法

共識算法在分庫分表的場景中很少有人提出,它現在廣泛用於分佈式系統中,像喜聞樂見的 Paxis,Raft 都屬於共識算法。

分庫分表業務場景下,就算了一致性哈希做到極致,當服務器節點增加或者減少的時候,總有需要數據需要遷移,只不過是多少的問題。那有沒有辦法不用遷移數據呢?

首先說明一點:數據庫不像緩存服務一樣,可以隨時減少節點。數據庫是有狀態的,一般只增不減。

利用共識算法,我認爲在只增加節點的情況下是可以做到不遷移數據的。因爲共識算法的特性就是:一個值達成一致之後,這個值就不會變化了。

假設:現在對用戶信息表已經分了 5 張表,用戶 id 爲 1 的會落在表 1,id 爲 2 的會落在表 2..... 依此類推(這裏可以先不考慮一致性哈希虛擬節點,因爲原理類似),當增加分表 6 的時候,按照簡單哈希原則,id 爲 6 的用戶信息應該在表 6 中,但是現實情況是在表 1 中,按照以往的經驗,這條數據是需要遷移的。

但是引入了共識算法之後,id 爲 6 的用戶數據被算法認爲仍然在表 1 中,因爲已經達成了共識。前提是你需要開發一套共識算法服務來保證,爲什麼很少有人這麼用呢,也許是共識算法門檻過高的原因,但是它卻能真正的解決我們的問題。

自增型數據

以上的說明都是針對散亂型數據而言,其實還有一種 log 型數據,簡單來說就一直追加型的數據,比如操作日誌,這種數據的典型特點就是時間有序,這樣的數據進行分庫分表,完全可以按照時間維度來進行的,比如:可以設計一個月爲一個表,類似 table_202109

寫在最後

無論哪種分表方式,都避免不了熱點問題,就像微博,一個明星出軌了,這條數據就會成爲熱點,而這一條數據只能存儲於一個表中。解決這種熱點問題從來都不能依靠數據庫,像緩存,CDN 等解決方案纔是正解


作者:老 T

來源:技術之上

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