目錄
一、前言
二、哨兵
1、是什么?
2、哨兵的功能
3、案例演示
Redis Sentinel 架構
配置說明
哨兵配置文件
主從配置文件
主節點宕機后各節點狀態
主從切換后配置文件的自動調整
4、哨兵運行流程和選舉原理
SDOWN主觀下線
ODOWN客觀下線
?選出新的主節點
哨兵領導者選舉流程
新主節點選舉
5、哨兵架構的缺陷
一、前言
上篇文章中,我們提到了Redis單機模式下的問題,并且引入了Redis的主從復制架構,從主從復制的配置談起,并且演示了Redis的一主二從的架構,提到了兩種實現主從復制的方案,且大致介紹了主從復制的原理和流程。
- 雖然Redis支持主從復制實現數據冗余,但當主節點故障時,需要人工干預進行故障轉移,無法自動恢復服務。
- 我們在生產環境中,需要保證Redis服務在節點故障時能夠自動恢復,減少人工干預和停機時間。
- 需要持續監控Redis實例的健康狀態,及時發現潛在問題。
基于上面情況的考慮,我們是不是可以大膽假設一下,如果有一個東西能自動幫我們監控Redis的實例的狀態,并且在主節點宕機的時候立即幫我們重新設置一個新的主節點,這樣就大大減少了人工干預所浪費的時間。
這就是本文的主題--Redis哨兵
二、哨兵
1、是什么?
主從模式中,一旦主節點由于故障不能提供服務,需要人工將從節點晉升為主節點,同時還要通知應用方更新主節點地址。顯然,多數業務場景都不能接受這種故障處理方式。Redis從2.8開始正式提供了Redis Sentinel(哨兵)架構來解決這個問題,它是一個分布式系統,用于監控Redis主從實例的健康狀態,在主從復制的基礎上,哨兵引入了主節點的自動故障轉移。
?哨兵會巡查監控后臺master主機是否故障,如果故障了根據投票數自動將某一個從庫轉換為新主庫,繼續對外服務,俗稱無人值守運維
下圖展示了一個Redis哨兵架構圖,其中紅色方塊代表主節點,負責處理讀寫請求。黃色方塊代表從節點,通過 replication 從主節點同步數據。灰色方塊代表哨兵節點,有三個哨兵,這是官方建議的最小的哨兵數量,為了避免單點故障。?哨兵通過虛線箭頭持續監控主節點和從節點的健康狀態,如心跳檢測
?
?
2、哨兵的功能
??
- 主從監控
- 監控主從redis庫運行是否正常
- 消息通知
- 哨兵可以將故障轉移的結果發送到客戶端
- 故障轉移
- 如果master異常,則會進行主從切換,將其中一個slave作為新master
- 配置中心
- 客戶端通過連接哨兵來獲得當前Redis服務的主節點地址
3、案例演示
Redis Sentinel 架構
主從架構還是采用上篇文章中的一主二從架構,另外再增加三個哨兵,自動監控和維護集群,不存放數據,只是監控。
上圖展示了 Redis Sentinel 的架構,需要注意的是?由于虛擬機運行內存問題,這次演示是將哨兵放在一臺機器上,真正部署項目時要分開。
配置說明
1、在 /myredis 目錄新建或者拷貝 sentinel.conf
2、redis解壓目錄下默認的sentinel.conf文件如下
3、sentinel.conf 文件配置
- bind 服務監聽地址,用于客戶端連接
- daemonize 是否以后臺daemon方式運行
- protected-mode 安全保護模式
- port 端口
- logfile 日志文件路徑
- pidfile pid日志路徑
- dir 工作目錄
重點參數項說明
sentinel monitor <master-name> <ip> <redis-port> <quorum>
- 設置要監控的master服務器。
- quorum 表示最少有幾個哨兵認可客觀下線,同意故障遷移的法定票數。
我們知道,網絡是不可靠的,有時候一個 sentinel 會因為網絡堵塞而誤以為一個 master redis 已經死掉了,在 sentinel 集群環境下需要多個 sentinel 互相溝通來確認某個 master?是否真的死了,quorum 這個參數是進行客觀下線的一個依據,意思是至少有 quorum 個 sentinel 認為這個 master有故障,才會對這個 master 進行下線以及故障轉移。因為有的時候,某個 sentinel 節點可能因為自身網絡原因,導致無法連接 master,而此時 master 并沒有出現故障,所以,這就需要多個sentinel 都一致認為該 master 有問題,才可以進行下一步操作,這就保證了公平性和高可用。
sentinel auth-pass <master-name> <password> //如果master設置了密碼,連接master服務的密碼sentinel down-after-milliseconds <master-name> <milliseconds> //指定多少毫秒之后,主節點沒有應答哨兵,此時哨兵主觀上認為主節點下線sentinel parallel-syncs <master-name> <nums>: //表示允許并行同步的slave個數,當Master掛了后,哨兵會選出新的Master, //此時,剩余的slave會向新的master發起同步數據sentinel failover-timeout <master-name> <milliseconds>: //故障轉移的超時時間,進行故障轉移時,如果超過設置的毫秒,表示故障轉移失敗sentinel notification-script <master-name> <script-path> : //配置當某一事件發生時所需要執行的腳本sentinel client-reconfig-script <master-name> <script-path>: //客戶端重新配置主節點參數腳本
哨兵配置文件
三臺哨兵配置如下
由于機器硬件關系,三個哨兵都同時配置在192.168.111.169同一臺機器上:
- sentinel26379.conf
- sentinel26380.conf
- sentinel26381.conf
這些文件中都是我們自己要填寫的,內容如下
- sentinel26379.conf
-
sentinel26380.conf
-
- sentienl26381.conf
主從配置文件
接下來一主二從架構如下
需要注意的是,我們測試主機宕機的情況,所有6379后續可能會變成從機,需要設置訪問新主機的密碼,?設置masterauth項訪問密碼為111111,
不然后續可能報錯master_link_status:down
主機 redis6379.conf
從機?redis6380.conf
從機?redis6381.conf
啟動一主二從
6379.confredis-server /myredis/redis6379.conf redis-cli -a 1234566380.confredis-server /myredis/redis6380.conf redis-cli -a 123456 -p 63806381.confredis-server /myredis/redis6381.conf redis-cli -a 123456 -p 6381
啟動哨兵
redis-sentinel sentinel26379.conf --sentinel
redis-sentinel sentinel26380.conf --sentinel
redis-sentinel sentinel26381.conf --sentinel
完成一次主從復制,可以看到沒什么問題
主節點宕機后各節點狀態
下面手動關閉6379主機,模仿主機意外宕機
查看 6379 的主從信息
觀察從機6380
“Broken pipe”錯誤通常表示客戶端與服務器之間的連接被意外中斷。錯誤發生后,客戶端顯示not connected,表明與Redis服務器的連接已經斷開。
類別 | 內容 |
---|---|
認識 broken pipe | pipe 是管道的意思,管道里面是數據流,通常是從文件或網絡套接字讀取的數據。當該管道從另一端突然關閉時,會發生數據突然中斷,即是 broken,對于 socket 來說,可能是網絡被拔出或另一端的進程崩潰 |
解決問題 | 其實當該異常產生的時候,對于服務端來說,并沒有多少影響。因為可能是某個客戶端突然中止了進程導致了該錯誤 |
總結 Broken Pipe | 這個異常是客戶端讀取超時關閉了連接,這時候服務器端再向客戶端已經斷開的連接寫數據時就發生了 broken pipe 異常! |
觀察從機 6381?
接下來查看三臺哨兵的日志文件
- sentinel26379
- sentinel26380
- sentinel26381
以sentinel26379的日志為例,解釋圖
1. Sentinel ID
- Sentinel ID is 293208ae686ecf0d5e90ba7c66a1692061e410e2:
- 這是當前Sentinel實例的唯一標識符,用于區分不同的Sentinel節點。
2. 監控主節點
- +monitor master mymaster 192.168.111.169 6379 quorum 2:
- Sentinel開始監控名為mymaster 的主節點,其IP地址為192.168.111.169,端口為
6379
。- quorum 2表示至少需要2個Sentinel節點同意才能進行故障轉移。
3. 發現從節點
- +slave slave 192.168.111.172:6380 192.168.111.172 6380 @ mymaster 192.168.111.169 6379:
- Sentinel發現了從節點192.168.111.172 6380,該節點屬于主節點mymaster。
4. 新配置保存到磁盤
- Sentinel new configuration saved on disk:
- Sentinel將新的配置信息保存到了磁盤上,確保配置的持久化。
5. 主節點下線
- +sdown master mymaster 192.168.111.169 6379:
- Sentinel檢測到主節點?mymaster?主觀下線(Subjectively Down, SDOWN),即某個Sentinel認為主節點不可用。
6. 故障轉移準備
- #new-epoch 1:
- Sentinel進入新的紀元(Epoch),這是為了確保在故障轉移過程中的一致性。
- vote-for-leader 90bb3177d97028772b2358444efcd407024f0664 1:
- Sentinel參與選舉新的領導者,以協調故障轉移過程。
7. 主節點客觀下線
- #odown master mymaster 192.168.111.169 6379 #quorum 3/2:
- 至少有3個Sentinel節點(超過quorum?2)確認主節點客觀下線(Objectively Down, ODOWN),即大多數Sentinel都認為主節點不可用。
8. 故障轉移延遲
- Next failover delay: I will not start a failover before Fri Jul 1 11:54:24 2022:
- Sentinel決定在指定時間之前不啟動故障轉移,可能是為了避免頻繁的故障轉移操作。
9. 配置更新和主節點切換
- config-update-from sentinel 90bb3177d97028772b2358444efcd407024f0664 192.168.111.169 26380 @ mymaster 192.168.111.169 6379:
- 從其他Sentinel節點接收配置更新。
- switch-master mymaster 192.168.111.169 6379 192.168.111.173 6381:
- 將主節點切換為192.168.111.173 6381,完成故障轉移。
10. 從節點狀態更新
- +slave slave 192.168.111.172:6380 192.168.111.172 6380 @ mymaster 192.168.111.173 6381:
- 更新從節點的狀態,使其連接到新的主節點。
再次查看 6381 節點的主從信息,可以看到如上面哨兵的日志文件所述,本次是將6381選為新的主機。再次重啟6379(之前的主節點)之后,發現此時它已經成為了6381的從節點
對于6380來說,它依然是從節點,但是它的上級主節點已經從6379換成了6381.
主從切換后配置文件的自動調整
!***!最后還需要注意的是在Redis Sentinel架構中,當發生Master-Slave切換時,相關的配置文件會自動進行相應的調整,以適應新的集群狀態。這種動態調整機制保證了Redis集群的高可用性和一致性。
- 當Master-Slave切換完成后,以下三個配置文件的內容會發生改變:
- 新上任的從節點的配置文件
- 原主節點的配置文件
- Sentinel的配置文件
具體來說,對于新上任的主節點(6381)的配置文件
- 在成為主節點之前,?redis6381.conf 文件中會包含一行?replicaof 192.168.111.169 6379的配置,用于指定其主節點為6379。
- 當該節點被選舉為新的主節點后,Redis Sentinel 會自動刪除或注釋掉這一行配置,因為新主節點不再需要作為副本(replica)從其他節點同步數據。
對于之前的的主節點(6379)的配置文件
- 原來的主節點在切換后變為從節點,其配置文件中會新增一行?replicaof??192.168.111.169 6381?配置,指定新的主節點地址和端口。
對于哨兵配置文件 sentinel.conf
- Sentinel的監控目標會隨之調整,以反映新的主從關系。原本監控舊主節點的配置會被更新為監控新主節點。
- 需要注意的是首次配置 Sentinel 時,會使用類似?sentinel monitor mymaster 192.168.111.169 6379 2?? 的命令。這行配置告訴 Sentinel:“請開始監控一個名為mymaster的主節點,它當前的地址是 192.168.111.169 6379”。
-
故障轉移后的變化:
- 當發生故障轉移后,Sentinel 集群會達成共識,將一個從節點?192.168.111.169 6381提升為新的主節點。
- sentinel.conf?文件本身可能不會重寫最初的?sentinel monitor?那一行(即它可能還是?
...
192.168.111.169 6379...),但這行配置的“意義”已經通過 Sentinel 的內部狀態和后續的持久化信息被覆蓋了。 - 關鍵變化在于 Sentinel 會將新的主節點信息持久化到配置文件中。在?sentinel.conf?文件里會看到類似這樣的新行被自動添加:
-
master mymaster 192.168.111.173 6381 //這行 master 記錄明確指出了當前 mymaster //這個邏輯名稱所對應的實際主節點是 192.168.111.173:6381。
因此,Sentinel 的“監控目標”確實是動態調整的,但它不是簡單地修改最初的sentinel monitor?那一行。
它是通過維護一個動態的、持久化的主節點記錄來實現的。Sentinel 在運行時會優先使用這個最新的?master? mymaster
...
?記錄來確定當前的主節點是誰。即使最初的?sentinel monitor?行沒有改變,Sentinel 的實際監控行為已經完全指向了新的主節點。
4、哨兵運行流程和選舉原理
當一個主從配置中的master失效之后,sentinel可以選舉出一個新的master用于自動接替原master的工作,主從配置中的其他redis服務器自動指向新的master同步數據。
一般建議sentinel采用奇數臺,哨兵集群的可靠性依賴于 “多數投票機制”,而奇數個哨兵節點是確保這一機制有效的關鍵。
SDOWN主觀下線
所謂主觀下線(Subjectively Down, 簡稱 SDOWN)指的是單個Sentinel實例對服務器做出的下線判斷,即單個sentinel認為某個服務下線(有可能是接收不到訂閱,之間的網絡不通等等原因)。主觀下線就是說如果服務器在[sentinel down-after-milliseconds]給定的毫秒數之內沒有回應PING命令或者返回一個錯誤消息, 那么這個Sentinel會主觀的(單方面的)認為這個master不可以用了
- sentinel down-after-milliseconds <masterName> <timeout>
- ?表示master被當前sentinel實例認定為失效的間隔時間,這個配置其實就是進行主觀下線的一個依據
- master在多長時間內一直沒有給Sentine返回有效信息,則認定該master主觀下線。也就是說如果多久沒聯系上redis-servevr,認為這個redis-server進入到失效(SDOWN)狀態。
ODOWN客觀下線
- ODOWN需要一定數量的sentinel,多個哨兵達成一致意見才能認為一個master客觀上已經宕機
在前面的哨兵配置文件中見到過<quorum>這個參數,
這個參數是進行客觀下線的一個依據,法定人數/法定票數
意思是至少有quorum個sentinel認為這個master有故障才會對這個master進行下線以及故障轉移。因為有的時候,某個sentinel節點可能因為自身網絡原因導致無法連接master,而此時master并沒有出現故障,所以這就需要多個sentinel都一致認為該master有問題,才可以進行下一步操作,這就保證了公平性和高可用。
?選出新的主節點
-
當主節點被判斷客觀下線以后,各個哨兵節點會進行協商,先選舉出一個領導者哨兵節點并由該領導者節點進行failover(故障遷移)
哨兵領導者選舉流程
監視該主節點的所有哨兵都有可能被選為領導者,選舉使用的算法是Raft算法;Raft算法的基本思路是先到先得:
即在一輪選舉中,哨兵A向B發送成為領導者的申請,如果B沒有同意過其他哨兵,則會同意A成為領導者
新主節點選舉
由領導者節點開始推動故障轉移并選出一個新master
故障轉移步驟
1、選舉新主節點
- 優先級最高:指從節點配置 replica-priority(Redis 5.0前叫 slave-priority,值越小優先級越高,默認100),優先級最高的從節點優先被選中(如配置為50的從節點 > 配置為100的節點)。
- 復制偏移量最大:若優先級相同,選擇與原主節點數據同步最完整的從節點(通過 INFO replication 中的 master_repl_offset 判斷,偏移量越大數據越新)。
- 最小 Run ID:若偏移量也相同,通過 Redis 實例的唯一運行ID(runid,類似身份證號)字典序最小的節點當選(避免平局的兜底規則)。
2、從節點角色切換
- slaveof no one:哨兵領導者向選中的從節點發送此命令,使其停止復制原主節點,升級為獨立主節點
- 其他從節點“臣服”:哨兵領導者向剩余從節點發送 slaveof <新主節點IP> <端口> 命令,讓它們重新指向新主節點,開始同步數據
3、原主節點回歸后的角色處理
- 原主節點因故障下線,恢復后哨兵會自動向其發送 slaveof <新主節點IP> <端口> 命令,使其降級為從節點,從新主節點同步數據(“舊主退位稱臣”)。
- 避免數據沖突:若原主節點恢復后仍以主節點身份運行,會導致“雙主并存”(數據寫入不一致),此設計確保集群只有一個主節點。
****以上的failover都是sentinel自己獨立完成,完全無需人工干預
5、使用建議
- 哨兵節點的數量應為多個,哨兵本身應該集群,保證高可用
- 哨兵節點的數量應該是奇數個
- 各個哨兵節點的配置應該一致
- 如果哨兵節點部署在Docker等容器里,要注意端口的正確映射
- 哨兵集群+主從復制,并不能保證數據零丟失
6、哨兵架構的缺陷
- 單主節點寫入壓力:哨兵模式本質仍是“一主多從”架構,所有寫入操作集中在單個主節點,無法橫向擴展寫入性能(主節點CPU、內存、網絡帶寬易成為瓶頸)。
- 存儲容量限制:單主節點的存儲容量受限于單臺服務器的硬件配置(如最大內存),無法通過增加從節點擴展數據容量。
- 服務中斷窗口:從主節點故障到新主節點選舉完成(約幾秒到十幾秒),期間寫入操作不可用(讀操作可由從節點分擔,但寫操作完全中斷)。
- 數據丟失風險:若主節點故障前未落盤的數據未同步到從節點,故障轉移后這部分數據會丟失(即使開啟AOF持久化,仍可能因主從同步延遲導致數據不一致)。
針對上述問題,下一篇就該引入Redis的集群的概念了!
感謝閱讀!