Redis哨兵機(jī)制的使用詳解
一.哨兵機(jī)制基本解讀
主庫發(fā)生故障了,如何不間斷的服務(wù)?
哨兵模式:有效的解決主從庫自動切換的關(guān)鍵機(jī)制

在Redis中如果從庫發(fā)生故障了,客戶端可以繼續(xù)向主庫和其他從庫發(fā)消息,進(jìn)行相關(guān)操作。但是如果主庫故障了,直接影響到從庫的同步操作(從庫沒有相應(yīng)主庫進(jìn)行相關(guān)數(shù)據(jù)復(fù)制操作了)和沒有實例來支持客戶端進(jìn)行寫操作。
把從庫切換成主庫,需要涉及三個問題:
- 主庫真的掛了嗎?
- 應(yīng)該選擇哪一個從庫來切換成主庫?
- 怎么把新主庫的信息通知給從庫和客戶端呢?
1.哨兵機(jī)制的基本流程
哨兵機(jī)制,在主從庫實例運(yùn)行的時候,就在運(yùn)行。哨兵機(jī)制主要的行為就是監(jiān)控。
1.1哨兵監(jiān)控
哨兵進(jìn)程在運(yùn)行過程中會周期性的給所有主從庫發(fā)送PING命令,檢測他們是否還在線運(yùn)行。如果從庫沒有在規(guī)定時間內(nèi)響應(yīng)哨兵的PING命令,哨兵就會把它標(biāo)記為“下線狀態(tài)”。同樣,如果主庫沒有在規(guī)定時間內(nèi)響應(yīng)哨兵的PING命令,哨兵也會把主庫標(biāo)記為“下線狀態(tài)”,然后開始自動切換主庫的流程。
1.2自動切換主庫流程
- 這個流程首先執(zhí)行的是哨兵的第二個任務(wù):選主。主庫掛了之后,哨兵需要從眾多從庫中,按照一定規(guī)則選擇一個從庫實例,把它作為更新的主庫。這一步完成后,集群里就會有新的主庫了。
- 然后執(zhí)行的是最后一個任務(wù):通知。在執(zhí)行任務(wù)通知時,哨兵會把新主庫的信息發(fā)送給其他所有從庫,讓他們執(zhí)行replicaof命令,和新主庫建立好連接,并且進(jìn)行數(shù)據(jù)復(fù)制。同時,哨兵會把新主庫連接信息給客戶端,讓他把新的請求發(fā)送到新主庫上。

在這三個任務(wù)中通知任務(wù)相對簡單,只需要給從庫和客戶端發(fā)送新主庫的信息,讓他們跟新主庫連接就行,并不涉及決策邏輯。但是在監(jiān)控和選主這兩個任務(wù)中,哨兵需要作出兩個決策:
- 在監(jiān)控任務(wù)中,哨兵需要決策主庫是否處于下線狀態(tài)
- 在選主任務(wù)中,哨兵也要決定選取那個從庫實例作為新主庫。
如何判斷主庫是否下線?
2.主庫是否下線判斷
主庫是否下線判斷分為兩種“主觀下線”和”客觀下線“。
2.1.主觀下線
主觀下線:
- 哨兵機(jī)制會給主從庫發(fā)送PING命令,檢測他自己和主從庫的網(wǎng)絡(luò)連接情況,用來判斷實例的狀態(tài)。
- 如果哨兵發(fā)現(xiàn)主從庫的響應(yīng)時間超時了,就會給主從庫標(biāo)記為“主觀下線”。
誤判:
- 但是會出現(xiàn)一種情況,哨兵誤判了,主從庫并沒有故障,主庫也并沒有下線,哨兵誤判他下線了。誤判一般發(fā)生在:集群網(wǎng)絡(luò)壓力大,網(wǎng)絡(luò)擁塞,或者主庫本身壓力較大的情況下。
- 一旦哨兵判斷主庫下線了,就需要進(jìn)行選主,主從庫同步等一系列操作,就會增加額外的計算和通信開銷。
- 所以需要減少誤判。
- 怎么減少誤判呢?
- 引入多幾個哨兵進(jìn)行協(xié)商判斷,也就是哨兵集群。
哨兵集群:
- 通常由多個實例組成的集群模式進(jìn)行部署。
- 引入多個哨兵實例進(jìn)行判斷,避免單個哨兵因為網(wǎng)絡(luò)不好造成的誤判主庫下線的情況。
- 多個哨兵網(wǎng)絡(luò)同時不穩(wěn)定的概率小,同時誤判的概率也小了。
2.2客觀下線
在判斷主庫是否下線時,不能由一個哨兵說了算,要大多數(shù)哨兵,都判斷主庫已經(jīng)“主觀下線”,主庫才會標(biāo)記為”客觀下線“,這個說法表明主庫下線已經(jīng)成為了客觀事實,判斷原理就是:少數(shù)服從多數(shù)。

客觀下線:當(dāng)有N個集群時,當(dāng)有N/2+1個集群已經(jīng)判斷主庫“主觀下線”,才能最終判斷主庫“客觀下線”。減少誤判帶來的主從庫切換開銷。(有幾個實例來作出主庫“主觀下線”的判斷才可以,由Redis管理員自信設(shè)定)。
3.主從切換機(jī)制:主庫下線了就要進(jìn)行主從切換了
如何選定新主庫?
一般來說,哨兵選擇新主庫的過程可以稱為“篩選+打分”。就是在多個實例從庫中,按照一定的篩選條件,把不符合條件的從庫去掉。然后在按照一定的規(guī)則,給剩下的從庫逐個打分,將得分最高的從庫選為新主庫。

3.1篩選條件
不僅僅要判斷從庫當(dāng)前的狀態(tài),還要判斷他之前的網(wǎng)絡(luò)連接狀態(tài)。如果之前從庫跟主庫斷聯(lián)次數(shù)超過了閾值,那么有有理由詳細(xì)這個從庫的網(wǎng)絡(luò)連接狀態(tài)不是很好,可以把它篩選掉。雖然現(xiàn)在他在運(yùn)行,但是萬一過一會斷掉了,就需要重新選主,所以需要判斷她之前的狀態(tài)。
具體怎么判斷呢?
使用配置項down-after-milliseconds*10。其中,down-after-milliseconds是我們認(rèn)定是從庫斷聯(lián)的最大時間。如果在down-after-milliseconds毫秒內(nèi),主從節(jié)點都沒有網(wǎng)絡(luò)連接上,那么就認(rèn)為從庫斷聯(lián)了。如果斷聯(lián)時間超過了10次就認(rèn)為,這個從庫的網(wǎng)絡(luò)轉(zhuǎn)態(tài)不是很好,不適合做主庫。
3.2打分規(guī)則
可以分別按照三個規(guī)則進(jìn)行打分:從庫優(yōu)先級、從庫復(fù)制進(jìn)度、以及從庫ID號
只需要在某一輪得分最高,那么他就是新主庫,選主過程到此結(jié)束,要是沒有出現(xiàn)得分最高的,那么久進(jìn)行下一輪。
第一輪:優(yōu)先級slave-priority最高的從庫得分高
用戶可以通過slave-priority配置項,給不同的從庫設(shè)置不同優(yōu)先級。比如,你有兩個從庫,它們的內(nèi)存大
小不一樣,你可以手動給內(nèi)存大的實例設(shè)置一個高優(yōu)先級。在選主時,哨兵會給優(yōu)先級高的從庫打高分,如果有一個從庫優(yōu)先級最高,那么它就是新主庫了。如果從庫的優(yōu)先級都一樣,那么哨兵開始第二輪打分。
第二輪:和舊主庫同步程度最接近的從庫得分高
如果選擇和舊主庫同步最接近的從庫作為主庫,新主庫上邊就會有最新的數(shù)據(jù)。
如何判斷從庫和主庫的同步進(jìn)度呢?(復(fù)制進(jìn)度)
主從庫同步的時有個命令傳播的過程,在這個過程中,主庫會用master-repl-offset記錄,當(dāng)前的最新寫操作在repl-backlog-buffer的中位置,而從庫會用slave-repl-offset記錄復(fù)制的進(jìn)度。
所以我們需要找到master-repl-offset,slave-repl-offset最接近的從庫。得分就高,就會被選為新主庫。如果slave-repl-offset相同,就會進(jìn)行下一輪的打分。
就像下圖所示,舊主庫的master_repl_offset是1000,從庫1、2和3的slave_repl_offset分別是950、990和900,那么,從庫2就應(yīng)該被選為新主庫。

第三輪:ID號小的從庫得分高
每個實例都會有一個id,這個ID類似于從庫的編號。Redis選主時,有一個規(guī)定:在優(yōu)先級和復(fù)制進(jìn)度相同的情況下,ID越小的得分越高。
3.3主從切換總結(jié)
首先哨兵機(jī)制會根據(jù)在線狀態(tài),網(wǎng)絡(luò)狀態(tài),過濾篩選掉一部分不符合要求的從庫。然后按照優(yōu)先級,復(fù)制進(jìn)度,ID大小對從庫進(jìn)行打分,得分最高的選為新主庫。
4.哨兵機(jī)制總結(jié)
主從集群數(shù)據(jù)同步,保證了數(shù)據(jù)的可靠性。主庫發(fā)生故障時,自動的主從切換是服務(wù)不間斷的關(guān)鍵支撐。
Redis的哨兵機(jī)制自動完成了以下三大功能,從而實現(xiàn)了主從庫的自動切換,可以降低Redis集群的運(yùn)維開銷:
- 監(jiān)控主庫運(yùn)行狀態(tài),并判斷主庫是否客觀下線;
- 在主庫客觀下線后,選取新主庫;
- 選出新主庫后,通知從庫和客戶端。

為了降低誤判率,在實際應(yīng)用時,哨兵機(jī)制通常來用多實例的方式進(jìn)行部署,多個哨兵實例通過“少數(shù)服從多數(shù)”的原則,來判斷主庫是否客觀下線。一般來說,我們可以部署三個哨兵,如果有兩個哨兵認(rèn)定主庫“主觀下線”,就可以開始切換過程。當(dāng)然,如果你希望進(jìn)一步提升判斷準(zhǔn)確率,也可以再適當(dāng)增加哨兵個數(shù),比如說使用五個哨兵。
哨兵集群中有實例掛了,怎么辦,會影響主庫狀態(tài)判斷和選主嗎?
簡單說結(jié)論:存在故障節(jié)點時,只要集群中大多數(shù)節(jié)點狀態(tài)正常,集群依舊可以對外提供服務(wù)
哨兵集群多數(shù)實例達(dá)成共識,判斷出主庫“客觀下線”后,由哪個實例來執(zhí)行主從切換呢?
哨兵集群判斷出主庫“主觀下線”后,會選出一個“哨兵領(lǐng)導(dǎo)者”,之后整個過程由它來完成主從切換。
哨兵在操作主從切換的過程中,客戶端能否正常地進(jìn)行請求操作?
如果客戶端使用了讀寫分離,那么讀請求可以在從庫上正常執(zhí)行,不會受到影響。但是由于此時主庫已經(jīng)掛了,而且哨兵還沒有選出新的主庫,所以在這期間寫請求會失敗,失敗持續(xù)的時間=哨兵切換主從的時間+客戶端感知到新主庫的時間.
如果不想讓業(yè)務(wù)感知到異常,客戶端只能把寫失敗的請求先緩存起來或?qū)懭胂㈥犃兄虚g件中,等哨兵切換完主從后,再把這些寫請求發(fā)給新的主庫,但這種場景只適合對寫入請求返回值不敏感的業(yè)務(wù),而且還需要業(yè)務(wù)層做適配,另外主從切換時間過長,也會導(dǎo)致客戶端或消息隊列中間件緩存寫請求過多,切換完成之后重放這些請求的時間變長。
哨兵檢測主庫多久沒有響應(yīng)就提升從庫為新的主庫,這個時間是可以配置的(down-after-milliseconds參數(shù))。配置的時間越短,哨兵越敏感,哨兵集群認(rèn)為主庫在短時間內(nèi)連不上就會發(fā)起主從切換,這種配置很可能因為網(wǎng)絡(luò)擁塞但主庫正常而發(fā)生不必要的切換,當(dāng)然,當(dāng)主庫真正故障時,因為切換得及時,對業(yè)務(wù)的影響最小。如果配置的時間比較長,哨兵越保守,這種情況可以減少哨兵誤判的概率,但是主庫故障發(fā)生時,業(yè)務(wù)寫失敗的時間也會比較久,緩存寫請求數(shù)據(jù)量越多。
二.哨兵掛了
如果有哨兵實例在運(yùn)行時發(fā)生了故障,主從庫還能正常切換嗎?
實際上,一旦多個實例組成了哨兵集群,即使有哨兵實例出現(xiàn)故障掛掉了,其他哨兵還能繼續(xù)協(xié)作完成主庫切換的工作,包括判定主庫是不是處于下線狀態(tài),選擇新主庫,以及通知從庫和客戶端。
如果你部署過哨兵集群的話就會知道,在配置哨兵的信息時,我們只需要用到下面的這個配置項,設(shè)置主的IP和端口,并沒有配置其他哨兵的連接信息。
sentinel monitor <master-name> <ip> <redis-port> <quorum>
哨兵既然不知道彼此的地址,怎么組成哨兵集群呢?
1.基于pub/sub機(jī)制的哨兵集群的組成
哨兵能被互相發(fā)現(xiàn)的原因:Redis提供的pub/sub機(jī)制(發(fā)布/訂閱機(jī)制)
1.1哨兵之間互相被發(fā)現(xiàn)過程
哨兵只要跟主庫建立起了連接,就可以在主庫上發(fā)布信息,發(fā)布自己的連接信息(ip和端口號)。同時也可以從主庫上訂閱信息,獲取其它哨兵發(fā)布的連接信息。當(dāng)多個哨兵在主庫上進(jìn)行了發(fā)布和訂閱后,他們就互相知道彼此的ip地址和端口號。
除了哨兵實例,我們自己編寫的應(yīng)用程序也可以通過Redis進(jìn)行消息發(fā)布和訂閱。
Redis如何區(qū)分不同的應(yīng)用程序?
Redis通過頻道的方式。對消息進(jìn)行歸類管理,區(qū)分不同的應(yīng)用消息。頻道其實就是消息類型,當(dāng)消息類型相同時,就屬于一個頻道。只有訂閱了同一個頻道的應(yīng)用才能通過發(fā)布的消息進(jìn)行信息交換。
在主從集群中,主庫存在“__sentinel__:hello”的頻道,不同哨兵通過實現(xiàn)他來相互發(fā)現(xiàn),實現(xiàn)互相通信。
1.2哨兵消息互通說明
例如:在下圖中,哨兵1把自己的IP (17216.19.3) 和端口26579) 發(fā)布到“_sentinel_:hello”頻道上,哨兵2和3訂閱了該頻道。那么此時,哨兵2和3就可以從這個頻道直接獲取哨兵1的IP地址和端口號。
然后,哨兵2、3可以和哨兵1建立網(wǎng)絡(luò)連接。通過這個方式,哨兵2和3也可以建立網(wǎng)絡(luò)連接,這樣一來,哨兵集群就形成了。它們相互間可以通過網(wǎng)絡(luò)連接進(jìn)行通信,比如說對主庫有沒有下線這件事兒進(jìn)行判斷和協(xié)商

哨兵除了需要彼此建立連接形成集群外還需要和從庫建立連接。因為在哨兵監(jiān)控任務(wù)中,哨兵需要對主從庫進(jìn)行心跳判斷,而且在主從庫切換完成后,還需要通知從庫,讓他們和新主庫進(jìn)行同步。
哨兵如何跟從庫簡歷連接?如何知道從庫的ip地址和端口呢?
1.3哨兵與從庫建立連接:INFO命令
當(dāng)哨兵給主庫發(fā)送INFO命令時,主庫接收命令后,會將從庫列表返回給哨兵。哨兵接收從庫列表連接信息后,會和每個從庫建立連接,并且在這個連接上持續(xù)的對從庫進(jìn)行監(jiān)控。

通過pub/sub機(jī)制,哨兵之間建立哨兵集群,又通過發(fā)送INFO命令,獲取從庫連接信息 ,哨兵與從庫建立連接,進(jìn)行監(jiān)控。主從庫切換后,客戶端需要知道新主庫的連接信息,才能像新主庫發(fā)送信息。因此哨兵還需要完成將新主庫信息告訴客戶端的任務(wù)。
在實際使用哨兵時,我們有時會遇到這樣的問題:如何在客戶端通過監(jiān)控了解哨兵進(jìn)行主從切換的過程呢?比如說,主從切換進(jìn)行到哪一步了? 這其實就是要求,客戶端能夠獲取到哨兵集群在監(jiān)控、選主、切換這個過程中發(fā)生的各種事件.
1.4哨兵與客戶端間的信息同步
基于pub/sub機(jī)制的客戶端事件的通知
從本質(zhì)上說,哨兵就是一個運(yùn)行在特定模式下的Redis實例,只不過它并不完成服務(wù)請求操作,只是完成監(jiān)控、選主和通知的任務(wù)。所以,每個哨兵實例也提供pub/sub機(jī)制,客戶端可以從哨兵訂閱消息。哨兵提供的消息訂閱頻道有很多,不同頻道包含了主從庫切換過程中的不同關(guān)鍵事件
常用事件:
事件 | 相關(guān)頻道 |
主庫下線事件 | +sdown(實例進(jìn)入“主觀下線”狀態(tài)) |
-sdown(實例退出“主觀下線”狀態(tài)) | |
+odown(實例進(jìn)入“客觀下線”狀態(tài)) | |
-odown(實例退出“客觀下線”狀態(tài)) | |
從庫重新配置事件 | +slave-reconf-sent(哨兵發(fā)送SLACEOF命令重新配置從庫) |
+slave-reconf-inprog(從庫配置新主庫,但尚未進(jìn)行同步) | |
+slave-reconf-done(從庫配置新主庫,且與新主庫同步完成) | |
新主庫切換 | +switch-master(主庫地址變化) |
知道了這些頻道之后,就可以讓客戶端從哨兵這里訂閱消息了。具體的操作步驟是,客戶端讀取哨兵的配置文件后,可以獲得哨兵的地址和端口,和哨兵建立網(wǎng)絡(luò)連接。然后,可以在客戶端執(zhí)行訂閱命令,來獲取不同的事件消息。
舉個例子,你可以執(zhí)行如下命令,來訂閱“所有實例進(jìn)入客觀下線狀態(tài)的事件”:
subscribe +odown
訂閱所有頻道
PSUBSCRIBE *
當(dāng)哨兵把新主庫選擇出來后,客戶端就會看到下面的switch-master事件。這個事件表示主庫已經(jīng)切換了,新主庫的IP地址和端口信息已經(jīng)有了。這個時候,客戶端就可以用這里面的新主庫地址和端口進(jìn)行通信了。
switch-master <master name> <oldip><oldport> <newport>
通過事件通知,客戶端不僅僅可以在主從切換后得到新主庫的連接信息,還可以監(jiān)控得到主從庫切換過程中發(fā)生的各個重要事件。這樣客戶端就可以知道主從切換到哪一步了,有助于了解切換速度。
總結(jié):有了pub/sub機(jī)制,哨兵可以和從庫之間,哨兵與哨兵之間,哨兵與客戶端之間建立起連接。主庫下線判斷,選主依據(jù)哨兵集群的監(jiān)控、選主和通知三個任務(wù)基本上可以正常工作了。
主從故障后,集群存在多個實例,怎么確定由哪個哨兵來進(jìn)行實際的主從切換呢?
2.哪個哨兵執(zhí)行主從切換?
其實由哪個哨兵進(jìn)行主從切換的過程,其實跟選主一樣也是一個“投票仲裁”的過程。
2.1從哨兵選主,主要過程開始說起
任何一個實例只要自身判斷主庫“主觀下線”后,就會給其他實例發(fā)送is-master-down-by-addr命令。接著,其他實例會根據(jù)自己和主庫的連接情況,做出Y或N的響應(yīng),Y相當(dāng)于贊成票,N相當(dāng)于反對票。

一個哨兵獲得了仲裁所需的贊成票數(shù)后,就可以標(biāo)記主庫為“客觀下線”。這個所需的贊成票數(shù)是通過哨兵配置文件中的 quorum 配置項設(shè)定的。例如,現(xiàn)在有 5 個哨兵,quorum 配置的是 3,那么,一個哨兵需要 3 張贊成票,就可以標(biāo)記主庫為“客觀下線”了。這 3 張贊成票包括哨兵自己的一張贊成票和另外兩個哨兵的贊成票。
2.2哨兵選出Leader過程:Leader選舉
此時,這個哨兵就可以再給其他哨兵發(fā)送命令,表明希望由自己來執(zhí)行主從切換,并讓所有其他哨兵進(jìn)行投票。這個投票過程稱為“Leader 選舉”。因為最終執(zhí)行主從切換的哨兵稱為 Leader,投票過程就是確定 Leader。
在投票過程中,任何一個想成為 Leader 的哨兵,要滿足兩個條件:第一,拿到半數(shù)以上的贊成票;第二,拿到的票數(shù)同時還需要大于等于哨兵配置文件中的 quorum 值。以 3 個哨兵為例,假設(shè)此時的 quorum 設(shè)置為 2,那么,任何一個想成為 Leader 的哨兵只要拿到 2 張贊成票,就可以了。
具體通過下圖講解:

在 T1 時刻,S1 判斷主庫為“客觀下線”,它想成為 Leader,就先給自己投一張贊成票,然后分別向 S2 和 S3 發(fā)送命令,表示要成為 Leader。
在 T2 時刻,S3 判斷主庫為“客觀下線”,它也想成為 Leader,所以也先給自己投一張贊成票,再分別向 S1 和 S2 發(fā)送命令,表示要成為 Leader。
在 T3 時刻,S1 收到了 S3 的 Leader 投票請求。因為 S1 已經(jīng)給自己投了一票 Y,所以它不能再給其他哨兵投贊成票了,所以 S1 回復(fù) N 表示不同意。同時,S2 收到了 T2 時 S3 發(fā)送的 Leader 投票請求。因為 S2 之前沒有投過票,它會給第一個向它發(fā)送投票請求的哨兵回復(fù) Y,給后續(xù)再發(fā)送投票請求的哨兵回復(fù) N,所以,在 T3 時,S2 回復(fù) S3,同意 S3 成為 Leader。
在 T4 時刻,S2 才收到 T1 時 S1 發(fā)送的投票命令。因為 S2 已經(jīng)在 T3 時同意了 S3 的投票請求,此時,S2 給 S1 回復(fù) N,表示不同意 S1 成為 Leader。發(fā)生這種情況,是因為 S3 和 S2 之間的網(wǎng)絡(luò)傳輸正常,而 S1 和 S2 之間的網(wǎng)絡(luò)傳輸可能正好擁塞了,導(dǎo)致投票請求傳輸慢了。
最后,在 T5 時刻,S1 得到的票數(shù)是來自它自己的一票 Y 和來自 S2 的一票 N。而 S3 除了自己的贊成票 Y 以外,還收到了來自 S2 的一票 Y。此時,S3 不僅獲得了半數(shù)以上的 Leader 贊成票,也達(dá)到預(yù)設(shè)的 quorum 值(quorum 為 2),所以它最終成為了 Leader。接著,S3 會開始執(zhí)行選主操作,而且在選定新主庫后,會給其他從庫和客戶端通知新主庫的信息。
如果 S3 沒有拿到 2 票 Y,那么這輪投票就不會產(chǎn)生 Leader。哨兵集群會等待一段時間(也就是哨兵故障轉(zhuǎn)移超時時間的 2 倍),再重新選舉。這是因為,哨兵集群能夠進(jìn)行成功投票,很大程度上依賴于選舉命令的正常網(wǎng)絡(luò)傳播。如果網(wǎng)絡(luò)壓力較大或有短時堵塞,就可能導(dǎo)致沒有一個哨兵能拿到半數(shù)以上的贊成票。所以,等到網(wǎng)絡(luò)擁塞好轉(zhuǎn)之后,再進(jìn)行投票選舉,成功的概率就會增加。
需要注意的是,如果哨兵集群只有 2 個實例,此時,一個哨兵要想成為 Leader,必須獲得 2 票,而不是 1 票。所以,如果有個哨兵掛掉了,那么,此時的集群是無法進(jìn)行主從庫切換的。因此,通常我們至少會配置 3 個哨兵實例。這一點很重要,你在實際應(yīng)用時可不能忽略了。
哨兵不會同時投票給自己的原因?
要發(fā)生S1、S2和S3同時同自己投票的情況,這需要這三個哨兵基本同時判定了主庫客觀下線。但是,不同哨兵的網(wǎng)絡(luò)連接、系統(tǒng)壓力不完全一樣,接收到下線協(xié)商消息的時間也可能不同,所以,它們同時做出主庫客觀下線判定的概率較小,一般都有個先后關(guān)系。文章中的例子,就是S1、S3先判定,S2一直沒有判定。
哨兵對主從庫進(jìn)行的在線狀態(tài)檢查等操作,是屬于一種時間事件,用一個定時器來完成,一般來說每100ms執(zhí)行一次這些事件。每個哨兵的定時器執(zhí)行周期都會加上一個小小的隨機(jī)時間偏移,目的是讓每個哨兵執(zhí)行上述操作的時間能稍微錯開些,也是為了避免它們都同時判定主庫下線,同時選舉Leader。
Redis 1主4從,5個哨兵,哨兵配置quorum為2,如果3個哨兵故障,當(dāng)主庫宕機(jī)時,哨兵能否判斷主庫“客觀下線”?能否自動切換?
1、哨兵集群可以判定主庫“主觀下線”。由于quorum=2,所以當(dāng)一個哨兵判斷主庫“主觀下線”后,詢問另外一個哨兵后也會得到同樣的結(jié)果,2個哨兵都判定“主觀下線”,達(dá)到了quorum的值,因此,哨兵集群可以判定主庫為“客觀下線”。
2、但哨兵不能完成主從切換。哨兵標(biāo)記主庫“客觀下線后”,在選舉“哨兵領(lǐng)導(dǎo)者”時,一個哨兵必須拿到超過多數(shù)的選票(5/2+1=3票)。但目前只有2個哨兵活著,無論怎么投票,一個哨兵最多只能拿到2票,永遠(yuǎn)無法達(dá)到多數(shù)選票的結(jié)果。
哨兵實例是不是越多越好?
- 并不是,我們也看到了,哨兵在判定“主觀下線”和選舉“哨兵領(lǐng)導(dǎo)者”時,都需要和其他節(jié)點進(jìn)行通信,交換信息,哨兵實例越多,通信的次數(shù)也就越多,而且部署多個哨兵時,會分布在不同機(jī)器上,節(jié)點越多帶來的機(jī)器故障風(fēng)險也會越大,這些問題都會影響到哨兵的通信和選舉,出問題時也就意味著選舉時間會變長,切換主從的時間變久。
- 哨兵實例越多,誤判率會越低,但是在判定主庫下線和選舉Leader時,實例需要拿到的贊成票數(shù)也越多,等待所有哨兵投完票的時間可能也會相應(yīng)增加,主從庫切換的時間也會變長,客戶端容易堆積較多的請求操作,可能會導(dǎo)致客戶端請求溢出,從而造成請求丟失。如果業(yè)務(wù)層對Redis的操作有響應(yīng)時間要求,就可能會因為新主庫一直沒有選定,新操作無法執(zhí)行而發(fā)生超時報警。
- 調(diào)大down-after-milliseconds后,可能會導(dǎo)致這樣的情況:主庫實際已經(jīng)發(fā)生故障了,但是哨兵過了很長時間才判斷出來,這就會影響到Redis對業(yè)務(wù)的可用性。
調(diào)大down-after-milliseconds值,對減少誤判是不是有好處?
是有好處的,適當(dāng)調(diào)大down-after-milliseconds值,當(dāng)哨兵與主庫之間網(wǎng)絡(luò)存在短時波動時,可以降低誤判的概率。但是調(diào)大down-after-milliseconds值也意味著主從切換的時間會變長,對業(yè)務(wù)的影響時間越久,我們需要根據(jù)實際場景進(jìn)行權(quán)衡,設(shè)置合理的閾值。
3.總結(jié):哨兵關(guān)鍵機(jī)制(哨兵聯(lián)系主從客哨兵,Leader選主)
我們在解決一個系統(tǒng)問題的時候,會引入一個新機(jī)制,或者設(shè)計一層新功能,哨兵主要內(nèi)容:為了實現(xiàn)主從切換,我們引入了哨兵;為了避免單個哨兵故障后無法進(jìn)行主從切換,以及為了減少誤判率,又引入了哨兵集群;哨兵集群又需要有一些機(jī)制來支撐它的正常運(yùn)行。
3.1哨兵集群的這些關(guān)鍵機(jī)制
- 基于 pub/sub 機(jī)制的哨兵集群組成過程;
- 基于 INFO 命令的從庫列表,這可以幫助哨兵和從庫建立連接;
- 基于哨兵自身的 pub/sub 功能,這實現(xiàn)了客戶端和哨兵之間的事件通知。
對于主從切換,當(dāng)然不是哪個哨兵想執(zhí)行就可以執(zhí)行的,否則就亂套了。所以,這就需要哨兵集群在判斷了主庫“客觀下線”后,經(jīng)過投票仲裁,選舉一個 Leader 出來,由它負(fù)責(zé)實際的主從切換,即由它來完成新主庫的選擇以及通知從庫與客戶端。
最后,我想再給你分享一個經(jīng)驗:要保證所有哨兵實例的配置是一致的,尤其是主觀下線的判斷值 down-after-milliseconds。這個值在不同的哨兵實例上配置不一致,導(dǎo)致哨兵集群一直沒有對有故障的主庫形成共識,也就沒有及時切換主庫,最終的結(jié)果就是集群服務(wù)不穩(wěn)定。所以,你一定不要忽略這條看似簡單的經(jīng)驗。
三.哨兵全部總結(jié)
1.哨兵怎么跟主庫連接
哨兵與主庫直接相關(guān)聯(lián),手動設(shè)置,可以設(shè)置多個哨兵
2.哨兵怎么給從庫發(fā)消息
哨兵給主庫發(fā)送info命令,主庫返回從庫的slave集合,與從庫建立連接,把新主庫的信息發(fā)送給從庫
3.哨兵怎么跟客戶端聯(lián)系
client訂閱Sentinel的某一個頻道,該頻道里有誰是master的信息,讀取哨兵的配置文件,獲取ip地址和端口號,與哨兵建立連接,連接之后訂閱信息,獲取主庫信息,并與主庫建立連接
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Redis監(jiān)控工具RedisInsight安裝與使用
這篇文章主要為大家介紹了Redis監(jiān)控工具RedisInsight的安裝步驟與使用方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-03-03
小白也能看懂的Redis遍歷鍵和數(shù)據(jù)庫管理詳解
這篇文章主要為大家介紹了小白也能看懂的Redis遍歷鍵和數(shù)據(jù)庫管理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10
RedisDesktopManager遠(yuǎn)程連接redis的實現(xiàn)
本文主要介紹了RedisDesktopManager遠(yuǎn)程連接redis的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05
Redis基礎(chǔ)學(xué)習(xí)之管道機(jī)制詳析
這篇文章主要給大家介紹了關(guān)于Redis基礎(chǔ)學(xué)習(xí)之管道機(jī)制的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Redis具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-11-11
基于Redis實現(xiàn)共享Session登錄的實現(xiàn)
本文主要介紹了基于Redis實現(xiàn)共享Session登錄的實現(xiàn),包括發(fā)送短信驗證碼、短信驗證碼登錄和注冊、以及登錄狀態(tài)校驗的流程,具有一定的參考價值,感興趣的可以了解一下2025-03-03

