分布式緩存 - hash環/一致性hash


一 引言

當前memcached,redis這類分布式kv緩存已經非常普遍。我們知道memcached的分布式其實是一種"偽分布式",也就是它的服務器節點之間其實是無關聯的,之間沒有網絡拓撲關系,由客戶端來決定一個key要存放在哪台機器。

具體來講,假設我們有多台memcached服務器,編號分別為m0, m1, m2.. 對於一個key,由客戶端來決定存放到哪台機器,最簡單的辦法就是key % N, 其中N是機器的總數

但是有一個問題,一旦機器數增加或減少,N發生變化,key去mod新舊N得到的機器編號大概率不相等,那么之前存放的數據就全部無效了。

 

二 hash環

基於上面的問題,提出了hash環的概念。hash環的過程有兩次hash

(1) 把所有的機器編號hash到這個環上

(2) 把key也hash到這個環上,然后在這個環上進行匹配,看這個key和哪台機器匹配

 

具體過程是這樣: 假定有一個hash函數,其值空間為(0 ~ 2^32-1)。也就是說,其hash值是個32位無整型數字,這些數字組成一個環。首先對機器進行hash(比如根據機器ip),算出每台機器在這個環上的位置; z再對key進行hash,算出該key在環上的位置,然后從這個位置往前走,遇到的第一台機器就是該key對應的機器,就把該(key, value)存儲到該機器上,如下圖所示。

首先計算出每台cache服務器在環上的位置(圖中淺藍色的大圓圈),然后每來一個key計算出value填到環上的位置(圖中橙色的小圓圈),然后順時針走,遇到的第一個機器,就是要存儲的機器

這里的關鍵點是:當機器數N變化時,其他機器在環上的位置並不會發生改變。這樣只有增加/減少的那台機器附近的數據會失效,其他機器上的數據還是有效的

 

三 數據傾斜問題

當機器不很多時,很可能出現幾台機器在環上面貼的很近,分布很不均勻。這將會導致大部門數據集中在某幾台機器上。

為了解決這個問題,可以引入"虛擬機器"的概念,也就是說,一台機器需要在環上映射出多個位置。比如我們用機器的ip來hash,那么我們可以在ip后面加幾個編號,形如ip_1, ip_2, ip_3... 這樣就實現了一台物理機器映射出了多個虛擬機器的編號。

數據首先映射到"虛擬機器"上,再從"虛擬機器"映射到物理機器上。因為虛擬機器可以很多,在環上均勻分布,從而保證數據相對均勻地分布在物理機器上。

 

四 zk的引入

上面我們提到了服務器的機器數N的變化,那么如何通知到客戶端呢

一種笨方法就是手動,當機器數N變化,重新配置客戶端,重啟客戶端。

另外一種,引入zk,服務器的節點列表注冊到zk上面,客戶端監聽zk。發現節點數發生變化,自動更新自己的配置。

當然不用zk用一個其他的中心節點也可以,只要能實現這種更改的通知即可(也即分布式服務協調)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM