常見分佈式算法的介紹

背景知識:

  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並沒有使用一致性哈希算法而是使用虛擬槽這種替代方案,因爲虛擬槽技術使得每一個節點管理的槽點是固定的,即使你增加了節點也是需要其他節點將槽點分配給新節點,新節點纔有資格管理槽,因此就不會出現數據丟失的問題)。

最後歡迎大家關注我的公衆號:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章