一、為什麼使用Redis Cluster叢集
這裡就要說到Redis叢集的演變過程
1. 主從複制
工作模式為提供多台redis服務,選擇其中的一台作為master節點向外提供讀寫服務,剩下的作為slave節點從master節點複制資料,隻向外提供讀服務。缺點在于,沒能實作redis狀态監控即故障自動切換。當主伺服器當機後,需要手動把一台伺服器切換為主伺服器,會造成一段時間内服務不可用;存儲能力受單機限制;master不能動态擴容。
2. 哨兵
哨兵模式可以實作對redis節點的監控和master的自動故障轉移。但仍然存在一些缺點。由于隻有一台master提供寫服務。當寫操作并發量很大時,無法緩解寫操作的壓力;此外master不能動态擴容。針對這種場景,Redis在3.0版本中引入了Redis Cluster叢集。
二、Redis Cluster簡介
Redis Cluster叢集是一個提供在多個Redis節點之間共享資料的程式集。由多個master節點提供寫服務,每個master節點中存儲的資料都不一樣,這些資料通過資料分片的方式被自動分割到不同的master節點上。
為了保證叢集的高可用,每個master節點下面還需要添加至少1個slave節點,這樣當某個master節點發生故障後,可以從它的slave節點中選舉一個作為新的master節點繼續提供服務。不過當某個master節點和它下面所有的slave節點都發生故障時,整個叢集就不可用了。基本架構圖如下:
三、Redis Cluster叢集的工作原理
3.1 哈希槽分區
這裡就需要提到哈希槽這個概念。
Redis Cluster叢集有16384個哈希槽,每個key通過CRC16校驗後對16384取模來決定放在哪個槽。叢集的每個master節點負責一部分hash槽。比如目前叢集有3個master節點,則:
master1節點包含0~5460号哈希槽
master2節點包含5461~10922号哈希槽
master3節點包含10923~16383号哈希槽
當需要redis叢集存放一個資料(key-value)時,redis會先對這個key進行CRC16算法,将得到的結果對16384進行取餘,這個餘數會對應到(0~16383)其中一個槽,進而決定key-value存儲在哪個節點中。
3.2 叢集通信
尋找槽的過程并非一次就能精準命中的。比如某個key經取餘計算要放到11000号槽位,但并不是一下就找到master3節點,可能先去通路master1、master2節點,再找到master3節點。
叢集中的每個節點都儲存了其它節點的資訊,包括目前叢集狀态、叢集中各節點負責的哈希槽、叢集中各節點的master-slave狀态、叢集中各節點的存活狀态等。這樣即使第一次通路未能命中槽,也會告知用戶端該槽位在哪個節點。
四、環境準備
準備八台機器,ip位址分别為192.168.8.105~112(主機名分别為node1~node8),其中192.168.8.111、192.168.8.112做Redis Cluster叢集擴容&縮容使用,另外六台機器做Redis Cluster叢集。用編譯安裝的方式部署6.2.x版本的redis。
五、搭建Redis Cluster叢集
5.1 啟用Redis Cluster配置
192.168.8.105~110六台機器需做redis.conf的如下配置(有注釋的取消注釋):
bind 0.0.0.0
dir "xxxxxxx" #快照檔案儲存路徑
masterauth xxx #建議配置,否則後期的主從複制不能成功
requirepass xxx
cluster-enabled yes #開啟叢集模式,普通模式不能加入Redis Cluster叢集。開啟後程序會有cluster辨別
cluster-config-file nodes-6379.conf #此為叢集狀态資料檔案,記錄主從關系和哈希槽範圍資訊,由Redis Cluster叢集自動建立和維護
cluster-require-full-coverage no #預設為yes,設為no可以防止一個節點不可用導緻整個Redis Cluster叢集不可用之後啟動Redis
5.2 建立Redis Cluster叢集
在任意一台機器執行如下指令:
redis-cli -a xxxxxx --cluster
create 192.168.8.105:6379 192.168.8.106:6379 192.168.8.107:6379
192.168.8.108:6379 192.168.8.109:6379 192.168.8.110:6379 --cluster-replicas 1
#指令redis-cli --cluster的選項--cluster-replicas是指定每個主節點的從節點個數
輸入yes自動建立叢集,确認已經配置設定的主從關系和各個master節點管理的槽位範圍
這樣Redis Cluster叢集就建立成功了。
可以用redis-cli -a xxxxxx --cluster check ip:port指令或redis-cli –a xxxxxx cluster info指令檢視Redis Cluster叢集狀态,用redis-cli –a xxxxxx cluster nodes檢視主從對應關系&槽位配置設定情況
5.3 測試Redis Cluster叢集讀寫資料
先随便進入一個master節點寫資料,發現不能寫入:
再到對應的master節點去寫資料就正常了。但是讀資料也是在相關的master節點,對應的slave節點也無法執行get k1指令,隻能用keys *指令檢視。此時可以發現,slave節點僅用來存資料,讀寫操作都做不了。
但是用redis-cli -a xxxxxx -c(-c參數用于叢集模式)可以實作自動重定向,随便進入一個master節點寫資料都可以,資料可以重定向到其它master節點
5.4 測試Redis Cluster叢集的高可用
此時的主從關系如下:
将192.168.8.105的redis服務停掉,之後由192.168.8.109提升為新的主節點(見下圖):
通過檢視叢集狀态資料檔案nodes-6379.conf也能看到192.168.8.105的redis服務異常,192.168.8.109提升為新的master節點。現由109機器代替105機器提供讀寫服務
即使重新開機105機器的redis,該機器也變成了109機器的從節點
注意:如果是105和109機器或107和108機器或106和110機器(對應的主從關系的機器)的redis同時挂掉,則它們存的資料就不能通路。如果有設定了RDB持久化,則在重新開機redis後可以從rdb檔案重新加載資料,但是在生産環境這樣也會丢失一部分資料
六、Redis Cluster叢集管理
6.1 擴容
6.1.1 應用場景
在客戶通路量激增的情況下,已有的Redis Cluster叢集很難滿足越來越高的并發通路請求。為解決此問題,就新增兩台機器,把它們動态添加到現有的Redis Cluster叢集,且不影響業務的正常通路。簡單的說就是新加n組主從到叢集中。
注意:生産環境建議master節點為奇數個(eg:3,5),以防發生腦裂現象
6.1.2 準備工作
為192.168.8.111和192.168.8.112兩台機器部署redis,配置檔案與其它六台機器的相同,之後啟動redis。
6.1.3 添加新的master節點到叢集
這裡把192.168.8.111作為新的master節點。在111機器執行如下指令:
redis-cli -a xxxxxx --cluster
add-node 192.168.8.111:6379 192.168.8.106:6379
#這裡包括以下示例中的192.168.8.106為已有Redis Cluster叢集的任意節點
執行效果如下:
此時可以看到,雖然111機器作為新的master加入了Redis Cluster叢集,但沒有槽位,後續需要配置設定。
6.1.4 為新的master節點重新配置設定槽位
在任意一個master節點執行如下指令:
redis-cli -a xxxxxx --cluster reshard 192.168.8.106:6379
這樣就完成配置設定槽位了。再确認一下槽位是否配置設定成功:
此時可以看到,新的master節點槽位已經配置設定成功,但沒有配置從節點,存在高可用隐患。
6.1.5 為新的master節點指定slave節點實作高可用
将192.168.8.112作為192.168.8.111機器的從節點。在112機器執行如下指令:
redis-cli -a magedu --cluster
add-node 192.168.8.112:6379 192.168.8.106:6379 --cluster-slave
--cluster-master-id 9219a29e48e0f2615f1d003714a7cd82a03ae9a1
驗證。如果是8個節點,4組主從說明擴容成功:
此時192.168.8.112就是192.168.8.111的從節點
6.2 縮容
6.2.1 應用場景
随着業務量縮水,使用者通路量明顯下降,業務組經與上司商量後決定将現有Redis Cluster叢集的8台機器下線2台。縮容後仍能滿足目前業務需求。
6.2.2 删除節點的過程
擴容是先添加機器到叢集,再配置設定槽位。而縮容與之相反,是先将要下線的機器的槽位遷移到叢集中的其它機器,然後才能下線機器。如果一個機器上的槽位未完全轉移幹淨,删除該機器時會提示資料出錯導緻無法删除。
6.2.3 遷移要删除的master節點的槽位到其它master節點
這裡仍然用192.168.8.111和192.168.8.112進行操作。
此時主從關系如下:
根據之前的擴容操作(見相關截圖),先把0~1364号槽位移到109機器。在叢集任意一個節點執行如下指令:
redis-cli -a magedu --cluster reshard 192.168.8.106:6379
再把5461~6826号槽位移到106機器,把10923~12287号槽位移到107機器。這樣111機器就沒有槽位了。由于112機器一開始作為111機器的從節點,無槽位,是以後續可直接執行删除機器的操作。
6.2.4 從叢集中删除機器
在叢集中任意一個節點執行如下指令:
#删除111機器
redis-cli -a magedu --cluster
del-node 192.168.8.106:6379 9219a29e48e0f2615f1d003714a7cd82a03ae9a1
#删除112機器
redis-cli -a magedu --cluster
del-node 192.168.8.106:6379 4f6306221bb9afa5ff38ea9e9df85199575b22fd
此時再次檢視就發現111和112機器被踢出叢集了:
6.3 叢集傾斜
Redis Cluster叢集的多個節點運作了一段時間後可能會出現傾斜現象,某個節點資料偏多,記憶體消耗更大,或者通路更多。
發生傾斜的原因如下:
節點之間槽位配置設定不均
不同槽位對應的鍵值數量差異較大
記憶體相關配置不一緻
包含bigkey
熱點資料不均衡。有的資料通路量特别大,有的資料通路量特别小
相關操作包括:
#擷取指定槽位對應的key個數。這裡1000為槽位号
redis-cli -a xxxxxx cluster countkeysinslot 1000
#槽位重新平衡分布
redis-cli -a xxxxxx --cluster rebalance
192.168.8.106:6379
#擷取bigkey
redis-cli -a xxxxxx --bigkeys
七、Redis Cluster叢集的局限性
讀寫操作均由主節點完成,從節點僅做備用
主機數量多,造成維護成本較高
一些指令不能跨節點使用:mget、keys、scan等
不支援多個資料庫,叢集模式下隻有1個資料庫
https://blog.51cto.com/u_15796303/5950859