redis哨兵故障轉移及實現

在上篇文章中docker-compose搭建redis-sentinel成功的搭建了1主2從3哨兵。

Sentinel命令

sentinel是一個特殊的redis節(jié)點,它有自己專屬的api

  • sentinel masters 顯示被監(jiān)控的所有master以及它們的狀態(tài)。
  • sentinel master <master name> 顯示指定master的信息和狀態(tài)。
  • sentinel slaves <master name> 顯示指定master的所有slave及它們的狀態(tài)。
  • sentinel sentinels <master name> 顯示指定mastersentinel節(jié)點集合(不包含當前節(jié)點)。
  • sentinel get-master-addr-by-name <master name> 返回指定masteripport,如果正在進行failover或者failover已經完成,將會顯示被提升為masterslaveipport。
  • sentinel failover <master name>強制sentinel執(zhí)行failover,并且不需要得到其它sentinel的同意。但是failover后會將最新的配置發(fā)送給其它sentinel

sentinel masters

展示所有被監(jiān)控的主節(jié)點狀態(tài)及相關信息:

127.0.0.1:26380> sentinel masters
1)  1) "name"
    2) "mymaster"
    3) "ip"
    4) "192.168.3.2"
    5) "port"
    6) "6379"
…………………………………………………………

sentinel master <master name>

展示指定<master name>狀態(tài)以及相關的信息:

127.0.0.1:26380> sentinel master mymaster
 1) "name"
 2) "mymaster"
 3) "ip"
 4) "192.168.3.2"
 5) "port"
 6) "6379"
 ………………………………

sentinel slaves <master name>

展示指定 <master name>的從節(jié)點狀態(tài)以及相關的統(tǒng)計信息:

127.0.0.1:26380> sentinel slaves mymaster
1)  1) "name"
    2) "192.168.3.4:6379"
    3) "ip"
    4) "192.168.3.4"
    5) "port"
    6) "6379"
…………………………………………
2)  1) "name"
    2) "192.168.3.3:6379"
    3) "ip"
    4) "192.168.3.3"
    5) "port"
    6) "6379"
…………………………………………

sentinel sentinels <master name>

展示指定 <master name>sentinel節(jié)點集合(不包含當前sentinel節(jié)點):

127.0.0.1:26380> sentinel sentinels mymaster
1)  1) "name"
    2) "570de1d8085ec8bd7974431c01c589847c857edf"
    3) "ip"
    4) "192.168.3.13"
    5) "port"
    6) "26379"
………………………………………………

sentinel get-master-addr-by-name <master name>

獲取主節(jié)點信息:

127.0.0.1:26380> sentinel get-master-addr-by-name mymaster
1) "192.168.3.2"
2) "6379"

sentinel failover <master name>

<master name>進行強制故障轉移:

127.0.0.1:26380> sentinel failover mymaster
OK
127.0.0.1:26380> info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=192.168.3.3:6379,slaves=2,sentinels=3

修改配置:

  • 添加新的監(jiān)聽:sentinel monitor test 127.0.0.1 6379 2
  • 放棄對某個master監(jiān)聽:sentinel REMOVE test
  • 設置配置選項:sentinel set failover-timeout mymaster 180000

Master可能會因為某些情況宕機了,如果客戶端是固定一個地址去訪問,肯定是不合理的,所以客戶端請求是請求哨兵,從哨兵獲取主機地址的信息,或者是從機的信息。可以實現一個例子:

  • 隨機選擇一個哨兵連接,獲取主機及從機信息。
  • 模擬客戶端定時訪問,實現簡單輪詢效果,輪詢從節(jié)點。
  • 連接失敗重試訪問

Sentinel故障轉移

執(zhí)行docker-composer up之后sentinel.conf發(fā)生了變化,每個配置文件變化如下:

sentinel\conf\sentinel.conf

user default on nopass ~* +@all
sentinel known-replica mymaster 192.168.3.3 6379
sentinel known-replica mymaster 192.168.3.4 6379
sentinel known-sentinel mymaster 192.168.3.12 26379 497f733919cb5d41651b4a2b5648c4adffae0a73
sentinel known-sentinel mymaster 192.168.3.13 26379 0d0ee41bcb5d765e9ff78ed59de66be049a23a82
sentinel current-epoch 0

sentine2\conf\sentinel.conf

user default on nopass ~* +@all
sentinel known-replica mymaster 192.168.3.3 6379
sentinel known-replica mymaster 192.168.3.4 6379
sentinel known-sentinel mymaster 192.168.3.13 26379 0d0ee41bcb5d765e9ff78ed59de66be049a23a82
sentinel known-sentinel mymaster 192.168.3.11 26379 f5f2a73dc0e60514e4f28c6f40517f48fa409eed
sentinel current-epoch 0

sentine3\conf\sentinel.conf

user default on nopass ~* +@all
sentinel known-replica mymaster 192.168.3.3 6379
sentinel known-replica mymaster 192.168.3.4 6379
sentinel known-sentinel mymaster 192.168.3.12 26379 497f733919cb5d41651b4a2b5648c4adffae0a73
sentinel known-sentinel mymaster 192.168.3.11 26379 f5f2a73dc0e60514e4f28c6f40517f48fa409eed
sentinel current-epoch 0

從變化中可以看出每臺Sentinel分別記錄了slave的節(jié)點信息和其它Sentinel節(jié)點信息。

在宿主機中隨便進入一臺Sentinel

127.0.0.1:26380> sentinel masters
1)  1) "name"
    2) "mymaster"
    3) "ip"
    4) "192.168.3.2"
    5) "port"
    6) "6379"

可以觀察到監(jiān)聽的所有master,將192.168.3.2這臺master進行宕機

docker stop redis-master

宕機完之后等待Sentinel檢測周期過了之后再對sentinel.confredis.conf進行觀察。

3臺Sentinelsentinel monitor mymaster 192.168.3.2 6379 2變成了sentinel monitor mymaster 192.168.3.4 6379 2

其次master對應的slave節(jié)點信息也進行更改。

192.168.3.3redis.confreplicaof 192.168.3.2 6379也變成了replicaof 192.168.3.4 6379。

192.168.3.2redis.confreplicaof 192.168.3.2 6379這行配置被刪除掉了。

再次啟動192.168.3.2redis節(jié)點,而這臺節(jié)點的redis.conf中增加了一行replicaof 192.168.3.4 6379

其實就是將我們的操作自動化了。

Sentinel實現原理

Sentinel的實現原理,主要分為三個步驟:

  • 檢測問題:三個定時任務,這三個內部的執(zhí)行任務可以保證出現問題馬上讓Sentinel知道。
  • 發(fā)現問題:主觀下線和客觀下線,當有一臺Sentinel機器發(fā)現問題時,它就會對它主觀下線。但是當多個Sentinel都發(fā)現問題的時候,才會出現客觀下線。
  • 找到解決問題的Sentinel:進行領導者選舉,如何在Sentinel內部多臺節(jié)點做領導者選擇。
  • 解決問題:就是要進行故障轉移。

三個定時任務

  • 每10s每個SentinelMasterSlave執(zhí)行一次Info Replication。

    Redis Sentinel可以對Redis節(jié)點做失敗判斷和故障轉移,來Info Replication發(fā)現Slave節(jié)點,來確定主從關系。

  • 每2s每個Sentinel通過Master節(jié)點的channel交換信息(pub/sub)。

    類似于發(fā)布訂閱,Sentinel會對主從關系進行判斷,通過__sentinel__:hello頻道交互。了解主從關系可以幫助更好的自動化操作Redis。然后Sentinel會告知系統(tǒng)消息給其它Sentinel節(jié)點,最終達到共識,同時Sentinel節(jié)點能夠互相感知到對方。

  • 每1s每個Sentinel對其它SentinelRedis執(zhí)行ping

    對每個節(jié)點和其它Sentinel進行心跳檢測,它是失敗判斷的依據。

主觀下線和客觀下線

回顧上一篇文章中Sentinel的配置。

sentinel monitor mymaster 192.168.3.2 6379 2
sentinel down-after-millseconds mymaster 30000

主觀下線:每個Sentinel節(jié)點對Redis失敗的“偏見”。之所以是偏見,只是因為某一臺機器30s內沒有得到回復。

客觀下線:這個時候需要所以Sentinel節(jié)點都發(fā)現它30s內無回復,才會達到共識。

領導者選舉方式

  • 每個做主觀下線的Sentinel節(jié)點,會像其它的Sentinel節(jié)點發(fā)送命令,要求將它設置成為領導者。
  • 收到命令的Sentinel節(jié)點,如果沒有同意通過其它節(jié)點發(fā)送的命令,那么就會同意請求,否則就會拒絕。
  • 如果Sentinel節(jié)點發(fā)現自己的票數超過半數,同時也超過了sentinel monitor mymaster 192.168.3.2 6379 2超過2個的時候,就會成為領導者。
  • 進行故障轉移操作。

如何選擇“合適”的Slave節(jié)點

? Redis內部其實是有一個優(yōu)先級配置的,在配置文件中replica-priority,這個參數是slave節(jié)點的優(yōu)先級配置,如果存在則返回,如果不存在則繼續(xù)。當上面這個優(yōu)先級不滿足的時候,Redis還會選擇復制偏移量最大的Slave節(jié)點,如果存在則返回,如果不存在則繼續(xù)。之所以選擇偏移量最大,這是因為偏移量越小,和Master的數據越不接近,現在Master掛掉了,說明這個偏移量小的機器數據可能存在問題,這就是為什么選擇偏移量最大的Slave的原因。如果發(fā)現偏移量都一樣,這個時候 Redis 會默認選擇 runid 最小的節(jié)點。

生產環(huán)境部署技巧:

  • Sentinel節(jié)點不應該部署在一臺物理機器上。

    這里特意強調物理機是因為一臺物理機做成了若干虛擬機或者現今比較流行的容器,它們雖然有不同的IP地址,但實際上它們都是同一臺物理機,同一臺物理機意味著如果這臺機器有什么硬件故障,所有的虛擬機都會受到影響,為了實現Sentinel節(jié)點集合真正的高可用,請勿將Sentinel節(jié)點部署在同一臺物理機器上。

  • 部署至少三個且奇數個的Sentinel節(jié)點。通過增加Sentinel節(jié)點的個數提高對于故障判定的準確性,因為領導者選舉需要至少一半加1個節(jié)點。

Sentinel常見問題

哨兵集群在發(fā)現master node掛掉后會進行故障轉移,也就是啟動其中一個slave nodemaster node。在這過程中,可能會導致數據丟失的情況。

  • 異步復制導致數據丟失

    因為master->slave的復制是異步,所以有可能部分還沒來得及復制到slave就宕機了,此時這些部分數據就丟失了。

  • 集群腦裂導致數據丟失

    腦裂,也就是說。某個master所在機器突然脫離了正常的網絡,跟其它slave機器不能連接,但是實際上master還運行著。

造成的問題:

? 此時哨兵可能就會認為master宕機了,然后開始選舉,將其它slave切換成master。這時候集群里就會有2個master,也就是所謂的腦裂。此時雖然某個slave被切換成master,但是可能client還沒來得及切換成新的master,還繼續(xù)寫向舊的master的數據可能就丟失了。因此舊master再次被恢復的時候,會被作為一個slave掛到新的master上去,自己的數據會被清空,重新從新的master復制數據。

怎么解決:

min-slaves-to-write 1
min-slaves-max-lag 10

要求至少有一個slave,數據復制和同步的延遲不能超過10s。

如果說一旦所有的slave,數據復制和同步的延遲都超過了10s,這個時候,master就不會再接收任何請求了。

上面兩個配置可以減少異步復制和腦裂導致的數據丟失。

異步復制導致的數據丟失:

? 在異步復制的過程當中,通過min-slaves-max-lag這個配置,就可以確保的說,一旦slave復制數據和ack延遲時間太長,就認為可能master宕機后損失的數據太多了,那么就拒絕寫請求,這樣就可以把master宕機時由于部分數據未同步到slave導致的數據丟失降低到可控范圍內。

集群腦裂導致的數據丟失:

? 集群腦裂因為client還沒來得及切換成新的master,還繼續(xù)寫向舊的master的數據可能就丟失了通過min-slaves-to-write確保必須是有多少個從節(jié)點連接,并且延遲時間小于min-slaves-max-lag多少秒。

客戶端需要怎么做:

? 對于client來講,就需要做些處理,比如先將數據緩存到內存當中,然后過一段時間處理,或者連接失敗,接收到錯誤切換新的master處理。

?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容