三分鐘帶你入門(mén)Redis 高可用架構(gòu)之哨兵
什么是哨兵?
哨兵(Sentinel)是 redis 的高可用性解決方案,前面我們講的主從復(fù)制它是高可用的基礎(chǔ),但是單純的主從復(fù)制需要人工介入才能完成故障轉(zhuǎn)移,哨兵可以解決這個(gè)問(wèn)題,在主從復(fù)制情況下,當(dāng)主節(jié)點(diǎn)發(fā)生故障時(shí),哨兵可以自動(dòng)的發(fā)現(xiàn)故障并且完成故障轉(zhuǎn)移,實(shí)現(xiàn)真正的 redis 高可用。在哨兵集群中,哨兵會(huì)監(jiān)視所有的 redis 服務(wù)器和其他 sentinel 節(jié)點(diǎn)狀態(tài),及時(shí)發(fā)現(xiàn)故障完成轉(zhuǎn)移,從而保證 redis 的高可用。
哨兵群集的搭建
哨兵本質(zhì)也是一個(gè) redis 服務(wù),只是跟普通的 redis 服務(wù)提供了不一樣的功能。哨兵是一個(gè)分布式架構(gòu),因?yàn)槟阋WC redis 高可用,首先需要保證自己高可用,所以如果我們需要搭建哨兵的話,最少需要部署三個(gè)實(shí)例,最好是奇數(shù)個(gè),因?yàn)樵诤罄m(xù)的故障轉(zhuǎn)移中會(huì)涉及到投票。
哨兵的配置文件我們可以在 redis 的 GitHub 項(xiàng)目下下載,在項(xiàng)目下有一個(gè)叫做 sentinel.conf 的文件,可以使用它作為我們哨兵的配置模板,當(dāng)然你也可以使用 redis.conf 配置文件,只需要添加哨兵相關(guān)配置就好了。
哨兵相關(guān)的配置項(xiàng)不多,主要有以下幾個(gè)配置項(xiàng):
- // 端口號(hào),默認(rèn)是 redis 實(shí)例+20000,所以我們沿用這個(gè)規(guī)則就好了
- port 26379
- // 是否守護(hù)進(jìn)程運(yùn)行
- daemonize yes
- // 日志存放的位置,這個(gè)非常重要,通過(guò)日志可以查看故障轉(zhuǎn)移的過(guò)程
- logfile "26379.log"
- // 監(jiān)視一個(gè)名為 mymaster(自定義) 的 redis 主服務(wù)器, 這個(gè)主服務(wù)器的 IP 地址為 127.0.0.1 , 端口號(hào)為 6379 ,
- // 最后面的 2 代表著至少有兩個(gè)哨兵認(rèn)為主服務(wù)器出現(xiàn)故障才會(huì)進(jìn)行故障轉(zhuǎn)移,否則認(rèn)定主服務(wù)未失效
- sentinel monitor mymaster 127.0.0.1 6379 2
- // 哨兵判斷服務(wù)器失效的響應(yīng)時(shí)間,超過(guò)這個(gè)時(shí)間未接收到服務(wù)器的回應(yīng),就認(rèn)為該服務(wù)器失效了
- sentinel down-after-milliseconds mymaster 30000
- // 完成故障轉(zhuǎn)移之后,最多多少個(gè)從服務(wù)器可以同時(shí)發(fā)起數(shù)據(jù)復(fù)制,數(shù)字越小,說(shuō)明完成全部從服務(wù)數(shù)據(jù)復(fù)制的時(shí)間越長(zhǎng)
- // 數(shù)字越大,對(duì)主服務(wù)器的壓力就變大了
- sentinel parallel-syncs mymaster 1
- // 故障轉(zhuǎn)移超時(shí)時(shí)間
- sentinel failover-timeout mymaster 180000
對(duì)于每個(gè) Sentinel 實(shí)例配置除了 port 和 logfile 不同之外,其他配置項(xiàng)都是一樣的。修改好配置后,我們可以使用 ./redis-sentinel sentinel.conf 命令來(lái)啟動(dòng)哨兵,命令跟 redis 實(shí)例啟動(dòng)差不多,因?yàn)樯诒彩?redis 實(shí)例,所以我們可以使用 ./redis-cli -p 26379 info sentinel 命令查看當(dāng)前的哨兵信息,如下圖所示:
哨兵信息
問(wèn)題:如何在只配置 master 服務(wù)器的情況下,發(fā)現(xiàn)從服務(wù)器和其他 Sentinel ?
從服務(wù)器的發(fā)現(xiàn),Sentinel 可以通過(guò)詢問(wèn)主服務(wù)器來(lái)獲取從服務(wù)器的信息,對(duì)于發(fā)現(xiàn)其他 Sentinel 節(jié)點(diǎn),則通過(guò)發(fā)布與訂閱功能實(shí)現(xiàn),通過(guò)向頻道 sentinel:hello 發(fā)送信息來(lái)實(shí)現(xiàn)的,主要有以下兩步:
1、每個(gè) Sentinel 每 2 秒會(huì)通過(guò)發(fā)布與訂閱功能向所有的主服務(wù)和從服務(wù)器的 sentinel:hello 頻道發(fā)送一條信息, 信息中包含了 Sentinel 的 IP 地址、端口號(hào)和運(yùn)行 ID (runid)
2、每個(gè) Sentinel 都訂閱了被它監(jiān)視的所有主服務(wù)器和從服務(wù)器的 sentinel:hello 頻道, 查找之前未出現(xiàn)過(guò)的 sentinel (looking for unknown sentinels)。當(dāng)一個(gè) Sentinel 發(fā)現(xiàn)一個(gè)新的 Sentinel 時(shí), 它會(huì)將新的 Sentinel 添加到一個(gè)列表中, 這個(gè)列表保存了 Sentinel 已知的, 監(jiān)視同一個(gè)主服務(wù)器的所有其他 Sentinel
哨兵故障轉(zhuǎn)移原理
故障轉(zhuǎn)移是哨兵的主要工作,這背后的實(shí)現(xiàn)邏輯也是非常的復(fù)雜,具體的實(shí)現(xiàn)邏輯還請(qǐng)查看相關(guān)書(shū)籍,我對(duì)哨兵的故障轉(zhuǎn)移總結(jié)了以下三點(diǎn):
1、監(jiān)聽(tīng)服務(wù)器
每個(gè) Sentinel 節(jié)點(diǎn)每隔 1 秒對(duì)主節(jié)點(diǎn)、從節(jié)點(diǎn)、其他 Sentinel 節(jié)點(diǎn)發(fā)送 ping 命令做心跳檢測(cè),來(lái)判斷服務(wù)器的狀態(tài)。
節(jié)點(diǎn)也會(huì)對(duì) Sentinel 進(jìn)行相應(yīng)的回復(fù),在這些回復(fù)中,以下三種回復(fù)是有效回復(fù):
- 返回 +PONG
- 返回 -LOADING
- 返回 -MASTERDOWN
如果節(jié)點(diǎn)在哨兵配置文件設(shè)置的 master-down-after-milliseconds 選項(xiàng)的值內(nèi),一直沒(méi)有哪怕一次有效回復(fù),那么 Sentinel 會(huì)把該服務(wù)器標(biāo)記為下線狀態(tài),我們把這種下線稱為主觀下線,也就是說(shuō)只有這個(gè) sentinel 認(rèn)為該服務(wù)器是下線狀態(tài)。
如果被主觀下線的服務(wù)器是主服務(wù)器時(shí),sentinel 為了確認(rèn)這個(gè)主服務(wù)器是否真的下線,該 Sentinel 會(huì)向其他的同樣監(jiān)聽(tīng)主服務(wù)器的 Sentinel 進(jìn)行詢問(wèn),看他們是否也認(rèn)為主服務(wù)器進(jìn)入下線狀態(tài),當(dāng)有足夠多的 Sentinel 都認(rèn)為主服務(wù)器下線時(shí),該 Sentinel 會(huì)將主服務(wù)器判斷為客觀下線,這是真正的下線了,并且會(huì)對(duì)它進(jìn)行故障轉(zhuǎn)移操作。
2、選舉 Sentinel 節(jié)點(diǎn)完成轉(zhuǎn)移任務(wù)
故障轉(zhuǎn)移并不是所有的 sentinel 共同完成,而是選舉出一臺(tái) sentinel 節(jié)點(diǎn)作為領(lǐng)導(dǎo)者來(lái)完成這次故障轉(zhuǎn)移,所以當(dāng)主服務(wù)器被標(biāo)記為客觀下線時(shí),sentinel 之間就會(huì)通過(guò) Raft 算法選舉出一個(gè)領(lǐng)導(dǎo)者來(lái)完成故障轉(zhuǎn)移工作。redis 選舉領(lǐng)頭的 sentinel 的規(guī)則和方法大致如下:
- 所有在線的 sentinel 都有資格被選為領(lǐng)導(dǎo)者,也就是說(shuō)每個(gè) sentinel 都有成為領(lǐng)導(dǎo)者的機(jī)會(huì)
- 當(dāng) sentinel 標(biāo)記主服務(wù)器為主觀下線時(shí),會(huì)向其他 Sentinel 節(jié)點(diǎn)發(fā)送 sentinel is-master-down-by-addr 命令, 要求將自己設(shè)置為領(lǐng)導(dǎo)者
- 收到命令的 Sentinel 節(jié)點(diǎn),采用先到先得的規(guī)則,如果沒(méi)有同意過(guò)其他 Sentinel 節(jié)點(diǎn)的 sentinel is-master-down-by-addr 命令,將同意該請(qǐng)求,否則拒絕
- 如果該 Sentinel 節(jié)點(diǎn)發(fā)現(xiàn)自己的票數(shù)已經(jīng)超過(guò)半數(shù),那么它將成為領(lǐng)導(dǎo)者
- 如果在規(guī)定時(shí)間內(nèi),沒(méi)有選舉出 sentinel 領(lǐng)導(dǎo)者,那么將在一段時(shí)間后再次選舉,知道選出 sentinel 領(lǐng)導(dǎo)者為止。
3、選舉新 master 服務(wù)器完成故障轉(zhuǎn)移
選舉出來(lái)的 sentinel 領(lǐng)導(dǎo)者將完成剩下的故障轉(zhuǎn)移工作,故障轉(zhuǎn)移主要有以下三步:
(1)挑選出新的主服務(wù)器
在已下線的主服務(wù)器的所有從服務(wù)器中,挑選出一個(gè)從服務(wù)器,并將其轉(zhuǎn)換為主服務(wù)器,選擇新的主服務(wù)器的規(guī)則如下:
- 在失效主服務(wù)器屬下的從服務(wù)器當(dāng)中, 那些被標(biāo)記為主觀下線、已斷線、或者最后一次回復(fù) PING 命令的時(shí)間大于五秒鐘的從服務(wù)器都會(huì)被淘汰
- 在失效主服務(wù)器屬下的從服務(wù)器當(dāng)中, 那些與失效主服務(wù)器連接斷開(kāi)的時(shí)長(zhǎng)超過(guò) down-after 選項(xiàng)指定的時(shí)長(zhǎng)十倍的從服務(wù)器都會(huì)被淘汰
- 在經(jīng)歷了以上兩輪淘汰之后剩下來(lái)的從服務(wù)器中, 選出復(fù)制偏移量(replication offset)最大的那個(gè)從服務(wù)器作為新的主服務(wù)器;如果復(fù)制偏移量不可用, 或者從服務(wù)器的復(fù)制偏移量相同, 那么帶有最小運(yùn)行 ID 的那個(gè)從服務(wù)器成為新的主服務(wù)器
對(duì)挑選出來(lái)的從服務(wù)器執(zhí)行 slaveof no one 命令,使其成為主節(jié)點(diǎn)。
(2)修改其他從服務(wù)器的復(fù)制目標(biāo)
當(dāng)新的主服務(wù)器出現(xiàn)后,sentinel 的領(lǐng)導(dǎo)者下一步需要做的就是,讓其他從服務(wù)器去復(fù)制新的主服務(wù)器,通過(guò)向其他從服務(wù)器發(fā)送 slaveof new_master port 命令來(lái)完成,復(fù)制規(guī)則和配置文件的 parallel-syncs 參數(shù)有關(guān)
(3)將舊的主服務(wù)器變成從服務(wù)器
故障轉(zhuǎn)移操作最后要做的就是將已下線的主服務(wù)器設(shè)置為新的主服務(wù)的從服務(wù)器,并保持對(duì)其關(guān)注,等它恢復(fù)后命令它去復(fù)制新的主節(jié)點(diǎn)。
以上就是我今天要分享的 redis 哨兵知識(shí),希望看完之后你有所收獲。