redis-官方cluster分割槽

森林森發表於2020-10-22

分割槽與叢集
https://blog.csdn.net/ko0491/article/details/109218004
proxy分割槽
https://blog.csdn.net/ko0491/article/details/109218776

官方cluster分割槽

Redis3.0之後,Redis官方提供了完整的叢集解決方案。
方案採用去中心化的方式,包括:sharding(分割槽)、replication(複製)、failover(故障轉移)。
稱為RedisCluster。
Redis5.0前採用redis-trib進行叢集的建立和管理,需要ruby支援
Redis5.0可以直接使用Redis-cli進行叢集的建立和管理
在這裡插入圖片描述

去中心化

RedisCluster由多個Redis節點組構成,是一個P2P無中心節點的叢集架構,依靠Gossip協議傳播的叢集

Gossip協議

Gossip協議是一個通訊協議,一種傳播訊息的方式。
起源於:病毒傳播
Gossip協議基本思想就是:
一個節點週期性(每秒)隨機選擇一些節點,並把資訊傳遞給這些節點。
這些收到資訊的節點接下來會做同樣的事情,即把這些資訊傳遞給其他一些隨機選擇的節點。
資訊會週期性的傳遞給N個目標節點。這個N被稱為fanout(扇出)
gossip協議包含多種訊息,包括meet、ping、pong、fail、publish等等

在這裡插入圖片描述

通過gossip協議,cluster可以提供叢集間狀態同步更新、選舉自助failover等重要的叢集功能

### slot
redis-cluster把所有的物理節點對映到[0-16383]個slot上,基本上採用平均分配和連續分配的方式。
比如上圖中有5個主節點,這樣在RedisCluster建立時,slot槽可按下表分配:
在這裡插入圖片描述
cluster 負責維護節點和slot槽的對應關係 value------>slot-------->節點
當需要在 Redis 叢集中放置一個 key-value 時,redis 先對 key 使用 crc16 演算法算出一個結果,然後把結果對 16384 求餘數,這樣每個 key 都會對應一個編號在 0-16383 之間的雜湊槽,redis 會根據節點數量大致均等的將雜湊槽對映到不同的節點。
比如:
set name zhaoyun
hash(“name”)採用crc16演算法,得到值:1324203551%16384=15903
根據上表15903在13088-16383之間,所以name被儲存在Redis5節點。
slot槽必須在節點上連續分配,如果出現不連續的情況,則RedisCluster不能工作,詳見容錯。

RedisCluster的優勢

  • 高效能
    Redis Cluster 的效能與單節點部署是同級別的。
    多主節點、負載均衡、讀寫分離

  • 高可用
    Redis Cluster 支援標準的 主從複製配置來保障高可用和高可靠。

  • failover
    Redis Cluster 也實現了一個類似 Raft 的共識方式,來保障整個叢集的可用性。

  • 易擴充套件
    向 Redis Cluster 中新增新節點,或者移除節點,都是透明的,不需要停機。
    水平、垂直方向都非常容易擴充套件。
    資料分割槽,海量資料,資料儲存

  • 原生
    部署 Redis Cluster 不需要其他的代理或者工具,而且 Redis Cluster 和單機 Redis 幾乎完全兼
    容。

叢集搭建

RedisCluster最少需要三臺主伺服器,三臺從伺服器。
埠號分別為:7001~7006

mkdir redis-cluster/7001
make install PREFIX=/var/redis-cluster/7001
  1. 第一步:建立7001例項,並編輯redis.conf檔案,修改port為7001。
    注意:建立例項,即拷貝單機版安裝時,生成的bin目錄,為7001目錄

在這裡插入圖片描述

  1. 第二步:修改redis.conf配置檔案,開啟cluster-enable yes
    在這裡插入圖片描述

  2. 第三步:複製7001,建立7002~7006例項,注意埠修改。

  3. 第四步:建立start.sh,啟動所有的例項

cd 7001/bin
/redis-server redis.conf
cd ..
cd ..
cd 7002/bin
./redis-server redis.conf
cd ..
cd ..
cd 7003/bin
./redis-server redis.conf
cd ..
cd ..
cd 7004/bin
./redis-server redis.conf
cd ..
cd ..
cd 7005/bin
./redis-server redis.conf
cd ..
cd ..
cd 7006/bin
./redis-server redis.conf
cd ..
cd ..

chmod u+x start.sh (賦寫和執行的許可權)

  1. 第五步:建立Redis叢集(建立時Redis裡不要有資料)
# cluster-replicas : 1 1從機 前三個為主
[root@localhost bin]# ./redis-cli --cluster create 192.168.127.128:7001
192.168.127.128:7002 192.168.127.128:7003 192.168.127.128:7004
192.168.127.128:7005 192.168.127.128:7006 --cluster-replicas 1
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 192.168.127.128:7005 to 192.168.127.128:7001
Adding replica 192.168.127.128:7006 to 192.168.127.128:7002
Adding replica 192.168.127.128:7004 to 192.168.127.128:7003
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: 02fdca827762904854293590323bb398e6bee971 192.168.127.128:7001
slots:[0-5460] (5461 slots) master
M: 2dddc9d3925d129edd4c6bd5eab3bbad531277ec 192.168.127.128:7002
slots:[5461-10922] (5462 slots) master
M: 95598dd50a91a72812ab5d441876bf2ee40ceef4 192.168.127.128:7003
slots:[10923-16383] (5461 slots) master
S: 633af51cfdadb907e4d930f3f10082a77b256efb 192.168.127.128:7004
replicates 02fdca827762904854293590323bb398e6bee971
S: 2191b40176f95a2a969bdcaccdd236aa01a3099a 192.168.127.128:7005
replicates 2dddc9d3925d129edd4c6bd5eab3bbad531277ec
S: 1d35bec18fcc23f2c555a25563b1e6f2ffa3b0e9 192.168.127.128:7006
replicates 95598dd50a91a72812ab5d441876bf2ee40ceef4
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
.....
>>> Performing Cluster Check (using node 192.168.127.128:7001)
M: 02fdca827762904854293590323bb398e6bee971 192.168.127.128:7001
slots:[0-5460] (5461 slots) master
1 additional replica(s)
M: 95598dd50a91a72812ab5d441876bf2ee40ceef4 192.168.127.128:7003
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: 2191b40176f95a2a969bdcaccdd236aa01a3099a 192.168.127.128:7005
slots: (0 slots) slave
replicates 2dddc9d3925d129edd4c6bd5eab3bbad531277ec
S: 633af51cfdadb907e4d930f3f10082a77b256efb 192.168.127.128:7004
slots: (0 slots) slave
replicates 02fdca827762904854293590323bb398e6bee971
S: 1d35bec18fcc23f2c555a25563b1e6f2ffa3b0e9 192.168.127.128:7006
slots: (0 slots) slave
replicates 95598dd50a91a72812ab5d441876bf2ee40ceef4
M: 2dddc9d3925d129edd4c6bd5eab3bbad531277ec 192.168.127.128:7002
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

命令客戶端連線叢集
命令

./redis-cli -h 127.0.0.1 -p 7001 -c

注意:-c 表示是以redis叢集方式進行連線

[root@localhost redis-cluster]# cd 7001
[root@localhost 7001]# ./redis-cli -h 127.0.0.1 -p 7001 -c
127.0.0.1:7001> set name1 aaa
-> Redirected to slot [12933] located at 127.0.0.1:7003
OK
127.0.0.1:7003>

檢視叢集的命令
檢視叢集狀態

127.0.0.1:7003> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:3
cluster_stats_messages_sent:926
cluster_stats_messages_received:926

檢視叢集中的節點

127.0.0.1:7003> cluster nodes
d277cd2984639747a17ca79428602480b28ef070 127.0.0.1:7003@17003 myself,master - 0
1570457306000 3 connected 10923-16383
af559fc6c82c83dc39d07e2dfe59046d16b6a429 127.0.0.1:7001@17001 master - 0
1570457307597 1 connected 0-5460
e7b1f1962de2a1ffef2bf1ac5d94574b2e4d67d8 127.0.0.1:7005@17005 slave
068b678923ad0858002e906040b0fef6fff8dda4 0 1570457308605 5 connected
068b678923ad0858002e906040b0fef6fff8dda4 127.0.0.1:7002@17002 master - 0
1570457309614 2 connected 5461-10922
51c3ebdd0911dd6564040c7e20b9ae69cabb0425 127.0.0.1:7004@17004 slave
af559fc6c82c83dc39d07e2dfe59046d16b6a429 0 1570457307000 4 connected
78dfe773eaa817fb69a405a3863f5b8fcf3e172f 127.0.0.1:7006@17006 slave
d277cd2984639747a17ca79428602480b28ef070 0 1570457309000 6 connected
127.0.0.1:7003>

分片

不同節點分組服務於相互無交集的分片(sharding),Redis Cluster 不存在單獨的proxy或配置伺服器,所以需要將客戶端路由到目標的分片

客戶端路由

Redis Cluster的客戶端相比單機Redis 需要具備路由語義的識別能力,且具備一定的路由快取能力

moved重定向

1.每個節點通過通訊都會共享Redis Cluster中槽和叢集中對應節點的關係
2.客戶端向Redis Cluster的任意節點傳送命令,接收命令的節點會根據CRC16規則進行hash運算與16384取餘,計算自己的槽和對應節點
3.如果儲存資料的槽被分配給當前節點,則去槽中執行命令,並把命令執行結果返回給客戶端
4.如果儲存資料的槽不在當前節點的管理範圍內,則向客戶端返回moved重定向異常
5.客戶端接收到節點返回的結果,如果是moved異常,則從moved異常中獲取目標節點的資訊
6.客戶端向目標節點傳送命令,獲取命令執行結果

在這裡插入圖片描述

[root@localhost bin]# ./redis-cli -h 127.0.0.1 -p 7001 -c
127.0.0.1:7001> set name:001 zhaoyun
OK
127.0.0.1:7001> get name:001
"zhaoyun"
[root@localhost bin]# ./redis-cli -h 127.0.0.1 -p 7002 -c
127.0.0.1:7002> get name:001
-> Redirected to slot [4354] located at 127.0.0.1:7001
"zhaoyun"
127.0.0.1:7001> cluster keyslot name:001
(integer) 4354

ask重定向

在對叢集進行擴容和縮容時,需要對槽及槽中資料進行遷移
當客戶端向某個節點傳送命令,節點向客戶端返回moved異常,告訴客戶端資料對應的槽的節點資訊
如果此時正在進行叢集擴充套件或者縮空操作,當客戶端向正確的節點傳送命令時,槽及槽中資料已經被遷
移到別的節點了,就會返回ask,這就是ask重定向機制
1.客戶端向目標節點傳送命令,目標節點中的槽已經遷移支別的節點上了,此時目標節點會返回ask轉
向給客戶端
2.客戶端向新的節點傳送Asking命令給新的節點,然後再次向新節點傳送命令
3.新節點執行命令,把命令執行結果返回給客戶端
在這裡插入圖片描述

moved和ask的區別
1、moved:槽已確認轉移
2、ask:槽還在轉移過程中

Smart智慧客戶端

JedisCluster
JedisCluster是Jedis根據RedisCluster的特性提供的叢集智慧客戶端
JedisCluster為每個節點建立連線池,並跟節點建立對映關係快取(Cluster slots)
JedisCluster將每個主節點負責的槽位一一與主節點連線池建立對映快取
JedisCluster啟動時,已經知道key,slot和node之間的關係,可以找到目標節點
JedisCluster對目標節點傳送命令,目標節點直接響應給JedisCluster
如果JedisCluster與目標節點連線出錯,則JedisCluster會知道連線的節點是一個錯誤的節點
此時節點返回moved異常給JedisCluster
JedisCluster會重新初始化slot與node節點的快取關係,然後向新的目標節點傳送命令,目標命令執行
命令並向JedisCluster響應
如果命令傳送次數超過5次,則丟擲異常"Too many cluster redirection!"

在這裡插入圖片描述

JedisPoolConfig config = new JedisPoolConfig();
Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();
jedisClusterNode.add(new HostAndPort("192.168.127.128", 7001));
jedisClusterNode.add(new HostAndPort("192.168.127.128", 7002));
jedisClusterNode.add(new HostAndPort("192.168.127.128", 7003));
jedisClusterNode.add(new HostAndPort("192.168.127.128", 7004));
jedisClusterNode.add(new HostAndPort("192.168.127.128", 7005));
jedisClusterNode.add(new HostAndPort("192.168.127.128", 7006));
JedisCluster jcd = new JedisCluster(jedisClusterNode, config);
jcd.set("name:001","zhangfei");
String value = jcd.get("name:001");

遷移

  • 在RedisCluster中每個slot 對應的節點在初始化後就是確定的。在某些情況下,節點和分片需要變更:
    新的節點作為master加入;
    某個節點分組需要下線;
    負載不均衡需要調整slot 分佈
  • 此時需要進行分片的遷移,遷移的觸發和過程控制由外部系統完成。包含下面 2 種:
    節點遷移狀態設定:遷移前標記源/目標節點。
    key遷移的原子化命令:遷移的具體步驟
    在這裡插入圖片描述
    1、向節點B傳送狀態變更命令,將B的對應slot 狀態置為importing。
    2、向節點A傳送狀態變更命令,將A對應的slot 狀態置為migrating。
    3、向A 傳送migrate 命令,告知A 將要遷移的slot對應的key 遷移到B。
    4、當所有key 遷移完成後,cluster setslot 重新設定槽位

擴容

新增主節點
先建立7007節點 (無資料)

mkdir redis-cluster/7007
make install PREFIX=/var/redis-cluster/7007

新增7007結點作為新節點,並啟動

[root@localhost bin]# ./redis-cli --cluster add-node 192.168.127.128:7007 192.168.127.128:7001
>>> Adding node 192.168.127.128:7007 to cluster 192.168.127.128:7001
>>> Performing Cluster Check (using node 192.168.127.128:7001)
M: 02fdca827762904854293590323bb398e6bee971 192.168.127.128:7001
slots:[0-5460] (5461 slots) master
1 additional replica(s)
M: 95598dd50a91a72812ab5d441876bf2ee40ceef4 192.168.127.128:7003
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: 2191b40176f95a2a969bdcaccdd236aa01a3099a 192.168.127.128:7005
slots: (0 slots) slave
replicates 2dddc9d3925d129edd4c6bd5eab3bbad531277ec
S: 633af51cfdadb907e4d930f3f10082a77b256efb 192.168.127.128:7004
slots: (0 slots) slave
replicates 02fdca827762904854293590323bb398e6bee971
S: 1d35bec18fcc23f2c555a25563b1e6f2ffa3b0e9 192.168.127.128:7006
slots: (0 slots) slave
replicates 95598dd50a91a72812ab5d441876bf2ee40ceef4
M: 2dddc9d3925d129edd4c6bd5eab3bbad531277ec 192.168.127.128:7002
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
>>> Send CLUSTER MEET to node 192.168.127.128:7007 to make it join the cluster.
[OK] New node added correctly.

檢視叢集結點發現7007已新增到叢集中

127.0.0.1:7001> cluster nodes
d277cd2984639747a17ca79428602480b28ef070 127.0.0.1:7003@17003 master - 0
1570457568602 3 connected 10923-16383
50b073163bc4058e89d285dc5dfc42a0d1a222f2 127.0.0.1:7007@17007 master - 0
1570457567000 0 connected
e7b1f1962de2a1ffef2bf1ac5d94574b2e4d67d8 127.0.0.1:7005@17005 slave
068b678923ad0858002e906040b0fef6fff8dda4 0 1570457569609 5 connected
068b678923ad0858002e906040b0fef6fff8dda4 127.0.0.1:7002@17002 master - 0
1570457566000 2 connected 5461-10922
51c3ebdd0911dd6564040c7e20b9ae69cabb0425 127.0.0.1:7004@17004 slave
af559fc6c82c83dc39d07e2dfe59046d16b6a429 0 1570457567000 4 connected
af559fc6c82c83dc39d07e2dfe59046d16b6a429 127.0.0.1:7001@17001 myself,master - 0
1570457567000 1 connected 0-5460
78dfe773eaa817fb69a405a3863f5b8fcf3e172f 127.0.0.1:7006@17006 slave
d277cd2984639747a17ca79428602480b28ef070 0 1570457567593 6 connected

hash槽重新分配(資料遷移)
新增完主節點需要對主節點進行hash槽分配,這樣該主節才可以儲存資料。

檢視叢集中槽佔用情況

cluster nodes

redis叢集有16384個槽,叢集中的每個結點分配自已槽,通過檢視叢集結點可以看到槽佔用情況

127.0.0.1:7001> cluster nodes
d277cd2984639747a17ca79428602480b28ef070 127.0.0.1:7003@17003 master - 0
1570457568602 3 connected 10923-16383
50b073163bc4058e89d285dc5dfc42a0d1a222f2 127.0.0.1:7007@17007 master - 0
1570457567000 0 connected
e7b1f1962de2a1ffef2bf1ac5d94574b2e4d67d8 127.0.0.1:7005@17005 slave
068b678923ad0858002e906040b0fef6fff8dda4 0 1570457569609 5 connected
068b678923ad0858002e906040b0fef6fff8dda4 127.0.0.1:7002@17002 master - 0
1570457566000 2 connected 5461-10922
51c3ebdd0911dd6564040c7e20b9ae69cabb0425 127.0.0.1:7004@17004 slave
af559fc6c82c83dc39d07e2dfe59046d16b6a429 0 1570457567000 4 connected
af559fc6c82c83dc39d07e2dfe59046d16b6a429 127.0.0.1:7001@17001 myself,master - 0
1570457567000 1 connected 0-5460
78dfe773eaa817fb69a405a3863f5b8fcf3e172f 127.0.0.1:7006@17006 slave
d277cd2984639747a17ca79428602480b28ef070 0 1570457567593 6 connected

給剛新增的7007結點分配槽

第一步:連線上叢集(連線叢集中任意一個可用結點都行)
 ./redis-cli --cluster reshard 192.168.127.128:7007
[root@localhost 7007]# ./redis-cli --cluster reshard 192.168.127.128:7007
>>> Performing Cluster Check (using node 127.0.0.1:7007)
M: 50b073163bc4058e89d285dc5dfc42a0d1a222f2 127.0.0.1:7007
slots: (0 slots) master
S: 51c3ebdd0911dd6564040c7e20b9ae69cabb0425 127.0.0.1:7004
slots: (0 slots) slave
replicates af559fc6c82c83dc39d07e2dfe59046d16b6a429
S: 78dfe773eaa817fb69a405a3863f5b8fcf3e172f 127.0.0.1:7006
slots: (0 slots) slave
replicates d277cd2984639747a17ca79428602480b28ef070
S: e7b1f1962de2a1ffef2bf1ac5d94574b2e4d67d8 127.0.0.1:7005
slots: (0 slots) slave
replicates 068b678923ad0858002e906040b0fef6fff8dda4
M: af559fc6c82c83dc39d07e2dfe59046d16b6a429 127.0.0.1:7001
slots:[0-5460] (5461 slots) master
1 additional replica(s)
M: 068b678923ad0858002e906040b0fef6fff8dda4 127.0.0.1:7002
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
M: d277cd2984639747a17ca79428602480b28ef070 127.0.0.1:7003
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered
第二步:輸入要分配的槽數量
How many slots do you want to move (from 1 to 16384)? 3000


輸入:3000,表示要給目標節點分配3000個槽

第三步:輸入接收槽的結點id

What is the receiving node ID?
輸入:50b073163bc4058e89d285dc5dfc42a0d1a222f2

PS:這裡準備給7007分配槽,通過cluster nodes檢視7007結點id為:

50b073163bc4058e89d285dc5dfc42a0d1a222f2

第四步:輸入源結點id

Please enter all the source node IDs.
Type 'all' to use all the nodes as source nodes for the hash slots.
Type 'done' once you entered all the source nodes IDs

輸入:all

第五步:輸入yes開始移動槽到目標結點id

在這裡插入圖片描述
輸入yes
在這裡插入圖片描述

檢視結果

127.0.0.1:7001> cluster nodes
95598dd50a91a72812ab5d441876bf2ee40ceef4 192.168.127.128:7003@17003 master - 0
1595301163000 3 connected 11922-16383
6ff20bf463c954e977b213f0e36f3efc02bd53d6 192.168.127.128:7007@17007 master - 0
1595301164568 7 connected 0-998 5461-6461 10923-11921
2191b40176f95a2a969bdcaccdd236aa01a3099a 192.168.127.128:7005@17005 slave
2dddc9d3925d129edd4c6bd5eab3bbad531277ec 0 1595301163000 5 connected
633af51cfdadb907e4d930f3f10082a77b256efb 192.168.127.128:7004@17004 slave
02fdca827762904854293590323bb398e6bee971 0 1595301164000 4 connected
1d35bec18fcc23f2c555a25563b1e6f2ffa3b0e9 192.168.127.128:7006@17006 slave
95598dd50a91a72812ab5d441876bf2ee40ceef4 0 1595301161521 6 connected
2dddc9d3925d129edd4c6bd5eab3bbad531277ec 192.168.127.128:7002@17002 master - 0
1595301162000 2 connected 6462-10922
02fdca827762904854293590323bb398e6bee971 192.168.127.128:7001@17001
myself,master - 0 1595301160000 1 connected 999-5460

新增從節點

新增7008從結點,將7008作為7007的從結點

  • 命令
./redis-cli --cluster add-node 新節點的ip和埠 舊節點ip和埠 --cluster-slave --cluster-master-id 主節點id

例如:

./redis-cli --cluster add-node 192.168.127.128:7008 192.168.127.128:7007 --
cluster-slave --cluster-master-id 6ff20bf463c954e977b213f0e36f3efc02bd53d6

50b073163bc4058e89d285dc5dfc42a0d1a222f2是7007結點的id,可通過cluster nodes檢視

[root@localhost bin]# ./redis-cli --cluster add-node 192.168.127.128:7008
192.168.127.128:7007 --cluster-slave --cluster-master-id
6ff20bf463c954e977b213f0e36f3efc02bd53d6

Adding node 192.168.127.128:7008 to cluster 192.168.127.128:7007
Performing Cluster Check (using node 192.168.127.128:7007)
M: 6ff20bf463c954e977b213f0e36f3efc02bd53d6 192.168.127.128:7007
slots:[0-998],[5461-6461],[10923-11921] (2999 slots) master
S: 1d35bec18fcc23f2c555a25563b1e6f2ffa3b0e9 192.168.127.128:7006
slots: (0 slots) slave
replicates 95598dd50a91a72812ab5d441876bf2ee40ceef4
S: 633af51cfdadb907e4d930f3f10082a77b256efb 192.168.127.128:7004
slots: (0 slots) slave
replicates 02fdca827762904854293590323bb398e6bee971
M: 2dddc9d3925d129edd4c6bd5eab3bbad531277ec 192.168.127.128:7002
slots:[6462-10922] (4461 slots) master
1 additional replica(s)
M: 02fdca827762904854293590323bb398e6bee971 192.168.127.128:7001
slots:[999-5460] (4462 slots) master
1 additional replica(s)
S: 2191b40176f95a2a969bdcaccdd236aa01a3099a 192.168.127.128:7005
slots: (0 slots) slave
replicates 2dddc9d3925d129edd4c6bd5eab3bbad531277ec
M: 95598dd50a91a72812ab5d441876bf2ee40ceef4 192.168.127.128:7003
slots:[11922-16383] (4462 slots) master
1 additional replica(s)
[OK] All nodes agree about slots configuration.

Check for open slots…
Check slots coverage…
[OK] All 16384 slots covered.

Send CLUSTER MEET to node 192.168.127.128:7008 to make it join the cluster.
Waiting for the cluster to join

Configure node as replica of 192.168.127.128:7007.
[OK] New node added correctly.

注意:如果原來該結點在叢集中的配置資訊已經生成到cluster-config-file指定的配置檔案中(如果
cluster-config-file沒有指定則預設為nodes.conf),這時可能會報錯

[ERR] Node XXXXXX is not empty. Either the node already knows other nodes (check
with CLUSTER NODES) or contains some key in database 0

解決方法是刪除生成的配置檔案nodes.conf,刪除後再執行./redis-cli --cluster add-node 指令

檢視叢集中的結點,剛新增的7008為7007的從節點

[root@localhost 7008]# ./redis-cli -h 127.0.0.1 -p 7001 -c
127.0.0.1:7001> cluster nodes
95598dd50a91a72812ab5d441876bf2ee40ceef4 192.168.127.128:7003@17003 master - 0
1595301378000 3 connected 11922-16383
6be94480315ab0dd2276a7f70c82c578535d6666 192.168.127.128:7008@17008 slave
6ff20bf463c954e977b213f0e36f3efc02bd53d6 0 1595301378701 7 connected
6ff20bf463c954e977b213f0e36f3efc02bd53d6 192.168.127.128:7007@17007 master - 0
1595301379715 7 connected 0-998 5461-6461 10923-11921
2191b40176f95a2a969bdcaccdd236aa01a3099a 192.168.127.128:7005@17005 slave
2dddc9d3925d129edd4c6bd5eab3bbad531277ec 0 1595301375666 5 connected
633af51cfdadb907e4d930f3f10082a77b256efb 192.168.127.128:7004@17004 slave
02fdca827762904854293590323bb398e6bee971 0 1595301379000 4 connected
1d35bec18fcc23f2c555a25563b1e6f2ffa3b0e9 192.168.127.128:7006@17006 slave
95598dd50a91a72812ab5d441876bf2ee40ceef4 0 1595301380731 6 connected
2dddc9d3925d129edd4c6bd5eab3bbad531277ec 192.168.127.128:7002@17002 master - 0
1595301376000 2 connected 6462-10922
02fdca827762904854293590323bb398e6bee971 192.168.127.128:7001@17001
myself,master - 0 1595301376000 1 connected 999-5460

縮容

命令:

./redis-cli --cluster del-node 192.168.127.128:7008
6be94480315ab0dd2276a7f70c82c578535d6666

刪除已經佔有hash槽的結點會失敗,報錯如下
[ERR] Node 192.168.127.128:7008 is not empty! Reshard data away and try again.

需要將該結點佔用的hash槽分配出去。

容災(failover)

故障檢測

叢集中的每個節點都會定期地(每秒)向叢集中的其他節點傳送PING訊息
如果在一定時間內(cluster-node-timeout),傳送ping的節點A沒有收到某節點B的pong回應,則A將B
標識為pfail。
A在後續傳送ping時,會帶上B的pfail資訊, 通知給其他節點。
如果B被標記為pfail的個數大於叢集主節點個數的一半(N/2 + 1)時,B會被標記為fail,A向整個叢集
廣播,該節點已經下線。
其他節點收到廣播,標記B為fail。

從節點選舉

raft,每個從節點,都根據自己對master複製資料的offset,來設定一個選舉時間,offset越大(複製數
據越多)的從節點,選舉時間越靠前,優先進行選舉。
slave 通過向其他master傳送FAILVOER_AUTH_REQUEST 訊息發起競選
master 收到後回覆FAILOVER_AUTH_ACK 訊息告知是否同意。
slave 傳送FAILOVER_AUTH_REQUEST 前會將currentEpoch 自增,並將最新的Epoch 帶入到
FAILOVER_AUTH_REQUEST 訊息中,如果自己未投過票,則回覆同意,否則回覆拒絕。
所有的Master開始slave選舉投票,給要進行選舉的slave進行投票,如果大部分master node(N/2 +1)都投票給了某個從節點,那麼選舉通過,那個從節點可以切換成master

RedisCluster失效的判定:
1、叢集中半數以上的主節點都當機(無法投票)
2、當機的主節點的從節點也當機了(slot槽分配不連續)

變更通知

當slave 收到過半的master 同意時,會成為新的master。此時會以最新的Epoch 通過PONG 訊息廣播自己成為master,讓Cluster 的其他節點儘快的更新拓撲結構(node.conf)

主從切換

自動切換
就是上面講的從節點選舉

手動切換

人工故障切換是預期的操作,而非發生了真正的故障,目的是以一種安全的方式(資料無丟失)將當前master節點和其中一個slave節點(執行cluster-failover的節點)交換角色

1、向從節點傳送cluster failover 命令(slaveof no one)
2、從節點告知其主節點要進行手動切換(CLUSTERMSG_TYPE_MFSTART)
3、主節點會阻塞所有客戶端命令的執行(10s)
4、從節點從主節點的ping包中獲得主節點的複製偏移量
5、從節點複製達到偏移量,發起選舉、統計選票、贏得選舉、升級為主節點並更新配置
6、切換完成後,原主節點向所有客戶端傳送moved指令重定向到新的主節點
以上是在主節點線上情況下。
如果主節點下線了,則採用cluster failover force或cluster failover takeover 進行強制切換

副本漂移

我們知道在一主一從的情況下,如果主從同時掛了,那整個叢集就掛了。
為了避免這種情況我們可以做一主多從,但這樣成本就增加了。
Redis提供了一種方法叫副本漂移,這種方法既能提高叢集的可靠性又不用增加太多的從機
在這裡插入圖片描述

Master1當機,則Slaver11提升為新的Master1

叢集檢測到新的Master1是單點的(無從機)
叢集從擁有最多的從機的節點組(Master3)中,選擇節點名稱字母順序最小的從機(Slaver31)漂移
到單點的主從節點組(Master1)。

具體流程如下(以上圖為例):

1、將Slaver31的從機記錄從Master3中刪除
2、將Slaver31的的主機改為Master1
3、在Master1中新增Slaver31為從節點
4、將Slaver31的複製源改為Master1
5、通過ping包將資訊同步到叢集的其他節點

相關文章