redis緩存架構詳解(七)- 實現 redis 主從架構高可用-redis哨兵架構詳解

接上篇文章,使用redis sentinel cluster 實現redis replication高可用,接下來詳細講解redis哨兵集羣,本節內容較多,全是乾貨!

4.7. redis 哨兵架構講解

4.7.1. 認識 Sentinel

sentinel,中文名是哨兵,目前採用的是sentinel 2版本,sentinel 2相對於sentinel 1,重寫了很多代碼,主要是讓故障轉移的機制和算法變得更加健壯和簡單。

在深入講解Sentinel之前,我們先認識Sentinel的配置,對 其中的配置項先有個大概認識,方便對Sentinel原理的深入剖析。

在redis存放配置文件處,創建一個sentinel.conf配置文件,sentinel 默認端口26379,所以我們的配置文件可以取名爲: sentinel-26379.conf 配置文件,文件內容如下:
port 26379
daemonize yes
logfile "26379.log"
dir "./"
sentinel monitor mymaster 192.168.250.132 7000 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 15000
sentinel auth-pass mymaster 123
bind 192.168.250.132 127.0.0.1

主要配置項解釋:

序號 配置項 解釋
1 sentinel monitor 告訴sentinel去監聽地址爲ip:port的一個master,這裏的master-name可以自定義,quorum是一個數字,指明當有多少個sentinel認爲一個master失效時,master纔算真正失效。
2 sentinel auth-pass 設置連接master和slave時的密碼,注意的是sentinel不能分別爲master和slave設置不同的密碼,因此master和slave的密碼應該設置相同。
3 sentinel down-after-milliseconds 這個配置項指定了需要多少失效時間,一個master纔會被這個sentinel主觀地認爲是不可用的。 單位是毫秒,默認爲30秒。
4 sentinel parallel-syncs 這個配置項指定了在發生failover主備切換時,最多可以有多少個slave同時對新的master進行 同步,這個數字越小,完成failover所需的時間就越長,但是如果這個數字越大,就意味着越 多的slave因爲replication而不可用。可以通過將這個值設爲 1 來保證每次只有一個slave 處於不能處理命令請求的狀態。
5 sentinel failover-timeout failover-timeout 可以用在以下這些方面:
1. 同一個sentinel對同一個master兩次failover之間的間隔時間。
2. 當一個slave從一個錯誤的master那裏同步數據開始計算時間。直到slave被糾正爲向正確的master那裏同步數據時。
3.當想要取消一個正在進行的failover所需要的時間。
4.當進行failover時,配置所有slaves指向新的master所需的最大時間。不過,即使過了這個超時,slaves依然會被正確配置爲指向master,但是就不按parallel-syncs所配置的規則來了。

4.7.2. 哨兵sentinel的核心原理

4.7.2.1. 哨兵sentinel的核心原理

在這裏插入圖片描述

哨兵sentinel的核心原理

哨兵是redis集羣架構中非常重要的一個組件,主要原理如下:

(1)哨兵本身是一個分佈式集羣,相互之間協同工作;

(2)集羣監控:負責監控redis master和slave進程是否正常工作;
(3)消息通知:如果某個redis實例有故障,那麼哨兵負責發送消息通知管理員;
(4)故障轉移:如果master node掛掉了,各個哨兵自動轉移到slave node上,選舉一個新的master,並進行故障轉移(主備切換);
(5)配置中心:如果故障轉移發生了,通知client客戶端新的master地址。

注意事項:

(1)故障轉移時,判斷一個master node是否宕機了,需要大部分的哨兵都認同master node宕機纔是真的宕機,這涉及到了分佈式選舉的問題。
(2)即使部分哨兵節點掛掉了,哨兵集羣也能正常工作。

(3)哨兵至少需要3個實例,來保證自己的健壯性。
(4)sentinel + redis replication 架構,是不會保證數據零丟失的,只能保證redis集羣的高可用性。
(5)sentinel + redis replication 架構,儘量在測試環境和生產環境,都進行充足的測試和演練。

4.7.2.2. Sentinel監控master整個過程

每個 `Sentinel` 節點都需要 **定期執行** 以下任務。
4.7.2.2.1. Sentinel向所知的master、slave發送PING命令
每個 `Sentinel` 以 每 `10` 秒一次的頻率,向它所知的 **主服務器**、**從服務器** 以及其他 `Sentinel` **實例** 發送一個 `PING` 命令。

在這裏插入圖片描述

4.7.2.2.2. master轉變爲主觀下線sdown
如果一個哨兵ping一個master,超過了down-after-milliseconds指定的毫秒數之後,那麼這個哨兵就主觀認爲master宕機,此時master處於sdown狀態。

在這裏插入圖片描述

當Sentinel Follow1或Sentinel Follow2 ping master超過down-after-milliseconds指定的毫秒數之後,就認爲master處於 **主觀下線 **,即 **sdown **。
4.7.2.2.3. Sentinel每秒一次的頻率確認master是否進入了 主觀下線狀態
如果一個 **master ** 被標記爲 **主觀下線**,那麼正在 **監視** 這個 **主服務器** 的所有 `Sentinel` 節點,要以 **每秒一次** 的頻率確認 **master** 的確進入了 **主觀下線** 狀態。

在這裏插入圖片描述

Sentinel Leader ping master的頻率編程1秒一次。
4.7.2.2.4. master轉變爲客觀下線odown
如果一個 master 被標記爲 **主觀下線**,並且有 **足夠數量** 的 `Sentinel`(大於等於quorum指定的數量)在指定的 **時間範圍** 內同意這一判斷,那麼這個 **master** 被標記爲 **客觀下線**,即**odown**。

在這裏插入圖片描述

哨兵之間的自動發現機制

這裏會涉及到sentinel之間的自動發現機制,哨兵互相之間發現的實現原理:是通過redis的pub/sub系統實現的。

1、每隔兩秒鐘,每個哨兵都會往自己監控的某個master+slaves對應的__sentinel__:hello channel裏發送一個消息,內容是自己的host、ip和runid還有對這個master的監控配置。

2、每個哨兵也會去監聽自己監控的每個master+slaves對應的__sentinel__:hello channel,然後去感知到同樣在監聽這個master+slaves的其他哨兵的存在。

3、每個哨兵還會跟其他哨兵交換對master的監控配置,互相進行監控配置的同步。

4.7.2.2.5. Sentinel向所有slave每秒一次發送INFO命令
當一個 **master** 被 `Sentinel` 標記爲 **客觀下線** 時,`Sentinel` 向所有 **從服務器 slave** 發送  `INFO` 命令的頻率,會從`10秒一次改爲每秒一次`。

在這裏插入圖片描述

4.7.2.2.6. 選舉主節點master,進行主備切換
選取主節點:`Sentinel` 和其他 `Sentinel` 協商 **master** 的狀態,如果 **master** 處於 `SDOWN` 狀態,則投票自動選出新的 **主節點 master**。將剩餘的 **從節點slave** 指向 **新的主節點** ,並進行 **數據複製**。

在這裏插入圖片描述

這個過程會涉及到slave配置的自動糾正,以及slave被選舉爲master的算法。  	

1、slave配置的自動糾正

哨兵會負責自動糾正slave的一些配置,比如slave如果要成爲潛在的master候選人,哨兵會確保slave複製現有master的數據。如果slave連接到了一個錯誤的master上(故障轉移之後,連接到舊的master上),那麼哨兵會確保它們連接到正確的master上。

2、slave->master選舉算法

如果一個master被認爲odown了,而且majority哨兵都允許了主備切換,那麼某個哨兵就會執行主備切換操作,此時首先要選舉一個slave,選舉slave通過以下信息進程選舉。

(1)Sentinel集羣選舉Leader
如果需要從redis集羣選舉一個節點爲主節點,首先需要從Sentinel集羣中選舉一個Sentinel節點作爲Leader。

每一個Sentinel節點都可以成爲Leader,當一個Sentinel節點確認redis集羣的主節點主觀下線後,會請求其他Sentinel節點要求將自己選舉爲Leader。被請求的Sentinel節點如果沒有同意過其他Sentinel節點的選舉請求,則同意該請求(選舉票數+1),否則不同意。

如果一個Sentinel節點獲得的選舉票數達到Leader最低票數(quorum和Sentinel節點數/2+1的最大值),則該Sentinel節點選舉爲Leader;否則重新進行選舉。

在這裏插入圖片描述

(2)Sentinel Leader決定新主節點

當Sentinel集羣選舉出Sentinel Leader後,由Sentinel Leader從redis從節點中選擇一個redis節點作爲主節點,選舉過程如下:

在這裏插入圖片描述

(1)跟master斷開連接的時長

如果一個slave跟master斷開連接已經超過了down-after-milliseconds的10倍,外加master宕機的時長,那麼slave就被認爲不適合選舉爲master。

(down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state

(2)對slave進行排序,排序方法如下:

  • slave priority:選擇優先級slave-priority最大的從節點作爲主節點,如不存在則繼續。 按照slave優先級進行排序,slave priority越低,優先級就越高。
  • replica offset:選擇複製偏移量(數據寫入量的字節,記錄寫了多少數據。主服務器會把偏移量同步給從服務器,當主從的偏移量一致,則數據是完全同步)最大的從節點作爲主節點,如不存在則繼續。如果slave priority相同,那麼看replica offset,哪個slave複製了越多的數據,offset越靠後,優先級就越高。
  • run id:如果上面兩個條件都相同,那麼選擇一個run id比較小的那個slave。(redis每次啓動的時候生成隨機的runid作爲redis的標識)

3、quorum和majority

quorum:quorum數量的哨兵認爲master odown了,這個master才真正的odown。

majority:選舉出一個哨兵切換爲master,只有得到majority個哨兵的授權,才能正式執行切換。

quorum和majority的關係:

1、如果quorum < majority,比如5個哨兵,majority就是3,quorum設置爲2,那麼就3個哨兵授權就可以執行切換

2、但是如果quorum >= majority,那麼必須quorum數量的哨兵都授權,比如5個哨兵,quorum是5,那麼必須5個哨兵都同意授權,才能執行切換。

4、configuration epoch

哨兵會對一套redis master+slave進行監控,有相應的監控配置。

執行切換的那個哨兵,會從要切換到的新master(salve->master)那裏得到一個configuration epoch,這就是一個version號,每次切換的version號都必須是唯一的。

如果第一個選舉出的哨兵切換失敗了,那麼其他哨兵,會等待failover-timeout時間,然後接替繼續執行切換,此時會重新獲取一個新的configuration epoch,作爲新的version號。

5、configuration傳播

哨兵完成切換之後,會在自己本地更新生成最新的master配置,然後同步給其他的哨兵,就是通過之前說的pub/sub消息機制。

這裏之前的version號就很重要了,因爲各種消息都是通過一個channel去發佈和監聽的,所以一個哨兵完成一次新的切換之後,新的master配置是跟着新的version號的。

其他的哨兵都是根據版本號的大小來更新自己的master配置的。

4.7.2.2.7. 移除主服務器的客觀下線
移除主服務器的客觀下線。當沒有足夠數量的 `Sentinel` 同意 **master** 下線時, **master** 的 **客觀下線狀態** 就會被移除。

在這裏插入圖片描述

4.7.2.2.8. 移除主服務器的主觀下線
移除主服務器的主觀下線。當 **master** 重新向 `Sentinel` 的 `PING` 命令返回 **有效回覆** 時,**主服務器** 的 **主觀下線狀態** 就會被移除。

在這裏插入圖片描述

4.7.3. 兩種數據丟失的情況

主備切換的過程,可能會導致數據丟失,數據丟失主要有兩種情況:

4.7.3.1. 異步複製導致的數據丟失

因爲master -> slave的複製是異步的,所以可能有部分數據還沒複製到slave,master就宕機了,此時這些部分數據就丟失了

4.7.3.2. 腦裂導致的數據丟失

在這裏插入圖片描述

  	1、如上圖所示,master所在機器突然脫離了正常的網絡或其他原因,導致其他slave以及sentinel不能連接,但是實際上master還運行着。
  	
  	2、此時哨兵可能認爲master宕機了,然後開啓選舉,將其他slave切換成了master。這個時候,集羣裏就會有兩個master,也就是所謂的腦裂。
  	
  	3、此時雖然某個slave被切換成了master,但是可能client還沒來得及切換到新的master,還繼續寫向舊的master。
  	
  	4、當舊master再次恢復的時候,會被作爲一個slave掛到新的master上去,自己的數據會清空,重新從新的master複製數據,這時寫入舊的master數據就丟失了。

4.7.3.3.數據丟失解決方案

解決異步複製和腦裂導致的數據丟失。

在redis.conf配置中配置以下兩個屬性:

在這裏插入圖片描述

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

意義:要求至少有1個slave,數據複製和同步的延遲不能超過10秒

如果所有的slave數據複製和同步的延遲都超過了10秒鐘,master就不會再接收任何請求。

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

配置 這兩個參數後,一旦slave從master複製數據和ack延時太長,不能繼續給指定數量的slave發送數據,就直接拒絕客戶端的寫請求,這樣腦裂後的舊master就不會接受client的新數據,也就避免了數據丟失,這樣就可以把master宕機時由於部分數據未同步到slave導致的數據丟失降低到可控範圍內。

因此在腦裂和異步複製的場景下,最多就丟失10秒的數據。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章