1、集群的概念
- 集群是一組相互獨立的、通過高速網絡互聯的計算機,它們構成了一個組,並以單一系統的模式加以管理。一個客戶與集群相互作用時,集群像是一個獨立的服務器。集群配置是用於提高可用性和可縮放性。當請求到來首先由負載均衡服務器處理,把請求轉發到另外的一台服務器上,redis集群主要是緩解單台服務器同一時間大量請求帶來的的壓力,就算集群中有服務器宕機,也不影響整體對外提供服務。
- Redis cluster在設計的時候,就考慮到了去中⼼化,去中間件,也就是說,集群中 的每個節點都是平等的關系,都是對等的,每個節點都保存各⾃的數據和整個集 群的狀態。每個節點都和其他所有節點連接,⽽且這些連接保持活躍,這樣就保 證了我們只需要連接集群中的任意⼀個節點,就可以獲取到其他節點的數據
- Redis集群沒有並使⽤傳統的⼀致性哈希來分配數據,⽽是采⽤另外⼀種叫做哈希槽 (hash slot)的⽅式來分配的。redis cluster 默認分配了 16384 個slot,當我們 set⼀個key 時,會⽤CRC16算法來取模得到所屬的slot,然后將這個key 分到哈希槽區間的節點上,具體算法就是:CRC16(key) % 16384。
- Redis 集群會把數據存在⼀個 master 節點,然后在這個 master 和其對應的salve 之間進⾏數據同步。當讀取數據時,也根據⼀致性哈希算法到對應的 master 節 點獲取數據。只有當⼀個master 掛掉之后,才會啟動⼀個對應的 salve 節點,充當 master。
2、組織架構
3、環境准備(每個節點都執行)
#創建目錄
mkdir -p /opt/{6380,6381}/{log,pid,etc}
#添加配置文件
cat >/opt/6380/etc/redis.conf<<-EOF
bind 0.0.0.0
port 6380
daemonize yes
pidfile "/opt/6380/pid/redis.pid"
logfile "/opt/6380/log/redis.log"
dir /opt/6380/
dbfilename dump.rdb
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 15000
EOF
cp /opt/6380/etc/redis.conf /opt/6381/etc/
sed -i "s/6380/6381/g" /opt/6381/etc/redis.conf
#啟動
redis-server /opt/6380/etc/redis.conf
redis-server /opt/6381/etc/redis.conf
#添加防火牆規則
#redis會在當前端口+10000的端口上進行集群節點間的數據交流。
firewall-cmd --permanent --add-port=6380/tcp
firewall-cmd --permanent --add-port=6381/tcp
firewall-cmd --permanent --add-port=16380/tcp
firewall-cmd --permanent --add-port=16381/tcp
firewall-cmd --reload
4、手動搭建redis集群
4.1、手動節點發現
redis-cli -h 192.168.20.161 -p 6380 CLUSTER MEET 192.168.20.162 6380
redis-cli -h 192.168.20.161 -p 6380 CLUSTER MEET 192.168.20.163 6380
redis-cli -h 192.168.20.161 -p 6380 CLUSTER MEET 192.168.20.161 6381
redis-cli -h 192.168.20.161 -p 6380 CLUSTER MEET 192.168.20.162 6381
redis-cli -h 192.168.20.161 -p 6380 CLUSTER MEET 192.168.20.163 6381
redis-cli -h 192.168.20.161 -p 6380 CLUSTER NODES
4.2、手動添加主從復制關系
redis-cli -h 192.168.20.161 -p 6381 CLUSTER REPLICATE 9bd06eadbaf32eff955a211a927fa6ab7dc4d56b
redis-cli -h 192.168.20.162 -p 6381 CLUSTER REPLICATE b1b2dfdea90fe6d833f5a83d77a7a8320bd7497b
redis-cli -h 192.168.20.163 -p 6381 CLUSTER REPLICATE d70d68d2b8557d753e2dcfd03b8aa707727adb11
redis-cli -h 192.168.20.161 -p 6380 CLUSTER NODES
4.2、手動分配槽位
#一共16384個槽位,只有當槽位全部分布完成后,集群才會正常工作,配置時使用的是槽位的序號,從0開始。
redis-cli -h 192.168.20.161 -p 6380 CLUSTER ADDSLOTS {0..5460}
redis-cli -h 192.168.20.162 -p 6380 CLUSTER ADDSLOTS {5461..10921}
redis-cli -h 192.168.20.163 -p 6380 CLUSTER ADDSLOTS {10922..16383}
redis-cli -h 192.168.20.161 -p 6380 CLUSTER NODES
redis-cli -h 192.168.20.161 -p 6380 CLUSTER INFO
5、驗證集群的可用性
5.1、測試數據寫入
[root@node01 ~]# cat set.sh
#!/bin/bash
for i in `seq -w 10000`;
do
redis-cli -h 192.168.20.161 -p 6380 -c set k_$i v_$i
done
bash set.sh
5.2、驗證隨機性
redis-cli -c -h 192.168.20.161 -p 6380 keys \* > keys_all.txt
cat keys_all.txt |awk -F "_" '{print $2}'|sort -n | head
5.3、檢查集群是否健康
#key分布誤差
redis-cli --cluster rebalance 192.168.20.161:6380
>>> Performing Cluster Check (using node 192.168.20.161:6380)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
*** No rebalancing needed! All nodes are within the 2.00% threshold.
#key分布情況
redis-cli --cluster info 192.168.20.161:6380
192.168.20.161:6380 (d70d68d2...) -> 3314 keys | 5461 slots | 1 slaves.
192.168.20.162:6380 (9bd06ead...) -> 3348 keys | 5461 slots | 1 slaves.
192.168.20.163:6380 (b1b2dfde...) -> 3338 keys | 5462 slots | 1 slaves.
[OK] 10000 keys in 3 masters.
0.61 keys per slot on average.
6、調整槽位分配錯誤
6.1、使用工具重新分配槽位
#重新分配槽位
redis-cli --cluster reshard 192.168.20.161:6380
#第一次交互:輸入遷出的槽的數量
How many slots do you want to move (from 1 to 16384)? 5461
#第二次交互:輸入接受的ID
What is the receiving node ID? cluster2的6380的ID
#第三次交互:輸入發送者的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.
Source node #1: cluster1的6380的ID
Source node #2: done
#第四次交互:YES!
#重復上面的操作,將槽位正確分配給 192.168.20.162:6380,192.168.20.16:6380 節點
6.2、pipline
前提條件:
1.了解aof格式
2.了解新版本redis默認是開啟混合模式的
3.需要修改為普通的aof格式並重啟
4.恢復時使用-c參數無效,需要在每一個節點都執行
命令:
redis-cli -c -h 192.168.20.161 -p 6380 --pipe < redis.aof
redis-cli -c -h 192.168.20.162 -p 6380 --pipe < redis.aof
redis-cli -c -h 192.168.20.163 -p 6380 --pipe < redis.aof
7、使用工具搭建集群
7.1、刪除上面使用手工搭建的集群
redis-cli -h 192.168.20.161 -p 6380 FLUSHALL
redis-cli -h 192.168.20.162 -p 6380 FLUSHALL
redis-cli -h 192.168.20.163 -p 6380 FLUSHALL
redis-cli -h 192.168.20.161 -p 6380 CLUSTER RESET
redis-cli -h 192.168.20.162 -p 6380 CLUSTER RESET
redis-cli -h 192.168.20.163 -p 6380 CLUSTER RESET
redis-cli -h 192.168.20.161 -p 6381 CLUSTER RESET
redis-cli -h 192.168.20.162 -p 6381 CLUSTER RESET
redis-cli -h 192.168.20.163 -p 6381 CLUSTER RESET
redis-cli -h 192.168.20.161 -p 6380 CLUSTER NODES
7.2、使用命令一鍵搭建
redis-cli --cluster create 192.168.20.161:6380 192.168.20.162:6380 192.168.20.163:6380 192.168.20.161:6381 192.168.20.162:6381 192.168.20.163:6381 --cluster-replicas 1
7.3、檢查集群狀態
redis-cli -h 192.168.20.161 -p 6380 CLUSTER NODES
redis-cli -h 192.168.20.161 -p 6380 CLUSTER INFO
redis-cli --cluster info 192.168.20.161:6380
redis-cli --cluster check 192.168.20.161:6380
8、集群擴容
8.0、原理圖
8.1、創建新節點
#創建目錄
mkdir -p /opt/{6390,6391}/{log,pid,etc}
#添加配置文件
cp /opt/6380/etc/redis.conf /opt/6390/etc/
cp /opt/6380/etc/redis.conf /opt/6391/etc/
sed -i "s/6380/6390/g" /opt/6390/etc/redis.conf
sed -i "s/6380/6391/g" /opt/6391/etc/redis.conf
#啟動
redis-server /opt/6390/etc/redis.conf
redis-server /opt/6391/etc/redis.conf
#因為是在cluster01,上添加兩個節點,所以需要cluster01上添加防火牆規則。
firewall-cmd --permanent --add-port=6390/tcp
firewall-cmd --permanent --add-port=6391/tcp
firewall-cmd --permanent --add-port=16390/tcp
firewall-cmd --permanent --add-port=16391/tcp
firewall-cmd --reload
8.2、添加節點
redis-cli -h 192.168.20.161 -p 6380 cluster meet 192.168.20.161 6390
redis-cli -h 192.168.20.161 -p 6380 cluster meet 192.168.20.161 6391
redis-cli -h 192.168.20.161 -p 6380 CLUSTER NODES
8.3、添加主從關系
redis-cli -h 192.168.20.161 -p 6391 CLUSTER REPLICATE 01ef4f1ab3102603892ceb55904965ab3211f9eb
8.4、分配hash slot
#重新分配槽位
redis-cli --cluster reshard 192.168.20.161:6380
#第一次交互:從已經構建的集群中拿出多少
How many slots do you want to move (from 1 to 16384)? 4096
#第二次交互:接受節點的ID是什么
What is the receiving node ID? 6390的ID
#第三次交互:哪些節點需要導出,這里輸入all,則會自動的從每個節點拿出一些槽位,交給第四個節點。
Source node #1: all
#第四次交互:確認是否執行
Do you want to proceed with the proposed reshard plan (yes/no)? yes
8.5、集群狀態
* redis-cli -h 192.168.20.161 -p 6380 CLUSTER NODES
* redis-cli -h 192.168.20.161 -p 6380 CLUSTER INFO
9、集群收縮
9.1、原理圖
9.2、重新分配
重新分配槽位
redis-cli --cluster reshard 192.168.20.161:6380
第一次交互:需要遷移多少個槽位
How many slots do you want to move (from 1 to 16384)? 1365
第二次交互:接受節點的ID是什么
What is the receiving node ID? 6380的ID
第三次交互:哪些節點需要導出
Source node #1: 6390的ID
Source node #2: done
第四次交互:確認
Do you want to proceed with the proposed reshard plan (yes/no)? yes
重復上面的操作,直到6390所有的槽位都被分配出去了
檢查集群狀態,確認6390沒有槽位了
redis-cli --cluster info 192.168.20.161:6380
9.3、刪除節點
redis-cli --cluster del-node 192.168.20.161:6390 01ef4f1ab3102603892ceb55904965ab3211f9eb
redis-cli --cluster del-node 192.168.20.161:6391 e897b069b8e869a2f04a0774bbdf2327dc546cca
9.4、驗證集群狀態
redis-cli -h 192.168.20.161 -p 6380 CLUSTER INFO
redis-cli --cluster info 192.168.20.161:6380
10、驗證高可用
10.1、查看集群節點信息
redis-cli -h 192.168.20.161 -p 6380 CLUSTER NODES
10.2、模擬故障
#停止主節點 192.168.20.161:6380
[root@node01 ~]# ps aux|grep redis
root 20335 0.2 0.1 146004 3404 ? Ssl 16:11 0:29 redis-server 0.0.0.0:6380 [cluster]
root 20340 0.1 0.1 146404 3652 ? Ssl 16:11 0:24 redis-server 0.0.0.0:6381 [cluster]
#殺死主節點
kill 20335
#查看信息
redis-cli -h 192.168.20.161 -p 6381 CLUSTER NODES
#再重新啟動節點 192.168.20.161:6380
redis-server /opt/6380/etc/redis.conf
#再次查看狀態
redis-cli -h 192.168.20.161 -p 6381 CLUSTER NODES
10.3、總結
1.主庫掛了,從庫會自動接替主庫的角色,集群恢復正常會受超時時間控制
2.老的主庫修復上線后,會自動變成從庫,同步新的主庫