我這里搭建演示的版本是redis-5.0.5,這個版本對於集群搭建會有很大的簡化,比如最常用的redis-trib.rb腳本功能已經集成到redis-cli工具中了,具體下面會詳細介紹。
一、為什么需要集群
①、並發量
通常來說,單台Redis能夠執行10萬/秒的命令,這個並發基本上能夠滿足我們所有需求了,但有時候比如做離線計算,為了更快的得出結果,有時候我們希望超過這個並發,那這個時候單機就不滿足我們需求了,就需要集群了.
②、數據量
通常來說,單台服務器的內存大概在16G-256G之間,前面我們說Redis數據量都是存在內存中的,那如果實際業務要保存在Redis的數據量超過了單台機器的內存,這個時候最簡單的方法是增加服務器內存,但是單台服務器內存不可能無限制的增加,縱向擴展不了了,便想到如何進行橫向擴展.這時候我們就會想將這些業務數據分散存儲在多台Redis服務器中,但是要保證多台Redis服務器能夠無障礙的進行內存數據溝通,這也就是Redis集群.
二、數據分區方式
對於集群來說,如何將原來單台機器上的數據拆分,然后盡量均勻的分布到多台機器上,這是我們創建集群首先要考慮的一個問題,通常來說,有如下兩種數據分區方式。
順序分布
比如我們有100W條數據,有3台服務器,我們可以將100W/3的結果分別存儲到三台服務器上,如下所示:
特點:鍵值業務相關;數據分散,但是容易造成訪問傾斜;支持順序訪問;支持批量操作。
哈希分布
同樣是100W條數據,有3台服務器,通過自定義一個哈希函數,比如節點取余的方法,余數為0的存在第一台服務器,余數為1的存在第二台服務器,余數為2的存儲在第三台服務器.如下所示:
特點:數據分散度高;鍵值分布與業務無關;不支持順序訪問;支持批量操作。
三、一致性哈希分布
問題:對於上面介紹的哈希分布,大家可以想一下,如果向集群中增加節點,或者集群中有節點宕機,這個時候應該怎么處理?
① 增加節點
如上圖所示,總共10個數據通過節點取余hash(key)%/3 的方式分布到3個節點,這時候由於訪問量變大,要進行擴容,由 3 個節點變為 4 個節點。
我們發現,如圖所示,數據除了標紅的1 2 沒有進行遷移,別的數據都要進行變動,達到了80%,如果這時候並發很高,80%的數據都要從下層節點(比如數據庫)獲取,會給下層節點造成很大的訪問壓力,這是不能接受的。
即使我們進行翻倍擴容,從3個節點增加到6個節點,其數據遷移也在50%左右。
② 刪除節點
上圖其實不管是哪一個節點宕機,其數據遷移量都會超過50%。基本上也是我們所不能接受的。
那么如何使得集群中新增節點或者刪除節點時,數據遷移量最少?——一致性哈希算法誕生。
假設有一個哈希環,從0到2的32次方,均勻的分成三份,中間存放三個節點,沿着順時針旋轉,從Node1到Node2之間的數據,存放在Node2節點上;從Node2到Node3之間的數據,存放在Node3節點上,依次類推。
假設Node1節點宕機,那么原來Node3到Node1之間的數據這時候改為存放到Node2節點上,Node2到Node3之間數據保持不變,原來Node1到Node2之間的數據還是存放在Node2上,也就是只影響三分之一的數據,節點越多,影響數據越少。
同理,假設增加一個節點,影響的數據甚至更少。
當然,實際業務中並不是你節點均勻分布,訪問就會很平均,這時候容易造成訪問傾斜的問題,這里就會引出虛擬節點的定義。
四、Redis Cluster虛擬槽分區
Redis集群數據分布沒有使用一致性哈希分布,而是使用虛擬槽分區概念。
Redis內部內置了序號 0-16383 個槽位,每個槽位可以用來存儲一個數據集合,將這些槽位按順序分配到集群中的各個節點。每次新的數據到來,會通過哈希函數 CRC16(key) 算出將要存儲的槽位下標,然后通過該下標找到前面分配的Redis節點,最后將數據存儲到該節點中。
具體情況如下圖:(以集群有3個節點為例)
至於為什么Redis不使用一致性哈希分布,而是虛擬槽分區。因為虛擬槽分區雖然沒有一致性哈希那么靈活,但是CRC16(key)%16384 已經分布很均勻了,並且對於后面節點增刪操作起來也很方便。
轉自:https://www.cnblogs.com/ysocean/archive/2004/01/13/12328088.html