今天早上逛B站的時候首頁給我推薦了一個視頻,關於面試中一致性哈希算法的回答,好奇心驅使我點了進去。
時長:1小時半...
很納悶為什么這個淺顯易懂的概念需要講這么久,越來越多培訓機構的營銷號在發一些明明10分鍾解決的問題卻要將幾個小時的視頻,打上一些騙小白的標題,浪費幾個小時看完直接會自閉。
引入問題
我們先來看一個分布式緩存的應用前景。
我們有三台緩存服務器S0,S1,S2。
現在有3萬張圖片需要存儲到這三台服務器,最好能夠均勻的緩存在服務器上。
(可能有人要問了,直接平均分配S1放第一到一萬張...)
如果說我們以后還要添加緩存服務器呢?如果說以后還要添加圖片呢? 直接分配無異於直接定死了規則,以后擴展就是一個坑。
簡單的做法是對圖片進行哈希算法取值,把圖片名稱當作Key。
哈希算法有很多種,這個你暫時不理解也沒關系,它可以對一個Key進行計算獲得一個整數。
對於同一張圖片,我們進行哈希之后得到的整數永遠是同一個,而不同圖片哈希有可能是同一個整數(哈希沖突)。
所以現在我們可以對圖片進行哈希取值,得到的值對3取模,那么每張圖片都可以得到一個0到2的整數,這就對應我們服務器的編號。
流程如下:
這樣我們就可以把圖片隨機分配了,現在我們新來的圖片只需要哈希取值之后再取模就可以知道放到哪個服務器,因為圖片名稱是key,所以我們要找一個圖片也可以通過哈希來找到存放在哪台服務器。
現在有一個問題是,如果說我們要添加一台服務器,那么取模的值3需要變成4,而且之前存儲的圖片都需要重新計算進行改變。因為多了一台服務器,我們在找圖片的時候用了4取模來找,而在存儲時用的是3取模來存儲。
新加一台服務器會導致整個緩存的修改,所以這種方法不適於添加服務器。
一致性哈希算法
對於上面的問題,我們可以通過哈希環來解決,這就是一致性哈希算法的核心了。
我們創建一個環,起始位置是0,終止位置是2的32次方。
對於三台服務器,我們對它們也進行哈希求值(現在不需要取模了),通過哈希我們得到它們在環上的位置。
得到服務器的位置之后,我們可以再來對圖片進行哈希取值拿到它們在環中的位置。
此時,如果我們要尋找圖片0存儲在哪個服務器,就可以對圖片0先進行哈希取值,得到它在環上的位置,從那個位置開始順時針遍歷,找到的第一台服務器就是它的存儲位置。
圖片0,圖片32在服務器S0。
圖片9在服務器S2。
這時如果我們要新添加一台服務器S3,可以先求得它的哈希值找到在環上的位置。
假如說現在得到的時下圖位置。
此時圖片9的緩存服務器就會變成服務器S3,而其它圖片不會有緩存失效問題。
一致性哈希算法可以很大程度上解決添加服務器之后緩存失效的問題,它會用局部失效來保證大部分緩存能夠存活,對於圖片9這種失效的緩存,就可以走正常的訪問路線,直接請求服務器數據庫獲得圖片了。
最后
一致性哈希算法有一個坑,在我們運氣不好的情況下,可能三台服務器哈希取值會非常接近。
這種情況下我們可以對三台服務器進行虛擬化,比如說把S0虛擬為S00,S01,S02,S03...把它們分布在環上。
一致性哈希在分布式緩存中有很大作用,同樣面試也是常常問到,雖然說我們平常自己學習用不到(沒錢買這么多服務器),但是這種分布式算法思想還是很有用的。