1. 程式人生 > 其它 >Redis 高可用篇:你管這叫 Sentinel 哨兵叢集原理

Redis 高可用篇:你管這叫 Sentinel 哨兵叢集原理

概要

我們知道「主從複製是高可用的基石」,從庫宕機依然可以將請求傳送給主庫或者其他從庫,但是 Master 宕機,只能響應讀操作,寫請求無法再執行。

所以主從複製架構面臨一個嚴峻問題,主庫掛了,無法執行「寫操作」,無法自動選擇一個 Slave 切換為 Master,也就是無法故障自動切換

深夜與女朋友麼麼噠……(此處省略 10000 字),突然宕機,總不能提起褲子從床上爬起來手工進行主從切換,再通知其他程式設計師把地址重新改成新主庫上線

如此一折騰自己已被女友切換成前男友了,萬萬使不得。所以我們必須有一個高可用的方案,為此,Redis 官方提供一個高可用方案——哨兵(Sentinel)

開篇寄語

技術的迭代非常的快,但是從技術中沉澱下來的思維卻是受益終生的。所以不要擔心什麼中年危機,那些擔心中年危機的人通常很難成長起來。只要我們成長,只要我們的認知在不斷突破,就不用擔心中年危機,這個世界始終是需要那些優秀人才的。

什麼是哨兵(Sentinel)

65 哥:碼哥,雖然我沒女朋友,但是,未雨綢繆我要掌握這個哨兵模式,防止當深夜與女朋友麼麼噠被打擾,你快說說哨兵的實現原理吧。

搭建例項採用三個哨兵形成叢集,三個資料節點(一主兩從)方式搭建,如下圖所示:

哨兵叢集的搭建演示就不在這裡贅述了,需要的讀者朋友可點選左下角的「閱讀原文」檢視。

65 哥你聽過「武當派」創始人張三瘋麼?Redis 主從架構就好比一個武當,掌門人就是 Master。掌門人如果掛了,需要從武當七俠裡面選舉能人擔當掌門人。這就需要一個部門

能監控掌門人的生死和武當其他弟子的生命狀態,並且能夠通過投票從武當弟子中選舉一個能者擔任新掌門,接著再舉行新聞釋出會向世界宣佈新掌門的資訊。這個「部門」就是哨兵。

哨兵在選舉新掌門會遇到以下幾個問題:

  1. 如何判斷掌門真的掛了,有可能假死;
  2. 到底選擇哪一個武當子弟作為新掌門?
  3. 通過新聞釋出會將新掌門的相關資訊通知到所有武當弟子(slave 和 master)和整個武林(客戶端)

哨兵部門主要負責的任務是:監控整個武當、選擇新掌門,通知整個武當和整個武林。

哨兵機制的主要任務

哨兵是 Redis 的一種執行模式,它專注於對 Redis 例項(主節點、從節點)執行狀態的監控,並能夠在主節點發生故障時通過一系列的機制實現選主及主從切換,實現故障轉移,確保整個 Redis 系統的可用性

。結合 Redis 的 官方文件,可以知道 Redis 哨兵具備的能力有如下幾個:

  • 監控:持續監控 master 、slave 是否處於預期工作狀態。
  • 自動切換主庫:當 Master 執行故障,哨兵啟動自動故障恢復流程:從 slave 中選擇一臺作為新 master。
  • 通知:讓 slave 執行 replicaof ,與新的 master 同步;並且通知客戶端與新 master 建立連線。

哨兵也是一個 Redis 程序,只是不對外提供讀寫服務,通常哨兵要配置成單數,為啥呢?且聽「碼哥位元組」慢慢分析。

65 哥:那到底「哨兵」這個神祕部門是如何實現這三個能力的?

我們先從全域性觀看哨兵,簡要的瞭解整個運作流程,接著再針對每一個任務詳細分析。首先從監控開始…...

監控

Sentinel 只是武當弟子中的特殊部門,在預設情況下,Sentinel 通過飛鴿傳書以每秒一次的頻率向所有武當弟子、掌門與哨兵(包括 Master、Slave、其他 Sentinel 在內)傳送 PING 命令,如果 slave 沒有在在規定時間內響應「哨兵」的 PING 命令,「哨兵」就認為這哥們可能嗝屁了,就會將他記錄為「下線狀態」;

假如 master 掌門沒有在規定時間響應 「哨兵」的 PING 命令,哨兵就判定掌門下線,開始執行「自動切換 master 掌門」的流程。

PING 命令的回覆有兩種情況:

  1. 有效回覆:返回 +PONG、-LOADING、-MASTERDOWN 任何一種;
  2. 無效回覆:有效回覆之外的回覆,或者再指定時間內返回任何回覆。

65 哥:哨兵如何判斷「掌門」嗝屁呢?掌門詐屍咋辦?

為了防止掌門「假死」,「哨兵」設計了「主觀下線」和「客觀下線」兩種暗號。

主觀下線

哨兵利用 PING 命令來檢測掌門、 slave 的生命狀態。如果是無效回覆,哨兵就把這個哥們標記為「主觀下線」。檢測到的是武當小弟,也就是 slave 角色。那麼就直接標記「主觀下線」。

因為 master 掌門還在,slave 的嗝屁對整個武當影響不大。依然可以對外開會,比武論劍、吃香喝辣…...

如果檢測到是 master 掌門完蛋,這時候哨兵不能這麼簡單的標記「主觀下線」,開啟新掌門選舉。

因為有可能出現誤判,掌門並沒有嗝屁,一旦啟動了掌門切換,後續的選主、通知開發佈會,slave 花時間與新 master 同步資料都會消耗大量資源。

所以「哨兵」要降低誤判的概率,誤判一般會發生在叢集網路壓力較大、網路擁塞,或者是主庫本身壓力較大的情況下。

既然一個人容易誤判,那就多個人一起投票判斷。哨兵機制也是類似的,採用多例項組成的叢集模式進行部署,這就是哨兵叢集。引入多個哨兵例項一起來判斷,就可以避免單個哨兵因為自身網路狀況不好,而誤判主庫下線的情況。

同時,多個哨兵的網路同時不穩定的概率較小,由它們一起做決策,誤判率也能降低。

客觀下線

判斷 master 是否下線不能只有一個「哨兵」說了算,只有過半的哨兵判斷 master 已經「主觀下線」,這時候才能將 master 標記為「客觀下線」,也就是說這是一個客觀事實,掌門真的嗝屁了,華佗再世也治不好了。

只有 master 被判定為「客觀下線」,才會進一步觸發哨兵開始主從切換流程。

主觀下線與客觀下線的區別

簡單來說,主觀下線是哨兵自己認為節點宕機,而客觀下線是不但哨兵自己認為節點宕機,而且該哨兵與其他哨兵溝通後,達到一定數量的哨兵都認為該哥們嗝屁了。

這裡的「一定數量」是一個法定數量(Quorum),是由哨兵監控配置決定的,解釋一下該配置:

# sentinel monitor <master-name> <master-host> <master-port> <quorum>
# 舉例如下:
sentinel monitor mymaster 127.0.0.1 6379 2

這條配置項用於告知哨兵需要監聽的主節點:

  • sentinel monitor:代表監控。
  • mymaster:代表主節點的名稱,可以自定義。
  • 192.168.11.128:代表監控的主節點 ip,6379 代表埠。
  • 2:法定數量,代表只有兩個或兩個以上的哨兵認為主節點不可用的時候,才會把 master 設定為客觀下線狀態,然後進行 failover 操作。

「客觀下線」的標準就是,當有 N 個哨兵例項時,要有 N/2 + 1 個例項判斷 master 為「主觀下線」,才能最終判定 Master 為「客觀下線」,其實就是過半機制。

自動切換主庫

65 哥:既然判斷 master 客觀下線了,那就要從選出一個新掌門人了吧。

「哨兵」的第二個任務,選擇新 master 掌門。需要從武當弟子中按照一定規則選擇一個牛逼人物作為新掌門,完成選任掌門後,新 master 帶領眾弟子一起吃香喝辣。

按照一定的「篩選條件」 + 「打分」策略,選出「最強王者」擔任掌門,也就是通過一些條件海選過濾一些「無能之輩」,接著將通過海選的靚仔全都打分排名,將最高者選為新 master。

如圖所示:

網路經常斷開的靚仔也不可取,你想,即使變成 master,可是很快網路出了故障,又得重新選擇新 master,這不鬧著玩麼,得排除掉!

篩選條件

65 哥:那都有哪些篩選條件呀?

  • 從庫當前線上狀態,下線的直接丟棄;
  • 評估之前的網路連線狀態 down-after-milliseconds * 10:如果從庫總是和主庫斷連,而且斷連次數超出了一定的閾值(10 次),我們就有理由相信,這個從庫的網路狀況並不是太好,就可以把這個從庫篩掉了。

打分

過濾掉不合適的 slave 之後,則進入打分環節。打分會按照三個規則進行三輪打分,規則分別為:

  1. slave 優先順序,通過 slave-priority 配置項,給不同的從庫設定不同優先順序(後臺有人沒辦法),優先順序高的直接晉級為新 master 掌門。
  2. slave_repl_offsetmaster_repl_offset進度差距(誰的武功與之前掌門的功夫越接近誰就更牛逼),如果都一樣,那就繼續下一個規則。其實就是比較 slave 與舊 master 複製進度的差距;
  3. slave runID,在優先順序和複製進度都相同的情況下,ID 號最小的從庫得分最高,會被選為新主庫。 (論資排輩,根據 runID 的建立時間來判斷,時間早的上位);

通知

65 哥:為哈還要召開新聞釋出會呢?

重新選舉新 master 掌門這種事情,何等大事,怎能不告知天下。再者其他 slave 弟子也要知道新掌門是誰,一起追隨新掌門吃香喝辣大保健。

最後一個任務,「哨兵」將新 「master 掌門」的連線資訊傳送給其他 slave 武當弟子,並且讓 slave 執行 replacaof 命令,和新「master 掌門」建立連線,並進行資料複製學習新掌門的所有武功。

除此之外,「哨兵」還需要將新掌門的連線資訊通知整個武林(客戶端),使得讓所有想拜訪、討教的人能找到新任掌門,這樣諸多事宜才能交給新掌門做決定(將讀寫請求轉移到新 master)。

哨兵的主要任務與實現目標

哨兵叢集工作原理

「哨兵」部門並不是一個人,多個人共同組成一個「哨兵叢集」,即使有一些「哨兵」被老王打死了,其他的「哨兵」依然可以共同協作完成監控、新掌門選舉以及通知 slave 、master 以及每一個武林人士(客戶端)。

在配置哨兵叢集的時候,哨兵配置中只設置了監控的 master IP 和 port,並沒有配置其他哨兵的連線資訊。

sentinel monitor <master-name> <ip> <redis-port> <quorum>

哨兵之間是如何知道彼此的?如何知道 slave 並監控他們的?由哪一個「哨兵」執行主從切換呢?

帶著這些問題,跟著「碼哥位元組」一起追本溯源,深入哨兵叢集心臟。

pub/sub 實現哨兵間通訊和發現 slave

65 哥:哨兵之間是如何知道彼此的?

哨兵之間可以相互通訊約會搞事情,主要歸功於 Redis 的 pub/sub 釋出/訂閱機制。

哨兵與 master 建立通訊,利用 master 提供釋出/訂閱機制釋出自己的資訊,比如身高體重、是否單身、IP、埠……

master 有一個 __sentinel__:hello 的專用通道,用於哨兵之間釋出和訂閱訊息。這就好比是 __sentinel__:hello 微信群,哨兵利用 master 建立的微信群釋出自己的訊息,同時關注其他哨兵釋出的訊息

當多個哨兵例項都在主庫上做了釋出和訂閱操作後,它們之間就能知道彼此的 IP 地址和埠,從而相互發現建立連線。

Redis 通過頻道的方式對訊息進行分別管理,這裡的頻道其實就是不同的微信群。比如“碼哥位元組讀者技術群”就是專門分享技術的群。朋友們可以關注公眾號,後臺回覆“加群”,一起成長。

65 哥:哨兵之間雖然建立連線了,但是還需要和 slave 建立連線,不然沒法監控他們呀,如何知道 slave 並監控他們的?

的確,哨兵之間建立連線形成叢集還不夠,還需要跟 slave 建立連線,不然沒法監控他們,無法對主從庫進行心跳判斷。

除此之外,如果發生了主從切換也得通知 slave 重新跟新 master 建立連線執行資料同步。關於主從架構資料同步原理可移步《Redis 高可用篇:你管這叫主從架構資料一致性同步》。

關鍵還是利用 master 來實現,哨兵向 master 傳送 INFO 命令, master 掌門自然是知道自己門下所有的 salve 小弟的。所以 master 接收到命令後,便將 slave 列表告訴哨兵。

哨兵根據 master 響應的 slave 名單資訊與每一個 salve 建立連線,並且根據這個連線持續監控哨兵。

如圖所示,哨兵 2 向 Master 傳送 INFO 命令,Master 就把 slave 列表返回給哨兵 2,哨兵 2 便根據 slave 列表連線資訊與每一個 slave 建立連線,並基於此連線實現持續監控。

剩下的哨兵也同理基於此實現監控。

選擇哨兵執行主從切換

65 哥:master 嗝屁了以後,哨兵這麼多,那到底讓哪一個哨兵來執行新 master 切換呢?

這個跟哨兵判斷 master “客觀下線”類似,也是通過投票的方式選出來的。

任何一個哨兵判斷 master “主觀下線”後,就會給其他哨兵基友傳送 is-master-down-by-addr 命令,好基友則根據自己跟 master 之間的連線狀況分別響應 Y 或者 NY 表示贊成票, N 就是反對。

如果某個哨兵獲得了大多數哨兵的“贊成票”之後,就可以標記 master 為 “客觀下線”,贊成票數是通過哨兵配置檔案中的 quorum 配置項設定。

sentinel monitor <master-name> <ip> <redis-port> <quorum>

比如一共 3 個哨兵組成叢集,那麼 quorum 就可以配置成 2,當一個哨兵獲得了 2 張贊成票,就可以標記 master “客觀下線”,當然這個票包含自己的那一票。

獲得多數贊成票的哨兵可以向其他哨兵傳送命令,申明自己想要執行主從切換。並讓其他哨兵進行投票,投票過程就叫做 “Leader 選舉”。

想要成為 “Leader”沒那麼簡單,得有兩把刷子。需要滿足以下條件:

  1. 獲得其他哨兵基友過半的贊成票;
  2. 贊成票的數量還要大於等於配置檔案的 quorum 的值。

如果哨兵叢集有 2 個例項,此時,一個哨兵要想成為 Leader,必須獲得 2 票,而不是 1 票。所以,如果有個哨兵掛掉了,那麼,此時的叢集是無法進行主從庫切換的。因此,通常我們至少會配置 3 個哨兵例項。

這也是為啥哨兵叢集部署成單數的原因,雙數的話多餘浪費。

選舉流程如下圖所示:

通過 pub/sub 實現客戶端事件通知

65 哥:新 master 選出來了,要怎麼公示天下呢?

當然是召開新聞釋出會呀,邀請訊息相關型別的媒體報道傳播,感興趣的人自然就去關注訂閱相關事件,並根據事件做出行動。

在 Redis 也是類似,通過 pub/sub 機制釋出不同事件,讓客戶端在這裡訂閱訊息。客戶端可以訂閱哨兵的訊息,哨兵提供的訊息訂閱頻道有很多,不同頻道包含了主從庫切換過程中的不同關鍵事件。

也就是在不同的“微信群”釋出不同的事件,讓對該事件感興趣的人進群即可。

master 下線事件

  • +sdown:進入“主觀下線”狀態;
  • -sdown:退出“主觀下線”狀態;
  • +odown:進入“客觀下線”狀態;
  • -odown:退出“客觀下線”狀態;

slave 重新配置事件

  • +slave-reconf-sent:哨兵傳送 replicaof 命令重新配置從庫;
  • +slave-reconf-inprog:slave 配置了新 master,但是尚未進行同步;
  • +slave-reconf-done:slave 配置了新 master,並與新 master 完成了資料同步;

新主庫切換

+switch-master:master 地址發生了變化。

知道了這些頻道之後,就可以讓客戶端從哨兵這裡訂閱訊息了。客戶端讀取哨兵的配置檔案後,可以獲得哨兵的地址和埠,和哨兵建立網路連線。

然後,我們可以在客戶端執行訂閱命令,來獲取不同的事件訊息。

舉個栗子:如下指令訂閱“所有例項進入客觀下線狀態的事件”

SUBSCRIBE +odown

注意事項與配置說明

發現了沒,Redis 的 pub/sub 釋出訂閱機制尤其重要,有了 pub/sub 機制,哨兵和哨兵之間、哨兵和從庫之間、哨兵和客戶端之間就都能建立起連線了,各種事件的釋出也是通過這個機制實現。

down-after-milliseconds

Sentinel 配置檔案中的 down-after-milliseconds 選項指定了 Sentinel 判斷例項進入主觀下線所需的時間長度:如果一個例項在 down-after-milliseconds 毫秒內,連續向 Sentinel 返回無效回覆,那麼 Sentinel 會修改這個例項所對應資料,以此來表示這個例項已經進入主觀下線狀態。

要保證所有哨兵例項的配置是一致的,尤其是主觀下線的判斷值 down-after-milliseconds。因為這個值在不同的哨兵例項上配置不一致,導致哨兵叢集一直沒有對有故障的主庫形成共識,也就沒有及時切換主庫,最終的結果就是叢集服務不穩定

down-after-milliseconds * 10

down-after-milliseconds 是我們認定主從庫斷連的最大連線超時時間。如果在 down-after-milliseconds 毫秒內,主從節點都沒有通過網路聯絡上,我們就可以認為主從節點斷連了。如果發生斷連的次數超過了 10 次,就說明這個從庫的網路狀況不好,不適合作為新主庫。

總結

哨兵主要任務

Redis 哨兵機制是實現 Redis 不間斷服務的高可用手段之一。主從架構叢集的資料同步,是資料可靠的基礎保障;主庫宕機,自動執行主從切換是服務不間斷的關鍵支撐。

Redis 哨兵機制實現了主從庫的自動切換,再也不怕跟女盆友麼麼噠的時候 master 宕機了:

  • 監控 master 與 slave 執行狀態,判斷是否客觀下線;
  • master 客觀下線後,選擇一個 slave 切換成 master;
  • 通知 slave 和客戶端新 master 資訊。

哨兵叢集原理

為了避免單個哨兵故障後無法進行主從切換,以及為了減少誤判率,又引入了哨兵叢集;哨兵叢集又需要有一些機制來支撐它的正常執行:

  • 基於 pub/sub 機制實現哨兵叢集之間的通訊;
  • 基於 INFO 命令獲取 slave 列表,幫助 哨兵與 slave 建立連線;
  • 通過哨兵的 pub/sub,實現了與客戶端和哨兵之間的事件通知。

主從切換,並不是隨意選擇一個哨兵就可以執行,而是通過投票仲裁,選擇一個 Leader,由這個 Leader 負責主從切換。

一起交流

下一篇「碼哥位元組」將帶來 《Redis 高可用篇:Cluster 叢集,是兄弟就跟我一起扛》,關注我,獲取真正的硬核知識點。

另外技術讀者群也開通了,後臺回覆「加群」獲取「碼哥位元組」作者微信交流或者提出建議,一起成長交流。群裡有 N 多大廠的大佬,也可內推哦。

以上就是 Redis 哨兵叢集原理詳解,覺得不錯請點贊、分享,「碼哥位元組」感激不盡。

參考資料

加我微信進去專屬技術群,歡迎讀者提出意見,喜歡請關注部落格和個人公眾號:碼哥位元組