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

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

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

哨兵模式簡介:

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

324186f22e73fb17c8e79adc69515b91.png
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網絡,互相通信並交換彼此關於被監視服務器信息。

ee7a9e89e47435aadf7bfd6e768f1a06.png
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.故障的主服務器修復後將成爲從服務器繼續工作。

故障發生

673026323ca857470eec7378a2d920ec.png

故障切換

e01bac333275eba2836f317d5b5c8264.png

Master重新上線後

7195055effe6a0713ac4b4a9bbfeb042.png
哨兵模式配置

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

6a6bc828eb005bf5b9d9c9fe02d8fef7.png

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切換爲主節點。

ed42dd22abfe6d9c08ede9550fac5ec5.png

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

f7e49410f1fc0db0cb9f793d80f89fad.png

最後查看一下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集羣採用無中心結構,每個節點保存數據和整個集羣狀態,每個節點都和其他所有節點連接。

faa5532ea8517a70a5ac0aafd54b798f.png

特點:

  • 所有的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個實例兩兩對應主從。

09edf9eeb7336fa624a326cc087f494f.png 32b65b455c2e38fda839de4ae14ec143.png

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.        #分配完畢,創建完成

最後集羣主從對應關係

25252cc72379b88b17a9bf4f96a0a028.png

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

來源:blog.csdn.net/wdwangye/article/details/113084351

ab80540bde55444773b477ba3b78a80a.png

閒魚:Thread.sleep(0) 到底有什麼用?我:有點懵~


2511073239924658da9a083acfc5ecca.png

SpringBoot 一個接口同時支持 form 表單、form-data、json 的優雅寫法


bb2e424cc79ba627e1e64e73f738ffef.png

SQL開發中爲什麼要儘量避免使用 IN 和 NOT IN 呢?


b5a9c6376aba65a444cf622fbe116d88.png

比 Xshell 還好用的 SSH 客戶端神器!


6a8118dd5e11137567d1516730558cb6.png

本文同步分享在 博客“獨行俠夢”(CSDN)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章