在說redis中的雜湊(準確來說是一致性雜湊)問題之前,先來看乙個問題:為什麼在分布式集群中一致性雜湊會得到大量應用?
在乙個分布式系統中,要將資料儲存到具體某個節點,或者將來自客戶端的請求分配到某個伺服器節點做負載均衡,如果採用普通的hash取模演算法進行對映,即如key.hashcode()%n,key代表資料的key,n是伺服器節點數,使用上能達到預期效果。
但是如果此時要下線乙個伺服器或者上線乙個新的伺服器,那麼原來的對映將全部失效。如果是做分布式儲存,則需要做資料遷移;如果是做分布式快取,則原來的快取失效,需要讓新增或下線的節點生效就需要做rehash,資料較大會比較消耗時間(其實這點對hashmap了解的,很熟悉這一點,hashmap在動態擴容進行rehash,資料量過大時很消耗時間影響效能)。這時,一致性雜湊就派上用場了。
下面通過幾個問題逐步介紹redis2.x和redis3.x中的一些特性,來了解一致性雜湊在redis中的應用,以及遇到的問題,不同版本是如何解決的。
1. 假如有兩台redis伺服器,jedis客戶端要存入資料到這兩台伺服器,它如何知道要存入哪台伺服器?
這個就是開篇所說一般的做法:雜湊取模。
key.hashcode() % nums(key是redis中的key,nums是redis伺服器數)最終結果範圍:0到nums-1
2. 此時新增一台redis伺服器,資料能寫入到新增的機器上嗎?不能。還是對原有redis伺服器數進行取模。
那麼如何解決這一問題呢?nums不定義為redis伺服器具體數,而是乙個比較大的值:2^32,從而對映到乙個比較大的空間內,拿key.hashcode*()% 2^32-1來確定存入的伺服器。最終會形成乙個一致性雜湊環,沿著這個環往下找,直至找到。
當然這裡key.hashcode*()% 2^32-1只是舉個例子,實際生產中我們會採用雜湊演算法,如md5、murmurhash、crc32將資料對映到乙個雜湊環上。
3. 假如在新增一台redis伺服器c前,資料存在節點a。加入c後,客戶端在操作的時候,會出現什麼問題?
查詢資料時,如果通過一致性雜湊演算法得出資料在c上,但真實資料在a上,客戶端在c上查詢會找不到資料就會報空指標異常。
這個其實是在redis2.x中的問題,因為redis2.x不支援冬天擴容。這時我們可以考慮找乙個合適的時間點如業務峰值低的時候,將環中的所有資料載入出來,灌入到另外乙個新增節點後的環中進行處理。
4. redis3.x如何解決redis2.x的上述問題?
通過上面的問題可以得知redis2.x不支援動態加節點,就算成功加入新節點,資料會發生錯亂現象,而redis3.x解決了這個問題:
redis集群內建了16384個雜湊槽,當需要在集群中插入資料時,先對key使用crc16演算法得出乙個結果,然後把結果對16384求餘數。這樣每個key都會對應乙個編號在0~16383之間的雜湊槽,redis會根據節點數量大致均等的將雜湊槽對映到不同節點。
redis集群的每個節點負責一部分雜湊槽,這種結構很容易新增或者刪除節點,並且無論是新增刪除或者修改某乙個節點,都不會造成集群不可用的狀態。雜湊槽的好處在於可以方便的新增或移除節點:
1)當需要增加節點時,只需要把其他節點的某些雜湊槽挪到新節點就可以了
2)當需要移除節點時,只需要把移除節點上的雜湊槽挪到其他節點就行了
5. redis3.x的hash碰撞問題
通過hash對映,當某台機器上資料過多支撐不住導致宕機,此時它負責的資料會分配到其他機器,而redis集群伺服器配置一般相同,其他機器也扛不住,就會造成雪崩,即便有主備也解決不了,最終可能導致整個集群都會掛掉。下圖演示了節點c宕機,c上的資料對映到d上的示例:
這其實就是分布式系統中極其常見的問題,資料傾斜。可以考慮通過如下方式解決:
1)如給大量相似資料即key相同,給key加上隨機串,將key打散盡可能隨機分配,避免資料傾斜
2)參考redis2.x版本中"虛擬節點"的做法,為每個真實節點引入n個虛擬節點。具體看下文
6. redis2.x是如何解決hash碰撞的問題?redis2.x有乙個非常重要的概念:虛擬節點,每個節點都虛擬出160個虛擬節點。資料的儲存是沿著環的順時針方向找乙個虛擬節點,每個虛擬節點都會關聯到乙個真實節點。
圖中的a1、a2、b1、b2、c1、c2、d1、d2都是虛擬節點,機器a負載a1、a2的資料,機器b負載b1、b2的資料,機器c負載c1、c2的資料。由於這些虛擬節點數量很多,均勻分布,因此不會造成"雪崩"現象。
,獲取更對技術乾貨
分享Redis中的一致性雜湊問題
在說redis中的雜湊 準確來說是一致性雜湊 問題之前,先來看乙個問題 為什麼在分布式集群中一致性雜湊會得到大量應用?在乙個分布式系統中,要將資料儲存到具體某個節點,或者將來自客戶端的請求分配到某個伺服器節點做負載均衡,如果採用普通的hash取模演算法進行對映,即如key.hashcode n,ke...
一致性雜湊
直接貼出一篇介紹的很清楚的博文。關鍵字一致性雜湊 平衡性,單調性,分散性,負載 其實說白了,就是解決把請求分散到不同的機器上運算,怎麼做分散的平均,機器少一台多一台,或者壞掉一台,成很好的自適應和拓展。最簡單的實現分布式演算法,取模嘛,但是它就上述的一些問題,所以不算好的雜湊函式。一致性雜湊演算法,...
一致性雜湊
from 學習分布式,一致性雜湊是最最基礎的知識,所以要理解好.那什麼是一致性雜湊呢?what 1.平衡性是指 hash的結果應該平均分配到各個節點,這樣從演算法上就解決了負載均衡問題.2.單調性是指 在新增或者刪減節點時,同乙個key訪問到的值總是一樣的.3.分散性是指 資料應該分散的存放在 分布...