《永劫無間》迦南濃妝捏臉資料分享
在如今的計算機系統設計中,有很多的應用已經不再侷限於在單機環境下運行了,這些應用會將本身或者底層的儲存本身部署在分散式環境中,像是資料庫的分片(Sharding),或者是將資料部署到分散式環境下的多臺機器叢集中,從而達到負載均衡。
那我們今天就一起來看看,資料結構在分散式環境應用中扮演著怎麼樣的一個角色。
1、雜湊函式
雜湊函式的定義是將任意長度的一個物件對映到一個固定長度的值上,而這個值稱作雜湊值。
雜湊函式一般有以下三個特性:
- 任何物件作為雜湊函式的輸入都可以得到一個相應的雜湊值;
- 兩個相同的物件作為雜湊函式的輸入,它們總會得到一樣的雜湊值;
- 兩個不同的物件作為雜湊函式的輸入,它們不一定會得到不同的雜湊值。
雜湊函式其實是在解決分散式環境部署的一個重要演算法,我們就以把資料部署到分散式環境機器叢集為例,來說明一下它的重要性。
伺服器部署例子
假設現在維護著一個應用,這個應用在同一個時間段會有大量使用者讀取資料這樣的一個場景。
為了緩解伺服器的壓力,我們決定將資料分別儲存在 3 臺不同的機器中,這樣就可以達到負載均衡的效果。
那要怎麼樣將資料均勻地分發到不同機器中呢?
最簡單的一種雜湊函式設計就是將所有的資料都事先給予一個數字編號,然後採用一個簡單的取模運算後將它們分發出去。
取模運算這樣的雜湊函式是指根據機器節點的數量,將資料的編號對機器節點的數量做除法,得到的餘數就是這個資料最終儲存機器的位置。
下面我們來詳細說明。現在客戶需要檢索以下三個資料,它們的資料編號分別為 7737、8989 和 8338。
因為前面已經決定了需要 3 臺機器來儲存這些資料,所以雜湊函式所要做的運算就是用資料編號除以 3,得到的餘數就是儲存資料的機器編號,也就是資料編號 %3 運算,結果如下表所示:
這種方法非常的直觀和簡單,但是卻有一個致命的缺點,那就是當我們改變機器數量的時候,有很多資料的雜湊運算結果將會改變。
這種情況發生在,當我們的伺服器壓力過大想要擴充伺服器數量的時候;又或者是伺服器數量已經很充足,公司想要節省開支而減少伺服器數量的時候。
我們來舉個簡單的例子看看當發生這種情況時後臺的資料會有什麼樣的變化。
當伺服器數量還是 3 的時候,編號在前 10 的資料,經過雜湊運算後儲存資料的機器如下表所示:
如果我們需要增加一個伺服器,也就是機器數量變成 4 的時候,編號在前 10 的資料,經過雜湊運算後儲存資料的機器如下表所示:
背景被標藍的行,表示儲存這個資料的機器發生了變化。這也就意味著:應用的後臺需要重新將資料分配一遍,而如果有使用者在重新分配資料的這段時間剛好想要訪問這些資料,比如說,使用者想訪問 key 為 3 的資料,到了 3 號伺服器,因為資料還未被重新分配,實際儲存這個資料的伺服器是 0 號伺服器,就會造成想要訪問的資料不存在,這時候使用者只能將所有伺服器遍歷一遍,看看哪一個伺服器儲存了這個資料。
這樣的缺點在資料量十分龐大又或者伺服器非常多的時候,對應用是十分不利的。為了克服這個缺點,我們需要用到另外一種演算法,那就是“一致性雜湊演算法”。
2、一致性雜湊演算法
定義
一致性雜湊演算法(Consistent Hashing)是 David Karger 在 MIT 於 1997 年提出的一個概念,該演算法可以使雜湊演算法的計算獨立於機器的數量。
一致性雜湊演算法會將計算出來的雜湊值對映到一個環中,為了方便說明,因為一個圓環是 360 度,所以這裡採用取模 360 的計算方式將雜湊值對映到環中,也就是說在計算出每個資料或者伺服器的雜湊值 H 後,我們採取 H % 360的計算方式來得到這個資料或者伺服器在圓環中的位置。當然在實際應用中,你也可以採用其他的計算方式將雜湊值對映在環上。
一致性雜湊演算法通常涉及了以下 3 個步驟:
- 計算出分散式環境下機器對應的雜湊值,然後根據雜湊值將其對映到圓環上,對於計算分散式環境下機器的雜湊值,我們一般根據機器的 IP 地址來進行計算;
- 計算出資料的雜湊值,然後根據雜湊值將其對映到圓環上;
- 把對映到圓環上的資料存放到在順時針方向上最接近它的機器中,如果機器對映在圓環上的值和資料對映在圓環上的值相同,則將資料直接儲存在該機器中。
一致性雜湊演算法是怎麼工作的
好了,那現在我們用實際的例子來看看一致性雜湊演算法是如何工作的。
我們還是按照一開始將資料部署到 3 臺機器的情況來講解。假設三個機器對映到環中的位置如下表所示:
資料對映到環中的位置如下表所示:
根據上面的演算法,將所有對映好的資料按順時針儲存到相應的機器節點中,就是說將 Data 1 和 Data 2 放到 Node A 中,Data 3 和 Data 4 放到 Node B 中,Data 5 和 Data 6 放到 Node C 中。
如果這個時候我們需要新增一個新的機器 Node D,對映到環上後的位置如下所示:
根據演算法,這時候只有 Data 1 和 Data 2 需要重新分配到 Node D 中,而不是像之前普通的雜湊演算法,需要將幾乎所有的資料都重新分配一遍。
一致性雜湊演算法,可以將增加或者刪除一個機器導致資料重新分配的平均時間複雜度從 O(K) 降到 O(K / N + log(N)),這裡的 K 代表資料的個數,N 代表機器的個數。
當然了,一致性雜湊演算法還涉及到很多其他問題,比如資料是否平均分配到了不同的機器中,想深入瞭解的話建議看看 Karger 的這篇論文。