2022年Java架構開發框架Redis之sentinel和集群

fans news 發佈 2022-01-10T11:52:22+00:00

一. redis高可用方案–sentinel(哨兵模式)當我們搭建好redis主從複製方案後會發現一個問題,那就是當主伺服器宕機後,需要手動把一台從伺服器切換為主伺服器,這就需要人工干預,費事費力,java培訓同時在手動切過程中也會導致redis伺服器寫入功能不可用。

一. Redis高可用方案–Sentinel(哨兵模式)

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

哨兵模式簡介:

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

sentinel工作過程:

  • 通過向主伺服器和從伺服器發送ping命令,讓伺服器返回運行狀態。
  • 當哨兵監測到master宕機,會自動將一個slave切換成master,然後通過發布訂閱模式通知其他的從伺服器,修改配置文件,讓它們切換主機。

關於sentinel的三個定時任務:

  • 每1秒每個sentinel對其他sentinel和redis節點執行ping操作,心跳檢測。
  • 每10秒每個sentinel會對master和slave執行info命令,目的是發現slave結點,確定主從關係。
  • 每2秒每個sentinel通過master節點的channel交換信息(pub/sub)。master節點上有一個發布訂閱的頻道(sentinel:hello)。sentinel節點通過__sentinel__:hello頻道進行信息交換(對節點的"看法"和自身的信息),達成共識.

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。遵照的原則如下:

  • slave的優先級
  • slave從master那同步的數據量,那個slave多就優先。

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
複製代碼
  • name :redis主服務名稱,可以自行命名,但是在一個sentinel網絡中,一個redis主服務只能有一個名稱;
  • ip和port :redis主服務的IP位址和埠號.
  • quorum :表示要將這個主伺服器判斷為失效並下線至少需要2個sentinel同意
  • protected-mode :關閉保護模式(默認情況下,redis node和sentinel的protected-mode都是yes,在搭建集群時,若想從遠程連接redis集群,需要將redis node和sentinel的protected-mode修改為no,若只修改redis node,從遠程連接sentinel後,依然是無法正常使用的,且sentinel的配置文件中沒有protected-mode配置項,需要手工添加。依據redis文檔的說明,若protected-mode設置為no後,需要增加密碼證或是IP限制等保護機制,否則是極度危險的。)

啟動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節點彼此互聯(PING-PONG機制),內部使用二進位協議優化傳輸速度和帶寬。
  • 節點的失效是通過集群中超過半數的節點檢測失效時才生效。
  • 集群是一個整體,客戶端與redis節點直連,不需要中間proxy層.客戶端不需要連接集群所有節點,連接集群中任何一個可用節點即可。
  • Redis集群預分好16384個桶,當需要在 Redis 集群中放置一個 key-value 時,根據 CRC16(key) mod 16384的值,決定將一個key放到哪個桶中。

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

節點分配:

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

  • 節點1:0-5460;
  • 節點2:5461-10922;
  • 節點3:10923-16383.

若存入一個值,按照哈希槽算法得到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繼續提供服務。





關鍵字: