Redis 超詳細的手動搭建Cluster集群步驟
點擊上方藍色字體,選擇“標星公眾號”
優(yōu)質文章,第一時間送達
作者 | 云崖先生
來源 | urlify.cn/BZN7fm
功能概述
Redis Cluster是Redis的自帶的官方分布式解決方案,提供數(shù)據(jù)分片、高可用功能,在3.0版本正式推出。
使用Redis Cluster能解決負載均衡的問題,內部采用哈希分片規(guī)則:
基礎架構圖如下所示:

圖中最大的虛線部分為一個Cluster集群,由6個Redis實例組成。
集群分片
整個Cluster集群中有16384個槽位,必須要將這些槽位分別規(guī)劃在3臺Master中。
如果有任意1個槽位沒有被分配,則集群創(chuàng)建不成功。
當集群中任意一個Master嘗試進行寫入操作后,會通過Hash算法計算出該條數(shù)據(jù)應該落在哪一個Master節(jié)點上。
如下圖所示:

情況1:如果你未指定任何參數(shù)就進行寫入,如在Master1上寫入數(shù)據(jù),經過內部計算發(fā)現(xiàn)該數(shù)據(jù)應該在Master2上寫入時,會提示你應該進入Master2寫入該條數(shù)據(jù),執(zhí)行并不會成功
情況2:如果你指定了一個特定參數(shù)進行寫入,如在Master1上寫入數(shù)據(jù),經過內部計算發(fā)現(xiàn)該數(shù)據(jù)應該在Master2上寫入時,會自動將寫入環(huán)境重定向至Master2,執(zhí)行成功
同理,讀取數(shù)據(jù)也是這樣,這個過程叫做MOVED重定向,如果你是情況1進行操作則必須手動進行重定向,情況2則會自動進行重定向。
集群通信
集群中各個節(jié)點的信息是互通的,這種現(xiàn)象由Gossip(流言)協(xié)議產生。
Gossip協(xié)議規(guī)定每個集群節(jié)點之間互相交換信息,使其能夠彼此知道對方的狀態(tài)。
在通信建立時,集群中的每一個節(jié)點都會單獨的開辟一個TCP通道,用于與其他節(jié)點進行通信,這個通信端口會在基礎端口上+10000。
通信建立成功后,每個節(jié)點在固定周期內通過特定規(guī)則選擇節(jié)點來發(fā)送ping消息(心跳機制)。
當收到ping消息的節(jié)點則會使用pong消息作為回應,也就是說,當有一個新節(jié)點加入后,一瞬間集群中所有的其他節(jié)點也能夠獲取到該信息。
Gossip協(xié)議的主要職責就是進行集群中節(jié)點的信息交換,常見的Gossip協(xié)議消息有以下幾點區(qū)分:
meet:用于通知新節(jié)點加入,消息發(fā)送者通知接受者加入到當前集群
ping:集群內每個節(jié)點與其他節(jié)點進行心跳檢測的命令,用于檢測其他節(jié)點是否在線,除此之外還能交換其他額外信息
pong:用于回復meet以及ping信息,表示已收到,能夠正常通行。此外還能進行群發(fā)更新節(jié)點狀態(tài)
fail:當其他節(jié)點收到fail消息后立馬把對應節(jié)點更新為下線狀態(tài),此時集群開始進行故障轉移

初步搭建
地址規(guī)劃
3臺服務器,每臺服務器開啟2臺實例構建基礎主從。
服務器采用centos7.3,Redis版本為6.2.1
地址規(guī)劃與結構圖如下:

在每個節(jié)點hosts文件中加入以下內容;
$ vim /etc/hosts
192.168.0.120 node1
192.168.0.130 node2
192.168.0.140 node3
集群準備
為所有節(jié)點下載Redis:
$ cd ~
$ wget https://download.redis.io/releases/redis-6.2.1.tar.gz
為所有節(jié)點配置目錄:
$ mkdir -p /usr/local/redis_cluster/redis_63{79,80}/{conf,pid,logs}
所有節(jié)點進行解壓:
$ tar -zxvf redis-6.2.1.tar.gz -C /usr/local/redis_cluster/
所有節(jié)點進行編譯安裝Redis:
$ cd /usr/local/redis_cluster/redis-6.2.1/
$ make && make install
書寫集群配置文件,注意!Redis普通服務會有2套配置文件,一套為普通服務配置文件,一套為集群服務配置文件,我們這里是做的集群,所以書寫的集群配置文件,共6份:
$ vim /usr/local/redis_cluster/redis_6379/conf/redis.cnf
# 快速修改::%s/6379/6380/g
# 守護進行模式啟動
daemonize yes
# 設置數(shù)據(jù)庫數(shù)量,默認數(shù)據(jù)庫為0
databases 16
# 綁定地址,需要修改
bind 192.168.0.120
# 綁定端口,需要修改
port 6379
# pid文件存儲位置,文件名需要修改
pidfile /usr/local/redis_cluster/redis_6379/pid/redis_6379.pid
# log文件存儲位置,文件名需要修改
logfile /usr/local/redis_cluster/redis_6379/logs/redis_6379.log
# RDB快照備份文件名,文件名需要修改
dbfilename redis_6379.rdb
# 本地數(shù)據(jù)庫存儲目錄,需要修改
dir /usr/local/redis_cluster/redis_6379
# 集群相關配置
# 是否以集群模式啟動
cluster-enabled yes
# 集群節(jié)點回應最長時間,超過該時間被認為下線
cluster-node-timeout 15000
# 生成的集群節(jié)點配置文件名,文件名需要修改
cluster-config-file nodes_6379.conf
啟動集群
啟動集群
在啟動集群時,會按照Redis服務配置文件的配置項判斷是否啟動集群模式,如圖所示:

每個節(jié)點上執(zhí)行以下2條命令進行服務啟動:
$ redis-server /usr/local/redis_cluster/redis_6379/conf/redis.cnf
$ redis-server /usr/local/redis_cluster/redis_6380/conf/redis.cnf
集群模式啟動,進程后會加上[cluster]的字樣:
$ ps -ef | grep redis
root 51311 1 0 11:30 ? 00:00:00 redis-server 192.168.0.120:6379 [cluster]
root 51329 1 0 11:30 ? 00:00:00 redis-server 192.168.0.120:6380 [cluster]
root 51396 115516 0 11:31 pts/1 00:00:00 grep --color=auto redis
同時,查看一下集群節(jié)點配置文件,會發(fā)現(xiàn)生成了一組集群信息,每個Redis服務都是不同的:
$ cat /usr/local/redis_cluster/redis_6379/nodes_6379.conf
c8a8c7d52e6e7403e799c75302b6411e2027621b :0@0 myself,master - 0 0 0 connected
vars currentEpoch 0 lastVoteEpoch 0
$ cat /usr/local/redis_cluster/redis_6380/nodes_6380.conf
baa10306639fcaca833db0d521235bc9593dbeca :0@0 myself,master - 0 0 0 connected
vars currentEpoch 0 lastVoteEpoch 0
# 第一段信息是這個Redis服務作為集群節(jié)點的一個身份編碼
# 別名為集群的node-id
加入集群
現(xiàn)在雖然說每個服務都成功啟動了,但是彼此之間并沒有任何聯(lián)系。
所以下一步要做的就是將6個服務加入至一個集群中,如下操作示例:
$ redis-cli -h node1 -p 6379
node1:6379> cluster meet 192.168.0.130 6379
node1:6379> cluster meet 192.168.0.140 6379
node1:6379> cluster meet 192.168.0.120 6380
node1:6379> cluster meet 192.168.0.130 6380
node1:6379> cluster meet 192.168.0.140 6380
查看當前集群所有的節(jié)點:
node1:6379> cluster nodes
214dc5a10149091047df1c61fd3415d91d6204ea 192.168.0.130:6379@16379 master - 0 1617291123000 1 connected
baa10306639fcaca833db0d521235bc9593dbeca 192.168.0.120:6380@16380 master - 0 1617291120000 3 connected
7a151f97ee9b020a3c954bbf78cd7ed8a674aa70 192.168.0.140:6379@16379 master - 0 1617291123000 2 connected
bae708f7b8df32edf4571c72bbf87715eb45c169 192.168.0.130:6380@16380 master - 0 1617291124175 4 connected
fd1dde2a641727e52b4e82cfb351fe3c17690a17 192.168.0.140:6380@16380 master - 0 1617291124000 0 connected
c8a8c7d52e6e7403e799c75302b6411e2027621b 192.168.0.120:6379@16379 myself,master - 0 1617291121000 5 connected
查看端口監(jiān)聽,可以發(fā)現(xiàn)Gossip監(jiān)聽的1000+端口出現(xiàn)了,此時代表集群各個節(jié)點之間已經能互相通信了:
$ netstat -lnpt | grep redis
tcp 0 0 192.168.0.120:6379 0.0.0.0:* LISTEN 51311/redis-server
tcp 0 0 192.168.0.120:6380 0.0.0.0:* LISTEN 51329/redis-server
tcp 0 0 192.168.0.120:16379 0.0.0.0:* LISTEN 51311/redis-server
tcp 0 0 192.168.0.120:16380 0.0.0.0:* LISTEN 51329/redis-server
主從配置
6個服務之間并沒有任何主從關系,所以現(xiàn)在進行主從配置,記錄下上面cluster nodes命令輸出的node-id信息,只記錄主節(jié)點:
首先是node1的6380,將它映射到node2的6379:
$ redis-cli -h node1 -p 6380
node1:6380> cluster replicate 214dc5a10149091047df1c61fd3415d91d6204ea
然后是node2的6380,將它映射到node3的6379:
$ redis-cli -h node2 -p 6380
node2:6380> cluster replicate 7a151f97ee9b020a3c954bbf78cd7ed8a674aa70
最后是node3的6380,將它映射到node1的6379:
$ redis-cli -h node3 -p 6380
node3:6380> cluster replicate c8a8c7d52e6e7403e799c75302b6411e2027621b
查看集群節(jié)點信息,內容有精簡:
$ redis-cli -h node1 -p 6379
node1:6379> cluster nodes
192.168.0.130:6379@16379 master
192.168.0.120:6380@16380 slave
192.168.0.140:6379@16379 master
192.168.0.130:6380@16380 slave
192.168.0.140:6380@16380 slave
192.168.0.120:6379@16379 myself,master
# myself表示當前登錄的是那個服務
分配槽位
接下來我們要開始分配槽位了,為了考慮今后的寫入操作能分配均勻,槽位也要進行均勻分配。
僅在Master上進行分配,從庫不進行分配,僅做主庫的備份和讀庫使用。
使用python計算每個master節(jié)點分多少槽位:
$ python3
>>> divmod(16384,3)
(5461, 1)
槽位分配情況如下,槽位號從0開始,到16383結束,共16384個槽位:
開始分配:
$ redis-cli -h node1 -p 6379 cluster addslots {0..5461}
$ redis-cli -h node2 -p 6379 cluster addslots {5462..10922}
$ redis-cli -h node3 -p 6379 cluster addslots {10923..16383}
檢查槽位是否分配正確,這里進行內容截取:
$ redis-cli -h node1 -p 6379
node1:6379> CLUSTER nodes
192.168.0.130:6379@16379 master - 0 1617292240544 1 connected 5462-10922
192.168.0.140:6379@16379 master - 0 1617292239000 2 connected 10923-16383
192.168.0.120:6379@16379 myself,master - 0 1617292238000 5 connected 0-5461
# 看master節(jié)點的最后
檢查狀態(tài)
使用以下命令檢查集群狀態(tài)是否ok,如果槽位全部分配完畢應該是ok,不然的話就檢查你分配槽位時是否輸錯了數(shù)量:
$ redis-cli -h node1 -p 6379
node1:6379> 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:5
cluster_my_epoch:5
cluster_stats_messages_ping_sent:2825
cluster_stats_messages_pong_sent:2793
cluster_stats_messages_meet_sent:5
cluster_stats_messages_sent:5623
cluster_stats_messages_ping_received:2793
cluster_stats_messages_pong_received:2830
cluster_stats_messages_received:5623
MOVED重定向
現(xiàn)在我們在node1的master節(jié)點上進行寫入:
$ redis-cli -h node1 -p 6379
node1:6379> set k1 "v1"
(error) MOVED 12706 192.168.0.140:6379
它會提示你去node2的master上進行寫入。
這個就是MOVED重定向。
-c參數(shù)
如何解決這個問題?其實在登錄的時候加上參數(shù)-c即可,-c參數(shù)無所謂你的Redis是否是集群模式,建議任何登錄操作都加上,這樣即使是Redis集群也會自動進行MOVED重定向:
$ redis-cli -c -h node1 -p 6379
node1:6379> set k1 "v1"
-> Redirected to slot [12706] located at 192.168.0.140:6379
OK
一并對主從進行驗證,這條數(shù)據(jù)是寫入至了node3的Master中,我們登錄node2的Slave中進行查看:
$ redis-cli -h node2 -p 6380 -c
node2:6380> keys *
1) "k1"
故障轉移
故障模擬
模擬node1的6379下線宕機,此時應該由node3的6380接管它的工作:
$ redis-cli -h node1 -p 6379 shutdown
登錄集群任意節(jié)點查看目前的集群節(jié)點信息:
node2:6379> cluster nodes
214dc5a10149091047df1c61fd3415d91d6204ea 192.168.0.130:6379@16379 myself,master - 0 1617294532000 1 connected 5462-10922
bae708f7b8df32edf4571c72bbf87715eb45c169 192.168.0.130:6380@16380 slave 7a151f97ee9b020a3c954bbf78cd7ed8a674aa70 0 1617294533000 2 connected
# 已下線
c8a8c7d52e6e7403e799c75302b6411e2027621b 192.168.0.120:6379@16379 master,fail - 1617294479247 1617294475173 5 disconnected
7a151f97ee9b020a3c954bbf78cd7ed8a674aa70 192.168.0.140:6379@16379 master - 0 1617294536864 2 connected 10923-16383
# 自動升級為主庫,并且插槽也轉移了
fd1dde2a641727e52b4e82cfb351fe3c17690a17 192.168.0.140:6380@16380 master - 0 1617294536000 6 connected 0-5461
baa10306639fcaca833db0d521235bc9593dbeca 192.168.0.120:6380@16380 slave 214dc5a10149091047df1c61fd3415d91d6204ea 0 1617294535853 1 connected
恢復工作
重啟node1的6379:
$ redis-server /usr/local/redis_cluster/redis_6379/conf/redis.cnf
登錄node1的6379,發(fā)現(xiàn)他已經自動的進行上線了,并且作為node3中6380的從庫:
$ redis-cli -h node1 -p 6379
node1:6379> cluster nodes
# 自動上線
c8a8c7d52e6e7403e799c75302b6411e2027621b 192.168.0.120:6379@16379 myself,slave fd1dde2a641727e52b4e82cfb351fe3c17690a17 0 1617294746000 6 connected
cluster命令
以下是集群中常用的可執(zhí)行命令,命令執(zhí)行格式為:
cluster 下表命令
命令如下,未全,如果想了解更多請執(zhí)行cluster help操作:
粉絲福利:Java從入門到入土學習路線圖
??????

??長按上方微信二維碼 2 秒
感謝點贊支持下哈 
