Redis 高可用方案:sentinel(哨兵模式)和集羣

一. redis 高可用方案–sentinel(哨兵模式)

當我們搭建好 redis 主從複製方案後會發現一個問題,那就是當主服務器宕機後,需要手動把一臺從服務器切換爲主服務器,這就需要人工干預,費事費力,同時在手動切過程中也會導致 redis 服務器寫入功能不可用。所以需要一種方法可以完成 Master 故障後可以自動的將一個 Slave 切換爲 Master,這個時候就有了 sentinel 哨兵模式。

哨兵模式簡介:

sentinel 是官方提供的高可用方案,其原理是哨兵通過發送命令,等待 Redis 服務器響應,從而監控運行的多個 Redis 實例。同時 sentinel 是一個分佈式系統,可以在一個架構中運行多個 Sentinel 進程,可以做到 sentinel 的高可用。

sentinel 工作過程:
關於 sentinel 的三個定時任務:
sentinel 網絡:

sentinel 是一個分佈式系統,可以在一個架構中運行多個 Sentinel 進程。所以監控同一個 Master 的 Sentinel 會自動連接,組成一個分佈式的 Sentinel 網絡,互相通信並交換彼此關於被監視服務器信息。

sentinel 網絡故障修復原理:

1. 主觀下線:

當主服務器發生故障時,此時一個 sentinel 發現了故障,系統並不會馬上進行 failover 過程(這個現象稱爲主觀下線),它會向網絡中的其他 Sentinel 進行確認。

2. 客觀下線:

接着其他 Sentinel 也陸續發現故障,這個時候其中一個 Sentinel 就會發起投票。一定數量的哨兵 (在配置文件中指定) 確認 Master 被標記爲主觀下線,此時將 Master 標記爲客觀下線。

3.sentinel 的 leader 選舉:

要想完成故障切換(將故障 master 剔除,並將一個 slave 提升爲 master)就必須先選舉一個 leader。最先發現故障的 sentinel 向其他哨兵發起請求成爲 leader,其他哨兵在沒有同意別的哨兵的 leader 請求時,就會把票投給該 sentinel。當半數以上的 sentinel 投票通過後就認定該 sentinel 爲 leader。接下來的故障切換有該 leader 完成。

4.master 選舉:

leader 選好後將故障 master 剔除,從 slave 中挑選一個成爲 master。遵照的原則如下:

5. 新 Master 再通過發佈訂閱模式通知所有 sentinel 更新監控主機信息。

6. 故障的主服務器修復後將成爲從服務器繼續工作。

故障發生

故障切換

Master 重新上線後

哨兵模式配置

本實驗在一臺機器上完成,創建不同端口的 redis 實例。

1. 創建 redis 實例

[root@redis ~]# nohup redis-server --port 6380 >> /data/redis/log/6380.log 2>&1 & 
[root@redis ~]# nohup redis-server --port 6381 >> /data/redis/log/6381.log 2>&1 & 
[root@redis ~]# nohup redis-server --port 6382 >> /data/redis/log/6382.log 2>&1 & 

[root@redis ~]# ps -ef |grep redis
root      16421  16314  0 03:01 pts/1    00:00:00 redis-server *:6380
root      16427  16314  0 03:01 pts/1    00:00:00 redis-server *:6381
root      16431  16314  0 03:01 pts/1    00:00:00 redis-server *:6382
root      16436  16314  0 03:01 pts/1    00:00:00 grep --color=auto redis

2. 連接數據庫並設置主從複製

[root@redis ~]# redis-cli -p 6380
127.0.0.1:6380> 

[root@redis ~]# redis-cli -p 6381
127.0.0.1:6381> SLAVEOF 127.0.0.1 6380    #將6380設置爲master
OK
[root@redis ~]# redis-cli -p 6382
127.0.0.1:6382> SLAVEOF 127.0.0.1 6380
OK

3. 搭建哨兵模式集羣

創建 sentinel 配置文件

[root@redis conf]# cat sentinel1.conf 
port 26300                              #指定sentinel進程端口號
sentinel monitor redis1 127.0.0.1 6380 2  #Sentinel monitor <name> <ip> <port> <quorum>

[root@redis conf]# cat sentinel2.conf 
port 26301
sentinel monitor redis1 127.0.0.1 6380 2

啓動 sentinel

[root@redis ~]# nohup redis-sentinel /data/redis/conf/sentinel1.conf >> /data/redis/log/sentinel1.log 2>&1 &
[1] 16522
[root@redis ~]# nohup redis-sentinel /data/redis/conf/sentinel2.conf >> /data/redis/log/sentinel2.log 2>&1 &
[2] 16526
[root@redis ~]# ps -ef |grep sentinel
root      16522  16440  0 03:55 pts/2    00:00:00 redis-sentinel *:26300 [sentinel]
root      16526  16440  0 03:55 pts/2    00:00:00 redis-sentinel *:26301 [sentinel]

4. 測試。模擬主節點故障,查看故障後主從環境改變

關閉主節點

[root@redis ~]#  ps -ef |grep redis-server
root      16604  16440  0 04:12 pts/2    00:00:02 redis-server *:6381
root      16608  16440  0 04:12 pts/2    00:00:03 redis-server *:6382
root      16702  16314  0 04:46 pts/1    00:00:00 redis-server *:6380
[root@redis ~]# kill 16702

此時查看 6381 和 6382 的日誌文件,在 6382 的日誌文件中發現瞭如下內容,說明此時已經將 6381 切換爲主節點。

再次啓動 6380 時,6380 成爲 slave,6381 時 master

最後查看一下 sentinel 配置文件:

cat /data/redis/conf/sentinel2.conf
port 26301
sentinel myid 74cdfbb5ae55a77ad4d05d5d9d50fd64725e192a
# Generated by CONFIG REWRITE
dir "/root"
protected-mode no
sentinel deny-scripts-reconfig yes
sentinel monitor redis1 127.0.0.1 6381 1     #主節點
sentinel config-epoch redis1 1
sentinel leader-epoch redis1 1
sentinel known-replica redis1 127.0.0.1 6382    #從節點
sentinel known-replica redis1 127.0.0.1 6380
sentinel known-sentinel redis1 127.0.0.1 26300 9539652da78b0385479a827e753deceaef864989
sentinel current-epoch 1

二. redis 高可用方案–集羣

使用哨兵模式,解決了主節點故障自動切換的問題,但是卻不可以動態擴充 redis。所以在 redis3.0 之後提出了集羣模式。

redis 集羣設計:

redis 集羣採用無中心結構,每個節點保存數據和整個集羣狀態, 每個節點都和其他所有節點連接。

特點:

redis 集羣節點分配和數據分配

節點分配:

Redis 集羣預分好 16384 個桶,採用哈希槽 (hash slot) 的方式來平均分配 16384 個 slot 。以三個節點爲例,

若存入一個值,按照哈希槽算法得到 6587,那麼就會將數據存入節點 2。取數據時也是從節點 2 上取。

當新增一個節點時:

採用從各個節點的前面各拿取一部分槽到新節點上,如添加節點 4,哈希槽就爲,0-1364,5461-6826,10923-12287。

redis 集羣的主從模式

爲了保證數據高可用,集羣應建立在主從基礎之上。一個主節點對應一個從節點。主節點提供數據存取,從節點提供數據讀取,當主節點故障後,就會有這個從節點選取一個來充當主節點,從而保證集羣正常運行。

但是在一個集羣中,一對主從節點同時故障,那麼集羣將失去服務能力。

redis 集羣搭建:

redis 集羣中至少應該有奇數個節點,所以至少有三個節點,每個節點至少有一個備份節點,所以本次實驗使用 6 個節點(主節點、備份節點由 redis-cluster 集羣確定)。

實驗在兩臺機器進行,每臺機器啓動三個基於不同端口 redis 實例,6 個實例兩兩對應主從。

1. 創建一個目錄 redis_cluster, 用來存放每個實例所用的配置文件.

[root@redis redis]# mkdir redis_cluster
[root@redis redis]# mkdir -p redis_cluster/7001
[root@redis redis]# cp -r conf/redis.conf redis_cluster/

2. 修改配置文件,將修改好的文件複製 5 份分別放置不同 redis 配置目錄下。

修改配置文件

vim 7001/redis.conf修改一下幾項
bind 192.168.126.162  (本機IP)
port 7001                                    #redis端口
daemonize yes                               #redis在後臺啓動
logfile "/data/redis/log/logs"
pidfile /var/run/redis_7001.pid
cluster-enabled yes                    #開啓集羣功能
cluster-config-file nodes-7001.conf    #集羣配置文件
cluster-node-timeout 5000          #姐點之間通訊時間
appendonly yes                      #開啓AOF持久化方式

創建目錄 7002 到 7006,其中 7004 到 7005 創建在192.168.126.161上。再把配置文件複製到700*目錄下,修改配置文件中端口號和 ip。

[root@redis redis_cluster]# cp -rp 7001 7002
[root@redis redis_cluster]# cp -rp 7001 7003

[root@redis redis_cluster]# vim 7002/redis.conf          #修改端口爲7002 
[root@redis redis_cluster]# vim 7003/redis.conf
將配置文件目錄拷貝到192.168.126.161上
[root@redis redis_cluster]# scp -rp 7001 192.168.126.161:/usr/local/redis/redis_cluster/

修改配置文件(端口號和ip)
[root@centosm redis_cluster]# ls
7004  7005  7006

3. 啓動 redis,可以使用腳本啓動

[root@redis redis_cluster]# ls
7001  7002  7003  start.sh
[root@redis redis_cluster]# cat start.sh     #另一臺機器相同操作
cd 7001
redis-server redis.conf
cd ../7002
redis-server redis.conf
cd ../7003
redis-server redis.conf
#192.168.126.162
[root@redis redis_cluster]# ps -ef |grep redis
root       1757      1  2 12:36 ?        00:00:00 redis-server 192.168.126.162:7001 [cluster]
root       1762      1  1 12:36 ?        00:00:00 redis-server 192.168.126.162:7002 [cluster]
root       1767      1  1 12:36 ?        00:00:00 redis-server 192.168.126.162:7003 [cluster]


#192.168.126.161
[root@centosm redis_cluster]# ps -ef |grep redis
root      11906      1  0 23:07 ?        00:00:00 redis-server 192.168.126.161:7004 [cluster]
root      11911      1  0 23:07 ?        00:00:00 redis-server 192.168.126.161:7005 [cluster]
root      11913      1  0 23:07 ?        00:00:00 redis-server 192.168.126.161:7006 [cluster]

4. 開始創建集羣

搭建集羣的話,如果 redis 版本小於 5.0 就需要使用一個工具 redis-trib(腳本文件),這個工具在 redis 解壓文件的源代碼裏。因爲這個工具是一個 ruby 腳本文件,所以這個工具的運行需要 ruby 的運行環境,所以需要安裝 ruby

yum install ruby -y

yum install rubygems -y

gem install redis

當前 redis 版本大於 5.0,所以不用 ruby,可以直接創建。

redis-cli --cluster create 192.168.126.162:7001 192.168.126.162:7002 192.168.126.162:7003 192.168.126.161:7004 192.168.126.161:7005 192.168.126.161:7006 --cluster-replicas 1

–cluster-replicas 1:主從比例爲 1:1

[root@redis redis_cluster]# redis-cli --cluster create 192.168.126.162:7001 192.168.126.162:7002 192.168.126.162:7003 192.168.126.161:7004 192.168.126.161:7005 192.168.126.161:7006 --cluster-replicas 1
>>> Performing hash slots allocation on 6 nodes...      #對6個節點進行哈希槽位分配,實際分配三個主節點即可。
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 192.168.126.161:7006 to 192.168.126.162:7001  #三個主節點7001 7004 7002
Adding replica 192.168.126.162:7003 to 192.168.126.161:7004   #三個從節點7006 7005 7003
Adding replica 192.168.126.161:7005 to 192.168.126.162:7002
M: fb89e991f2fca476964195f496428c0de3e57f76 192.168.126.162:7001
   slots:[0-5460] (5461 slots) master
M: 54788eed17c99719f0d9e49b4933f8fc6e900cd9 192.168.126.162:7002
   slots:[10923-16383] (5461 slots) master
S: 0d4d849e80a4f12e546fa3df7fcec42cb65951b2 192.168.126.162:7003
   replicates 4fbffafb9088e65f60526147f4bff5260ea897f0
M: 4fbffafb9088e65f60526147f4bff5260ea897f0 192.168.126.161:7004
   slots:[5461-10922] (5462 slots) master
S: 6f44fa89577fd53ff8d703390e3908b7db5cb88c 192.168.126.161:7005
   replicates 54788eed17c99719f0d9e49b4933f8fc6e900cd9
S: 3f224e631bffba6d3978412df83c11b9d53f5799 192.168.126.161:7006
   replicates fb89e991f2fca476964195f496428c0de3e57f76
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.126.162:7001)
M: fb89e991f2fca476964195f496428c0de3e57f76 192.168.126.162:7001
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: 0d4d849e80a4f12e546fa3df7fcec42cb65951b2 192.168.126.162:7003
   slots: (0 slots) slave
   replicates 4fbffafb9088e65f60526147f4bff5260ea897f0
M: 54788eed17c99719f0d9e49b4933f8fc6e900cd9 192.168.126.162:7002
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: 6f44fa89577fd53ff8d703390e3908b7db5cb88c 192.168.126.161:7005
   slots: (0 slots) slave
   replicates 54788eed17c99719f0d9e49b4933f8fc6e900cd9
S: 3f224e631bffba6d3978412df83c11b9d53f5799 192.168.126.161:7006
   slots: (0 slots) slave
   replicates fb89e991f2fca476964195f496428c0de3e57f76
M: 4fbffafb9088e65f60526147f4bff5260ea897f0 192.168.126.161:7004
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
[OK] All nodes agree about slots configuration.   #所有節點同意分配hash槽
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.        #分配完畢,創建完成

最後集羣主從對應關係

可以看出主從節點在兩個節點隨機分配,且一對對應主從服務不會分配到同一臺機器上。即使一臺機器損壞,也不會影響 redis 繼續提供服務。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/SCCgm0nmFTCe0vge5s-B_g