1. 程式人生 > >常見分散式演算法的介紹

常見分散式演算法的介紹

背景知識:

  1. 雜湊演算法主要應用於快取分散式系統。
  2. 分散式是指將一個整體拆成多個部分,由多個伺服器來執行完成。注意與叢集的區別,叢集是將多個相同的整體部署在多個伺服器上獨立執行。
  3. 本文主要以key-value式快取為例子講解

1.節點取餘:如果你的快取伺服器有3臺,編號為0,1,2,節點取餘的方式就是將key做雜湊運算並將返回值與3(伺服器個數)取餘,根據值將value分配到相應編號的伺服器中。例如:

例如我有6個key,分別是:1,2,3,4,5,6。根據上面的描述(假設hash函式返回值就是key的值),我們很容易計算出如下值的分佈情況:
           0號伺服器      1號伺服器      2號伺服器
key          3,6          1,4          2,5

注: key=3經過取餘運算會被分配到0號伺服器

但是需要注意的是,節點取餘的容錯性和擴充套件性不好,怎麼理解呢,我們還是舉例:

容錯性:例如有一天我的2號伺服器宕機了向外提供不了服務了,因此需要把它移除並對剩下的伺服器重新編排,
緊接著取餘演算法也要相應發生改變,即與2取餘得到的結果是:

       0號伺服器      1號伺服器
key     2,4,6       1,3,5


擴充套件性:例如由於我們的快取伺服器現在滿足不了業務需求了,因此又增加一臺伺服器,同理取餘演算法相應也發生
了改變,即與4取餘,得到的結果是:

       0號伺服器       1號伺服器      2號伺服器       3號伺服器

kay      4              1,5           2,6          3



我們都知道快取服務,當key對應的值不存在時,會從源頭獲取資料(例如從mysql中),然後再存入快取並返回
給客端,如果key對應的值存在即直接返回給客戶端。基於這個原理,假設在三臺伺服器的時候,我們已經將1-6
個key對應的值設定在了相應的伺服器中,這時候由於宕機了,伺服器變成兩臺了按照上面分析的分佈關係,我們
如果要獲取2對應的值會被分配到0號伺服器中去獲取,但是0號伺服器並沒有儲存(因為2對應的值在三臺服務時
儲存在了編號為2的伺服器中),因此導致的結果就是快取沒有命中,即又要從源頭中獲取資料。
從上述的分析不難發現,節點取餘這種方式只要伺服器節點發生變化,快取的命中率就會降低,因此不介意使用
如果硬要使用的話,建議擴充的節點是原來節點的兩倍。

2.為了解決節點取餘這種伺服器數量一變更就導致大量快取無法命中的問題,一致性雜湊就出現了,一致性雜湊說白了就是將整個雜湊值設計成一個閉合的環狀,並將伺服器節點用雜湊函式對映在這個環上,當有一個key過來了,利用相同的演算法也對映在環上,有人可能會問了那麼這個key到底是屬於哪個伺服器呢?根據key當前對映的位置順時針走,遇到的第一個伺服器就是key對應值所儲存的伺服器。具體可以檢視下圖(忽略圖片左下角水印,粉紅色圈就是key對映在環上的位置,白青色圈就是節點對映在換上的位置)

雖然一致性雜湊解決了節點取餘伺服器數量變更導致大量快取無法命中的問題,相對來說容錯性和可擴充套件性也挺不錯的,但是它仍然會導致小部分快取資料無法命中的問題,這是需要注意的。(這也是為什麼redis並沒有使用一致性雜湊演算法而是使用虛擬槽這種替代方案,因為虛擬槽技術使得每一個節點管理的槽點是固定的,即使你增加了節點也是需要其他節點將槽點分配給新節點,新節點才有資格管理槽,因此就不會出現資料丟失的問題)。