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

一 引言

當前memcached,redis這類分佈式kv緩存已經很是廣泛。咱們知道memcached的分佈式實際上是一種"僞分佈式",也就是它的服務器節點之間實際上是無關聯的,之間沒有網絡拓撲關係,由客戶端來決定一個key要存放在哪臺機器。redis

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

可是有一個問題,一旦機器數增長或減小,N發生變化,key去mod新舊N獲得的機器編號大機率不相等,那麼以前存放的數據就所有無效了。服務器

 

二 hash環

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

(1) 把全部的機器編號hash到這個環上分佈式

(2) 把key也hash到這個環上,而後在這個環上進行匹配,看這個key和哪臺機器匹配memcached

 

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

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

這裏的關鍵點是:當機器數N變化時,其餘機器在環上的位置並不會發生改變。這樣只有增長/減小的那臺機器附近的數據會失效,其餘機器上的數據仍是有效的blog

 

三 數據傾斜問題

當機器不不少時,極可能出現幾臺機器在環上面貼的很近,分佈很不均勻。這將會致使大部門數據集中在某幾臺機器上。ip

爲了解決這個問題,能夠引入"虛擬機器"的概念,也就是說,一臺機器須要在環上映射出多個位置。好比咱們用機器的ip來hash,那麼咱們能夠在ip後面加幾個編號,形如ip_1, ip_2, ip_3... 這樣就實現了一臺物理機器映射出了多個虛擬機器的編號。

數據首先映射到"虛擬機器"上,再從"虛擬機器"映射到物理機器上。由於虛擬機器能夠不少,在環上均勻分佈,從而保證數據相對均勻地分佈在物理機器上。

 

四 zk的引入

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

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

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

固然不用zk用一個其餘的中心節點也能夠,只要能實現這種更改的通知便可(也即分佈式服務協調)

相關文章
相關標籤/搜索