位元組一面:Redis主節點不小心宕機了!

「來源: |架構師修行之路 ID:jiagoushixiuxing」

今天跟大家聊下,如果Redis某個節點宕機了,要怎麼處理?

位元組一面:Redis主節點不小心宕機了!

我們知道,Redis叢集一般採用主從模式,主節點負責寫,從節點負責讀。

從節點故障

從節點主要提供讀服務,為了分攤主伺服器壓力,一般會有多個從節點。

位元組一面:Redis主節點不小心宕機了!

如果是從節點故障,不算什麼大問題,客戶端把該故障節點遮蔽即可,仍可訪問其他的主、從節點滿足正常的業務功能。

主節點故障

如果是主節點宕機了,那就有點麻煩了,畢竟寫操作是在主節點上,無法替代。

位元組一面:Redis主節點不小心宕機了!

這時候,我們要幹一件事,從所有的從庫節點中挑選一臺做為主節點。這裡要介紹下Sentienl 哨兵機制了。

哨兵機制分為三個階段:

1、監控。哨兵程序會週期給所有的主庫、從庫傳送 PING 命令,檢測機器是否處於服務狀態。如果沒有在設定時間內收到回覆,則判定為下線。

2、選主。主要是看各個節點的打分情況,打分規則分為 從庫優先順序、從庫複製進度、從庫ID號。只要有一輪,某個從庫得分最高,則選舉它為主庫。

從庫優先順序,主要是考慮到不同的機器可能配置不一樣,配置高的機器,優先順序高一些,透過slave-priority 來配置

從庫複製進度,主要是看slave_repl_offset 的值大小,值越大表示已經同步的資料越多,得分越高。

從庫ID號,每個Redis 例項啟動時,都會生成一個 ID,在優先順序和複製進度相同的條件下,ID號最小的從庫分數最高,會被選為新主庫。

3、通知。把選舉後的新主庫傳送給所有節點,讓所有的從庫執行 replicaof 命令,和新 master建立主從關係、資料同步複製。另外,也會把最新的主庫資訊同步給客戶端。這樣後續的寫請求會打到新的 主節點上。

我們知道網路存在不穩定性,所以會不會有什麼特殊問題?我們繼續往下看

網路抖動,引發誤判

問題描述:

哨兵節點監控到主節點超時未響應,主節點不一定是真的宕機。可能是之間的網路擁堵,或者主庫自身壓力過大,導致響應超時。

如何避免這種情況?

引入哨兵叢集,多個哨兵例項一起判斷,降低誤判率。判斷標準就是,假如 n 個哨兵例項,至少有 n/2+1 個判定一致,才可以定論。

注意:

上面的誤判只會用在主庫,從庫只是負責讀,如果監測到未響應,直接標記為 ”下線“,並不需要叢集投票驗證其真實性。

如果是主庫超時未響應,則不能這麼草率決定,畢竟後面的選主和通知都是一筆不小的開銷,所以,標記主庫”下線“,一定要慎之又慎。

那麼,哨兵叢集集如何投票,確認主節點是否真的下線呢?在深入這個問題之前,我們先來了解下哨兵叢集

哨兵叢集如何構建?

首先,在redis-sentinel 的conf檔案裡新增兩個配置項:

sentinel monitor

master-name:對某個master+slave 組合的一個區分標識(一套sentinel是可以監聽多套master+slave這樣的組合)

ip 和 port:就是master節點的 ip 和 埠號。

quorum:進行客觀下線的一個依據,意思是至少有 quorum 個sentinel主觀的認為這個master有故障,才會對這個master下線或故障轉移。

sentinel down-after-milliseconds

timeout:毫秒值,如果這臺sentinel超過timeout時間無法連通master或slave(slave不需要客觀下線,因為不需要故障轉移),就會主觀認為該master已經下線(實際下線需要客觀下線的判斷透過才會真正下線)

位元組一面:Redis主節點不小心宕機了!

藉助釋出/訂閱組建哨兵叢集

我們知道Redis 有pub/sub 機制,當一個哨兵與主庫建立連線,可以在主庫上釋出自己的訊息(ip、port),當然也可以在主庫上訂閱其他哨兵釋出的訊息。

有點類似MQ的topic味道,大家基於同一個topic完成資料交換。

當所有的哨兵都完成上述動作,哨兵叢集也就組建完成。

為什麼要組建哨兵叢集呢?因為後面的選主需要有一個leader帶頭操作。

哨兵如何知道所有從庫地址呢?

我們知道每個哨兵例項的配置引數裡有配置主庫的ip和port,而每個主庫要同步資料給從庫,自然有掛載的所有從庫資訊。

所以,哨兵例項只需向主庫傳送INFO命令即可獲取到所需要的資訊,然後哨兵例項在依次與從庫建立連線。

至此,一個哨兵例項便可以收集到整個Redis 叢集的資料,包含三塊:

所有的哨兵節點ip、port

主節點ip、port

主節點掛載的所有從節點的 ip、port

其他哨兵例項也是一樣道理,這裡就不在贅述了。

哨兵是個叢集,選主需要有個帶頭大哥

當一個哨兵例項監控到主庫”主觀下線“後,給其他例項傳送 is-master-down-by-addr 命令,其他哨兵例項根據自己與主庫的連線情況,做出 Y 或 N的回覆。

當這個哨兵收集到了超過 quorum 配置項的 Y 回覆後,就會標記主庫”客觀下線“。

下面,就要進入選主階段了。正所謂”一山不容二虎“,那麼由哪個哨兵例項來執行選主操作呢?

位元組一面:Redis主節點不小心宕機了!

還是公平點,採用民主投票。先在 哨兵叢集中選出一個帶頭大哥,由它代表大家執行後續操作。

如何選哨兵Leader?

位元組一面:Redis主節點不小心宕機了!

上圖畫了個流程例項,三個哨兵節點在 t1~t6 不同時刻點的投票情況。

當一個哨兵例項收到超過 設定的quorum 票Y後,它會成為新的Leader。然後由它(哨兵S3)負責後面的從庫選主,通知從庫與新主庫建立關係並同步資料,通知客戶端訪問新主庫。

如果本輪沒有選出Leader節點,等哨兵故障轉移超時時間的 2 倍時間後,重新發起新一輪選舉。

為了保證哨兵Leader選舉的順利進行,除了對網路質量有要求外,最好配置奇數個哨兵節點且最好三個以上。

哨兵也是例項,如果掛了怎麼辦?

哨兵主要是用來監控Redis叢集的健康狀況,本身並不提供服務。

當一個哨兵例項掛掉後,會影響到叢集的監測。為了降低影響,我們引入哨兵叢集,降低單點風險,由哨兵叢集保障Redis主從叢集的健康。

舉個例子:

哨兵叢集配置了三個例項,quorum 配置值為2。當一個哨兵例項宕機後,其餘兩個哨兵例項依然可以完成選舉,只是可能存在一定風險而已。

哨兵叢集完成了主從切換,客戶端如何感知?

我們知道Redis有pub/sub機制,為了便於外部知道當前的切換進度,哨兵提供了多個訂閱頻道。

其中就有一個新主庫切換頻道,(switch-master)

SUBSCRIBE +switch-master

訂閱對應頻道,可以獲得切換後的新主庫ip、port,並與之建立連線,繼續享受Redis服務。