Redis 哨兵模式
點擊藍(lán)色“JavaKeeper”關(guān)注我喲加個“星標(biāo)”,一起成長,做牛逼閃閃的技術(shù)人
Keeper導(dǎo)讀:我們知道 Reids 提供了主從模式的機(jī)制,來保證可用性,可是如果主庫發(fā)生故障了,那就直接會影響到從庫的同步,怎么辦呢?
所以,如果主庫掛了,我們就需要運(yùn)行一個新主庫,比如說把一個從庫切換為主庫,把它當(dāng)成主庫。這就涉及到三個問題:
主庫真的掛了嗎?
該選擇哪個從庫作為主庫?
怎么把新主庫的相關(guān)信息通知給從庫和客戶端呢?
圍繞這 3 個問題,我們來看下不需要人工干預(yù)就可以解決這三個問題的 Redis 哨兵。
一、Redis Sentinel 哨兵

上圖 展示了一個典型的哨兵架構(gòu)圖,它由兩部分組成,哨兵節(jié)點和數(shù)據(jù)節(jié)點:
- 哨兵節(jié)點: 哨兵系統(tǒng)由一個或多個哨兵節(jié)點組成,哨兵節(jié)點是特殊的 Redis 節(jié)點,不存儲數(shù)據(jù);
- 數(shù)據(jù)節(jié)點: 主節(jié)點和從節(jié)點都是數(shù)據(jù)節(jié)點;
在復(fù)制的基礎(chǔ)上,哨兵實現(xiàn)了 自動化的故障恢復(fù) 功能,下面是官方對于哨兵功能的描述:
監(jiān)控(Monitoring): 哨兵會不斷地檢查主節(jié)點和從節(jié)點是否運(yùn)作正常。
監(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 命令,哨兵就會判定主庫下線,然后開始自動切換主庫的流程。
通知(Notification): 當(dāng)被監(jiān)控的某個 Redis 服務(wù)器出現(xiàn)問題時, 哨兵可以通過 API 向管理員或者其他應(yīng)用程序發(fā)送通知。
在執(zhí)行通知任務(wù)時,哨兵會把新主庫的連接信息發(fā)給其他從庫,讓它們執(zhí)行
replicaof命令,和新主庫建立連接,并進(jìn)行數(shù)據(jù)復(fù)制。同時,哨兵會把新主庫的連接信息通知給客戶端,讓它們把請求操作發(fā)到新主庫上。自動故障轉(zhuǎn)移(Automatic failover)/ 選主: 當(dāng) 主節(jié)點 不能正常工作時,哨兵會開始 自動故障轉(zhuǎn)移操作,它會將失效主節(jié)點的其中一個 從節(jié)點升級為新的主節(jié)點,并讓其他從節(jié)點改為復(fù)制新的主節(jié)點。
配置提供者(Configuration provider): 客戶端在初始化時,通過連接哨兵來獲得當(dāng)前 Redis 服務(wù)的主節(jié)點地址。
當(dāng)客戶端試圖連接失效的主服務(wù)器時, 集群也會向客戶端返回新主服務(wù)器的地址, 使得集群可以使用新主服務(wù)器代替失效服務(wù)器。
其中,監(jiān)控和自動故障轉(zhuǎn)移功能,使得哨兵可以及時發(fā)現(xiàn)主節(jié)點故障并完成轉(zhuǎn)移。而配置提供者和通知功能,則需要在與客戶端的交互中才能體現(xiàn)。
二、 Hello Wolrd
2.1 部署主從節(jié)點
哨兵系統(tǒng)中的主從節(jié)點,與普通的主從節(jié)點配置是一樣的,并不需要做任何額外配置。
下面分別是主節(jié)點(port=6379)和 2 個從節(jié)點(port=6380、6381)的配置文件:
#redis.conf??master
port?6379
daemonize?yes
logfile?"6379.log"
dbfilename?"dump-6379.rdb"
#redis_6380.conf
port?6380
daemonize?yes
logfile?"6380.log"
dbfilename?"dump-6380.rdb"
replicaof?127.0.0.1?6379
#redis_6381.conf
port?6381
daemonize?yes
logfile?"6381.log"
dbfilename?"dump-6381.rdb"
replicaof?127.0.0.1?6379
然后我們可以執(zhí)行 redis-server 來根據(jù)配置文件啟動不同的 Redis 實例,依次啟動主從節(jié)點:
redis-server?redis.conf
redis-server?redis_6380.conf?
redis-server?redis_6381.conf
節(jié)點啟動后,我們執(zhí)行 redis-cli 默認(rèn)連接到我們端口為 6379 的主節(jié)點執(zhí)行 info Replication 檢查一下主從狀態(tài)是否正常:(可以看到下方正確地顯示了兩個從節(jié)點)
127.0.0.1:6379>?info?replication
#?Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=154,lag=1
slave1:ip=127.0.0.1,port=6381,state=online,offset=140,lag=1
master_replid:52a58d69125881d3af366d0559439377a70ae879
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:154
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:154
2.2 部署哨兵節(jié)點
按照上面同樣的方法,我們給哨兵節(jié)點也創(chuàng)建三個配置文件。(哨兵節(jié)點本質(zhì)上是特殊的 Redis 節(jié)點,所以配置幾乎沒什么差別,只是在端口上做區(qū)分就好,每個哨兵只需要配置監(jiān)控主節(jié)點,就可以自動發(fā)現(xiàn)其他的哨兵節(jié)點和從節(jié)點)
#?redis-sentinel-26379.conf
port?26379
daemonize?yes
logfile?"26379.log"
sentinel?monitor?mymaster?127.0.0.1?6379?2
#?redis-sentinel-26380.conf
port?26380
daemonize?yes
logfile?"26380.log"
sentinel?monitor?mymaster?127.0.0.1?6379?2
#?redis-sentinel-26381.conf
port?26381
daemonize?yes
logfile?"26381.log"
sentinel?monitor?mymaster?127.0.0.1?6379?2
其中,sentinel monitor mymaster 127.0.0.1 6379 2 配置的含義是:該哨兵節(jié)點監(jiān)控 127.0.0.1:6379 這個主節(jié)點,該主節(jié)點的名稱是 mymaster,最后的 2 的含義與主節(jié)點的故障判定有關(guān):至少需要 2 個哨兵節(jié)點同意,才能判定主節(jié)點故障并進(jìn)行故障轉(zhuǎn)移。
啟動 3 個哨兵節(jié)點:
redis-sentinel?redis-sentinel-26379.conf
redis-sentinel?redis-sentinel-26380.conf
redis-server?redis-sentinel-26381.conf?--sentinel???#等同于?redis-sentinel?redis-sentinel-26381.conf
使用 redis-cil 工具連接哨兵節(jié)點,并執(zhí)行 info Sentinel 命令來查看是否已經(jīng)在監(jiān)視主節(jié)點了:
redis-cli?-p?26380?
127.0.0.1:26380>?info?sentinel
#?Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=127.0.0.1:6379,slaves=2,sentinels=3
此時你打開剛才寫好的哨兵配置文件,你還會發(fā)現(xiàn)出現(xiàn)了一些變化。
2.3 演示故障轉(zhuǎn)移
我們先看下我們啟動的 redis 進(jìn)程,3 個數(shù)據(jù)節(jié)點,3 個哨兵節(jié)點

使用 kill 命令來殺掉主節(jié)點,同時 在哨兵節(jié)點中執(zhí)行 info Sentinel 命令來觀察故障節(jié)點的過程:
如果 剛殺掉瞬間 在哨兵節(jié)點中執(zhí)行 info 命令來查看,會發(fā)現(xiàn)主節(jié)點還沒有切換過來,因為哨兵發(fā)現(xiàn)主節(jié)點故障并轉(zhuǎn)移需要一段時間:
#?第一時間查看哨兵節(jié)點發(fā)現(xiàn)并未轉(zhuǎn)移,還在?6379?端口
127.0.0.1:26379>?info?Sentinel
#?Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=127.0.0.1:6379,slaves=2,sentinels=3
一段時間之后你再執(zhí)行 info 命令,查看,你就會發(fā)現(xiàn)主節(jié)點已經(jīng)切換成了 6381 端口的從節(jié)點:
#?過一段時間之后在執(zhí)行,發(fā)現(xiàn)已經(jīng)切換了?6381?端口
127.0.0.1:26379>?info?Sentinel
#?Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=127.0.0.1:6381,slaves=2,sentinels=3
但同時還可以發(fā)現(xiàn),哨兵節(jié)點認(rèn)為新的主節(jié)點仍然有兩個從節(jié)點 (上方 slaves=2),這是因為哨兵在將 6381 切換成主節(jié)點的同時,將 6379 節(jié)點置為其從節(jié)點。雖然 6379 從節(jié)點已經(jīng)掛掉,但是由于 哨兵并不會對從節(jié)點進(jìn)行客觀下線,因此認(rèn)為該從節(jié)點一直存在。當(dāng) 6379 節(jié)點重新啟動后,會自動變成 6381 節(jié)點的從節(jié)點。
另外,在故障轉(zhuǎn)移的階段,哨兵和主從節(jié)點的配置文件都會被改寫:
- 對于主從節(jié)點: 主要是
slaveof配置的變化,新的主節(jié)點沒有了slaveof配置,其從節(jié)點則slaveof新的主節(jié)點。 - 對于哨兵節(jié)點: 除了主從節(jié)點信息的變化,紀(jì)元(epoch) (記錄當(dāng)前集群狀態(tài)的參數(shù)) 也會變化,紀(jì)元相關(guān)的參數(shù)都 +1 了。
三、哨兵機(jī)制的工作流程
其實哨兵主要負(fù)責(zé)的就是三個任務(wù):監(jiān)控、選主和通知。
在監(jiān)控和選主過程中,哨兵都需要做一些決策,比如
- 在監(jiān)控任務(wù)中,哨兵需要判斷主庫、從庫是否處于下線狀態(tài)
- 在選主任務(wù)中,哨兵也要決定選擇哪個從庫實例作為主庫
這就引出了兩個概念,“主觀下線”和“客觀下線”
3.1 主觀下線和客觀下線
我先解釋下什么是“主觀下線”。
哨兵進(jìn)程會使用 PING 命令檢測它自己和主、從庫的網(wǎng)絡(luò)連接情況,用來判斷實例的狀態(tài)。如果哨兵發(fā)現(xiàn)主庫或從庫對 PING 命令的響應(yīng)超時了,那么,哨兵就會先把它標(biāo)記為“主觀下線”。
如果檢測的是從庫,那么,哨兵簡單地把它標(biāo)記為“主觀下線”就行了,因為從庫的下線影響一般不太大,集群的對外服務(wù)不會間斷。
但是,如果檢測的是主庫,那么,哨兵還不能簡單地把它標(biāo)記為“主觀下線”,開啟主從切換。因為很有可能存在這么一個情況:那就是哨兵誤判了,其實主庫并沒有故障??墒?,一旦啟動了主從切換,后續(xù)的選主和通知操作都會帶來額外的計算和通信開銷。
為了避免這些不必要的開銷,我們要特別注意誤判的情況。
誤判一般會發(fā)生在集群網(wǎng)絡(luò)壓力較大、網(wǎng)絡(luò)擁塞,或者是主庫本身壓力較大的情況下。一旦哨兵判斷主庫下線了,就會開始選擇新主庫,并讓從庫和新主庫進(jìn)行數(shù)據(jù)同步,這個過程本身就會有開銷,例如,哨兵要花時間選出新主庫,從庫也需要花時間和新主庫同步。
那怎么減少誤判呢?
在日常生活中,當(dāng)我們要對一些重要的事情做判斷的時候,經(jīng)常會和家人或朋友一起商量一下,然后再做決定。
哨兵機(jī)制也是類似的,它通常會采用多實例組成的集群模式進(jìn)行部署,這也被稱為哨兵集群。引入多個哨兵實例一起來判斷,就可以避免單個哨兵因為自身網(wǎng)絡(luò)狀況不好,而誤判主庫下線的情況。同時,多個哨兵的網(wǎng)絡(luò)同時不穩(wěn)定的概率較小,由它們一起做決策,誤判率也能降低。
在判斷主庫是否下線時,不能由一個哨兵說了算,只有大多數(shù)的哨兵實例,都判斷主庫已經(jīng)“主觀下線”了,主庫才會被標(biāo)記為“客觀下線”,這個叫法也是表明主庫下線成為一個客觀事實了。這個判斷原則就是:少數(shù)服從多數(shù)。同時,這會進(jìn)一步觸發(fā)哨兵開始主從切換流程。
需要特別注意的是,客觀下線是主節(jié)點才有的概念;如果從節(jié)點和哨兵節(jié)點發(fā)生故障,被哨兵主觀下線后,不會再有后續(xù)的客觀下線和故障轉(zhuǎn)移操作。
3.2 選舉領(lǐng)導(dǎo)者哨兵節(jié)點
當(dāng)主節(jié)點被判斷客觀下線以后,各個哨兵節(jié)點會進(jìn)行協(xié)商,選舉出一個領(lǐng)導(dǎo)者哨兵節(jié)點,并由該領(lǐng)導(dǎo)者節(jié)點對其進(jìn)行故障轉(zhuǎn)移操作。
監(jiān)視該主節(jié)點的所有哨兵都有可能被選為領(lǐng)導(dǎo)者,選舉使用的算法是 Raft 算法;Raft 算法的基本思路是先到先得:即在一輪選舉中,哨兵 A 向 B 發(fā)送成為領(lǐng)導(dǎo)者的申請,如果 B 沒有同意過其他哨兵,則會同意 A 成為領(lǐng)導(dǎo)者。(Raft 算法:https://raft.github.io/)
3.3 故障轉(zhuǎn)移
接著,選舉出的領(lǐng)導(dǎo)者哨兵,開始故障轉(zhuǎn)移操作,大概分 3 步:
- 第一步要做的就是在已下線主服務(wù)器屬下的所有從服務(wù)器中,挑選出一個狀態(tài)良好、數(shù)據(jù)完整的從服務(wù)器
- 第二步,更新主從狀態(tài),向選出的從服務(wù)器發(fā)送
slaveof no one命令,將這個從服務(wù)器轉(zhuǎn)換為主服務(wù)器,并通過slaveof命令讓其他節(jié)點成為其從節(jié)點 - 第三步將已下線的主節(jié)點設(shè)置為從節(jié)點
細(xì)說下第一步的選主過程
一般來說,我把哨兵選擇新主庫的過程稱為“篩選 + 打分”。
篩選就是先過濾掉不健康的從節(jié)點,那些被標(biāo)記為主觀下線、已斷線、或者最后一次回復(fù) PING 命令的時間大于五秒鐘的從服務(wù)器都會被 淘汰。
打分就是按 Redis 給定的三個規(guī)則,給剩下的從庫逐個打分,將得分最高的從庫選為新主庫,這個規(guī)則分別是:
優(yōu)先級最高的從庫得分最高
用戶可以通過
slave-priority配置項,給不同的從庫設(shè)置不同優(yōu)先級。比如,你有兩個從庫,它們的內(nèi)存大小不一樣,你可以手動給內(nèi)存大的實例設(shè)置一個高優(yōu)先級。在選主時,哨兵會給優(yōu)先級高的從庫打高分,如果有一個從庫優(yōu)先級最高,那么它就是新主庫了。如果從庫的優(yōu)先級都一樣,那么哨兵開始第二輪打分。和舊主庫同步程度最接近的從庫得分高
從庫的
slave_repl_offset需要最接近master_repl_offset,即得分最高。ID 號小的從庫得分高
每個實例都會有一個 runid,這個 ID 就類似于這里的從庫的編號。目前,Redis 在選主庫時,有一個默認(rèn)的規(guī)定:在優(yōu)先級和復(fù)制進(jìn)度都相同的情況下,ID 號最小的從庫得分最高,會被選為新主庫。

四、哨兵集群的原理
實際上,一旦多個實例組成了哨兵集群,即使有哨兵實例出現(xiàn)故障掛掉了,其他哨兵還能繼續(xù)協(xié)作完成主從庫切換的工作,包括判定主庫是不是處于下線狀態(tài),選擇新主庫,以及通知從庫和客戶端。
認(rèn)真看到這里的話,應(yīng)該會有個疑問,我們在 hello world 環(huán)節(jié)中只是在哨兵節(jié)點加了一條配置
sentinel?monitor?mymaster?127.0.0.1?6379?2
怎么就能組成一個哨兵集群呢?
一套合理的監(jiān)控機(jī)制是哨兵節(jié)點判定節(jié)點不可達(dá)的重要保證,Redis 哨兵通過三個定時監(jiān)控任務(wù)完成對各個節(jié)點發(fā)現(xiàn)和監(jiān)控:
每隔 10 秒,每個哨兵節(jié)點會向主節(jié)點和從節(jié)點發(fā)送 info 命令獲取最新的拓?fù)浣Y(jié)構(gòu)
這個定時任務(wù)的作用具體可以表現(xiàn)在三個方面:
- 通過向主節(jié)點執(zhí)行 info 命令,獲取從節(jié)點的信息,這也是為什么哨兵節(jié)點不需要顯式配置監(jiān)控從節(jié)點。
- 當(dāng)有新的從節(jié)點加入時都可以立刻感知出來。
- 節(jié)點不可達(dá)或者故障轉(zhuǎn)移后,可以通過 info 命令實時更新節(jié)點拓?fù)湫畔?/li>
每隔 2 秒,每個哨兵節(jié)點會向 Redis 數(shù)據(jù)節(jié)點的 __sentinel__:hello 頻道上發(fā)送該哨兵節(jié)點對于主節(jié)點的判斷以及當(dāng)前哨兵節(jié)點的信息,同時每個哨兵節(jié)點也會訂閱該頻道,來了解其他哨兵節(jié)點以及它們對主節(jié)點的判斷。
這個定時任務(wù)可以完成以下兩個工作:
- 發(fā)現(xiàn)新的哨兵節(jié)點:通過訂閱主節(jié)點的
__sentinel__:hello了解其他的哨兵節(jié)點信息,如果是新加入的哨兵節(jié)點,將該哨兵節(jié)點信息保存起來,并與該哨兵節(jié)點創(chuàng)建連接。 - 哨兵節(jié)點之間交換主節(jié)點的狀態(tài),作為后面客觀下線以及領(lǐng)導(dǎo)者選舉的依據(jù)。
每隔 1 秒,每個哨兵節(jié)點會向主節(jié)點、從節(jié)點、其余哨兵節(jié)點發(fā)送一條 ping 命令做一次心跳檢測,來確認(rèn)這些節(jié)點當(dāng)前是否可達(dá)。
通過這個定時任務(wù),哨兵節(jié)點對主節(jié)點、從節(jié)點、其余哨兵節(jié)點都建立起連接,實現(xiàn)了對每個節(jié)點的監(jiān)控,這個定時任務(wù)是節(jié)點失敗判定的重要依據(jù)
4.1 基于 pub/sub 機(jī)制的哨兵集群組成
哨兵實例之間可以相互發(fā)現(xiàn),要?dú)w功于 Redis 提供的 pub/sub 機(jī)制,也就是 發(fā)布/訂閱 機(jī)制。
哨兵只要和主庫建立起了連接,就可以在主庫上發(fā)布消息了,比如說發(fā)布它自己的連接信息(IP 和端口)。同時,它也可以從主庫上訂閱消息,獲得其他哨兵發(fā)布的連接信息。當(dāng)多個哨兵實例都在主庫上做了發(fā)布和訂閱操作后,它們之間就能知道彼此的 IP 地址和端口。
在主從集群中,主庫上有一個名為 "_ _sentinel_ _:hello" 的頻道,不同哨兵就是通過它來相互發(fā)現(xiàn),實現(xiàn)互相通信的。
舉個例子,具體說明一下。
在下圖中,哨兵 sentinel_26379 把自己的 IP(127.0.0.1)和端口(26379)發(fā)布到頻道上,哨兵 26380 和 26381 訂閱了該頻道。那么此時,其他哨兵就可以從這個頻道直接獲取哨兵 sentinel_26379 的 IP 地址和端口號。通過這個方式,各個哨兵之間就可以建立網(wǎng)絡(luò)連接,哨兵集群就形成了。它們相互間可以通過網(wǎng)絡(luò)連接進(jìn)行通信,比如說對主庫有沒有下線這件事兒進(jìn)行判斷和協(xié)商。

4.2 哨兵和從庫的連接
哨兵除了彼此之間建立起連接形成集群外,還需要和從庫建立連接。這是因為,在哨兵的監(jiān)控任務(wù)中,它需要對主從庫都進(jìn)行心跳判斷,而且在主從庫切換完成后,它還需要通知從庫,讓它們和新主庫進(jìn)行同步。
哨兵是如何知道從庫的 IP 地址和端口的呢?
這是由哨兵向主庫發(fā)送 INFO 命令來完成的。
就像下圖所示,哨兵 sentinel_26380 給主庫發(fā)送 INFO 命令,主庫接受到這個命令后,就會把從庫列表返回給哨兵。接著,哨兵就可以根據(jù)從庫列表中的連接信息,和每個從庫建立連接,并在這個連接上持續(xù)地對從庫進(jìn)行監(jiān)控。senetinel_26379 和 senetinel_26381 可以通過相同的方法和從庫建立連接。

4.3 哨兵和客戶端的連接
但是,哨兵不能只和主、從庫連接。因為,主從庫切換后,客戶端也需要知道新主庫的連接信息,才能向新主庫發(fā)送請求操作。所以,哨兵還需要完成把新主庫的信息告訴客戶端這個任務(wù)。
在實際使用哨兵時,我們有時會遇到這樣的問題:如何在客戶端通過監(jiān)控了解哨兵進(jìn)行主從切換的過程呢?比如說,主從切換進(jìn)行到哪一步了?這其實就是要求,客戶端能夠獲取到哨兵集群在監(jiān)控、選主、切換這個過程中發(fā)生的各種事件。此時,我們?nèi)匀豢梢?strong>依賴 pub/sub 機(jī)制,來幫助我們完成哨兵和客戶端間的信息同步。
從本質(zhì)上說,哨兵就是一個運(yùn)行在特定模式下的 Redis 實例,只不過它并不服務(wù)請求操作,只是完成監(jiān)控、選主和通知的任務(wù)。所以,每個哨兵實例也提供 pub/sub 機(jī)制,客戶端可以從哨兵訂閱消息。
哨兵提供的消息訂閱頻道有很多,不同頻道包含了主從庫切換過程中的不同關(guān)鍵事件。(這里就不一一列出了)
知道了這些頻道之后,你就可以讓客戶端從哨兵這里訂閱消息了。具體的操作步驟是,客戶端讀取哨兵的配置文件后,可以獲得哨兵的地址和端口,和哨兵建立網(wǎng)絡(luò)連接。然后,我們可以在客戶端執(zhí)行訂閱命令,來獲取不同的事件消息。
舉個例子,你可以執(zhí)行如下命令,來訂閱“所有實例進(jìn)入客觀下線狀態(tài)的事件”:
SUBSCRIBE?+odown
當(dāng)然,你也可以執(zhí)行如下命令,訂閱所有的事件:
PSUBSCRIBE?*
五、小結(jié)
Redis 哨兵是 Redis 的高可用實現(xiàn)方案:故障發(fā)現(xiàn)、故障自動轉(zhuǎn)移、配置中心、客戶端通知。
5.1 哨兵機(jī)制其實就有三大功能:
監(jiān)控:監(jiān)控主庫運(yùn)行狀態(tài),并判斷主庫是否客觀下線;
選主:在主庫客觀下線后,選取新主庫;
通知:選出新主庫后,通知從庫和客戶端。
5.2 一個哨兵,實際上可以監(jiān)控多個主節(jié)點,通過配置多條 sentinel monitor 即可實現(xiàn)。
5.3 哨兵集群的關(guān)鍵機(jī)制:
- 哨兵集群是基于 pub/sub 機(jī)制組成的
- 基于 INFO 命令的從庫列表,這可以幫助哨兵和從庫建立連接
- 基于哨兵自身的 pub/sub 功能,這實現(xiàn)了客戶端和哨兵之間的事件通知
Sentinel 與 Redis 主節(jié)點 和 從節(jié)點 交互的命令,主要包括:
| 命令 | 作 用 |
|---|---|
| PING | Sentinel 向 Redis 節(jié)點發(fā)送 PING 命令,檢查節(jié)點的狀態(tài) |
| INFO | Sentinel 向 Redis 節(jié)點發(fā)送 INFO 命令,獲取它的 從節(jié)點信息 |
| PUBLISH | Sentinel 向其監(jiān)控的 Redis 節(jié)點 __sentinel__:hello 這個 channel 發(fā)布 自己的信息 及 主節(jié)點 相關(guān)的配置 |
| SUBSCRIBE | Sentinel 通過訂閱 Redis 主節(jié)點 和 從節(jié)點 的 __sentinel__:hello 這個 channnel,獲取正在監(jiān)控相同服務(wù)的其他 Sentinel 節(jié)點 |
Sentinel 與 Sentinel 交互的命令,主要包括:
| 命令 | 作 用 |
|---|---|
| PING | Sentinel 向其他 Sentinel 節(jié)點發(fā)送 PING 命令,檢查節(jié)點的狀態(tài) |
| SENTINEL:is-master-down-by-addr | 和其他 Sentinel 協(xié)商 主節(jié)點 的狀態(tài),如果 主節(jié)點 處于 SDOWN 狀態(tài),則投票自動選出新的 主節(jié)點 |
5.4 建議
盡可能在不同物理機(jī)上部署 Redis 哨兵所有節(jié)點
Redis 哨兵中的哨兵節(jié)點個數(shù)應(yīng)該為大于等于 3 且最好為奇數(shù)
推薦奇數(shù)個節(jié)點,主要是從成本上考慮,因為,集群中,半數(shù)以上節(jié)點認(rèn)為主節(jié)點故障了,才會選舉新的節(jié)點。這樣的話奇數(shù)個節(jié)點和偶數(shù)個節(jié)點允許宕機(jī)的節(jié)點數(shù)就是一樣的,比如 3 個節(jié)點和 4 個節(jié)點都只允許宕機(jī)一臺,那么為什么要搞 4 個節(jié)點去浪費(fèi)服務(wù)資源呢?但是 4 個節(jié)點的性能和容量肯定是更高的哈。
參考與來源
- 《Redis 開發(fā)與運(yùn)維》
- 《Redis 核心技術(shù)與實戰(zhàn)》
- https://redis.io/topics/sentinel
- https://www.cnblogs.com/kismetv/p/9609938.html


