Redis 哨兵集群如何實現高可用?

原文出處:https://github.com/doocs/advanced-java/blob/master/docs/high-concurrency/redis-sentinel.md
歡迎 star 關注 GitHub 項目最新動態!

Redis 哨兵集群實現高可用

哨兵的介紹

sentinel,中文名是哨兵。哨兵是 redis 集群機構中非常重要的一個組件,主要有以下功能:

  • 集群監控:負責監控 redis master 和 slave 進程是否正常工作。
  • 消息通知:如果某個 redis 實例有故障,那么哨兵負責發送消息作為報警通知給管理員。
  • 故障轉移:如果 master node 掛掉了,會自動轉移到 slave node 上。
  • 配置中心:如果故障轉移發生了,通知 client 客戶端新的 master 地址。

哨兵用于實現 redis 集群的高可用,本身也是分布式的,作為一個哨兵集群去運行,互相協同工作。

  • 故障轉移時,判斷一個 master node 是否宕機了,需要大部分的哨兵都同意才行,涉及到了分布式選舉的問題。
  • 即使部分哨兵節點掛掉了,哨兵集群還是能正常工作的,因為如果一個作為高可用機制重要組成部分的故障轉移系統本身是單點的,那就很坑爹了。

哨兵的核心知識

  • 哨兵至少需要 3 個實例,來保證自己的健壯性。
  • 哨兵 + redis 主從的部署架構,是不保證數據零丟失的,只能保證 redis 集群的高可用性。
  • 對于哨兵 + redis 主從這種復雜的部署架構,盡量在測試環境和生產環境,都進行充足的測試和演練。

哨兵集群必須部署 2 個以上節點,如果哨兵集群僅僅部署了 2 個哨兵實例,quorum = 1。

+----+         +----+
| M1 |---------| R1 |
| S1 |         | S2 |
+----+         +----+

配置 quorum=1,如果 master 宕機, s1 和 s2 中只要有 1 個哨兵認為 master 宕機了,就可以進行切換,同時 s1 和 s2 會選舉出一個哨兵來執行故障轉移。但是同時這個時候,需要 majority,也就是大多數哨兵都是運行的。

2 個哨兵,majority=2
3 個哨兵,majority=2
4 個哨兵,majority=2
5 個哨兵,majority=3
...

如果此時僅僅是 M1 進程宕機了,哨兵 s1 正常運行,那么故障轉移是 OK 的。但是如果是整個 M1 和 S1 運行的機器宕機了,那么哨兵只有 1 個,此時就沒有 majority 來允許執行故障轉移,雖然另外一臺機器上還有一個 R1,但是故障轉移不會執行。

經典的 3 節點哨兵集群是這樣的:

       +----+
       | M1 |
       | S1 |
       +----+
          |
+----+    |    +----+
| R2 |----+----| R3 |
| S2 |         | S3 |
+----+         +----+

配置 quorum=2,如果 M1 所在機器宕機了,那么三個哨兵還剩下 2 個,S2 和 S3 可以一致認為 master 宕機了,然后選舉出一個來執行故障轉移,同時 3 個哨兵的 majority 是 2,所以還剩下的 2 個哨兵運行著,就可以允許執行故障轉移。

redis 哨兵主備切換的數據丟失問題

兩種情況和導致數據丟失

主備切換的過程,可能會導致數據丟失:

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

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

async-replication-data-lose-case.png
  • 腦裂導致的數據丟失

腦裂,也就是說,某個 master 所在機器突然脫離了正常的網絡,跟其他 slave 機器不能連接,但是實際上 master 還運行著。此時哨兵可能就會認為 master 宕機了,然后開啟選舉,將其他 slave 切換成了 master。這個時候,集群里就會有兩個 master ,也就是所謂的腦裂

此時雖然某個 slave 被切換成了 master,但是可能 client 還沒來得及切換到新的 master,還繼續向舊 master 寫數據。因此舊 master 再次恢復的時候,會被作為一個 slave 掛到新的 master 上去,自己的數據會清空,重新從新的 master 復制數據。而新的 master 并沒有后來 client 寫入的數據,因此,這部分數據也就丟失了。

redis-cluster-split-brain.png

數據丟失問題的解決方案

進行如下配置:

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

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

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

  • 減少異步復制數據的丟失

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

  • 減少腦裂的數據丟失

如果一個 master 出現了腦裂,跟其他 slave 丟了連接,那么上面兩個配置可以確保說,如果不能繼續給指定數量的 slave 發送數據,而且 slave 超過 10 秒沒有給自己 ack 消息,那么就直接拒絕客戶端的寫請求。因此在腦裂場景下,最多就丟失 10 秒的數據。

sdown 和 odown 轉換機制

  • sdown 是主觀宕機,就一個哨兵如果自己覺得一個 master 宕機了,那么就是主觀宕機
  • odown 是客觀宕機,如果 quorum 數量的哨兵都覺得一個 master 宕機了,那么就是客觀宕機

sdown 達成的條件很簡單,如果一個哨兵 ping 一個 master,超過了 is-master-down-after-milliseconds 指定的毫秒數之后,就主觀認為 master 宕機了;如果一個哨兵在指定時間內,收到了 quorum 數量的其它哨兵也認為那個 master 是 sdown 的,那么就認為是 odown 了。

哨兵集群的自動發現機制

哨兵互相之間的發現,是通過 redis 的 pub/sub 系統實現的,每個哨兵都會往 __sentinel__:hello 這個 channel 里發送一個消息,這時候所有其他哨兵都可以消費到這個消息,并感知到其他的哨兵的存在。

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

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

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

slave 配置的自動糾正

哨兵會負責自動糾正 slave 的一些配置,比如 slave 如果要成為潛在的 master 候選人,哨兵會確保 slave 復制現有 master 的數據;如果 slave 連接到了一個錯誤的 master 上,比如故障轉移之后,那么哨兵會確保它們連接到正確的 master 上。

slave->master 選舉算法

如果一個 master 被認為 odown 了,而且 majority 數量的哨兵都允許主備切換,那么某個哨兵就會執行主備切換操作,此時首先要選舉一個 slave 來,會考慮 slave 的一些信息:

  • 跟 master 斷開連接的時長
  • slave 優先級
  • 復制 offset
  • run id

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

(down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state

接下來會對 slave 進行排序:

  • 按照 slave 優先級進行排序,slave priority 越低,優先級就越高。
  • 如果 slave priority 相同,那么看 replica offset,哪個 slave 復制了越多的數據,offset 越靠后,優先級就越高。
  • 如果上面兩個條件都相同,那么選擇一個 run id 比較小的那個 slave。

quorum 和 majority

每次一個哨兵要做主備切換,首先需要 quorum 數量的哨兵認為 odown,然后選舉出一個哨兵來做切換,這個哨兵還需要得到 majority 哨兵的授權,才能正式執行切換。

如果 quorum < majority,比如 5 個哨兵,majority 就是 3,quorum 設置為 2,那么就 3 個哨兵授權就可以執行切換。

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

configuration epoch

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

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

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

configuration 傳播

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

這里之前的 version 號就很重要了,因為各種消息都是通過一個 channel 去發布和監聽的,所以一個哨兵完成一次新的切換之后,新的 master 配置是跟著新的 version 號的。其他的哨兵都是根據版本號的大小來更新自己的 master 配置的。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評論 6 546
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,814評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,980評論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,779評論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,109評論 1 330
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,287評論 0 291
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,799評論 1 338
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,515評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,750評論 1 375
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,933評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,492評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,703評論 2 380

推薦閱讀更多精彩內容