咱們都瞭解 Redis主從庫集羣模式。在這個模式下,若是從庫發生故障了,客戶端能夠繼續向主庫或其餘從庫發送請求,進行相關的操做,可是若是主庫發生故障了,那就直接會影響到從庫的同步,由於從庫沒有相應的主庫能夠進行數據複製操做了。網絡
並且,若是客戶端發送的都是讀操做請求,那還能夠由從庫繼續提供服務,這在純讀的業務場景下還能被接受。可是,一旦有寫操做請求了,按照主從庫模式下的讀寫分離要求,須要由主庫來完成寫操做。此時,也沒有實例能夠來服務客戶端的寫操做請求了,以下圖所示:運維
不管是寫服務中斷,仍是從庫沒法進行數據同步,都是不能接受的。因此,若是主庫掛了,咱們就須要運行一個新主庫,好比說把一個從庫切換爲主庫,把它當成主庫。這就涉及到三個問題:ide
主庫真的掛了嗎?spa
該選擇哪一個從庫做爲主庫?3d
怎麼把新主庫的相關信息通知給從庫和客戶端呢?blog
這就要提到哨兵機制了。在 Redis 主從集羣中,哨兵機制是實現主從庫自動切換的關鍵機制,它有效地解決了主從複製模式下故障轉移的這三個問題。進程
哨兵機制的基本流程圖片
哨兵其實就是一個運行在特殊模式下的 Redis 進程,主從庫實例運行的同時,它也在運行。哨兵主要負責的就是三個任務:監控、選主(選擇主庫)和通知。內存
咱們先看監控。監控是指哨兵進程在運行時,週期性地給全部的主從庫發送 PING 命令,檢測它們是否仍然在線運行。若是從庫沒有在規定時間內響應哨兵的 PING 命令,哨兵就會把它標記爲「下線狀態」;一樣,若是主庫也沒有在規定時間內響應哨兵的 PING 命令,哨兵就會斷定主庫下線,而後開始自動切換主庫的流程。ci
這個流程首先是執行哨兵的第二個任務,選主。主庫掛了之後,哨兵就須要從不少個從庫裏,按照必定的規則選擇一個從庫實例,把它做爲新的主庫。這一步完成後,如今的集羣裏就有了新主庫。
而後,哨兵會執行最後一個任務:通知。在執行通知任務時,哨兵會把新主庫的鏈接信息發給其餘從庫,讓它們執行 replicaof 命令,和新主庫創建鏈接,並進行數據複製。同時,哨兵會把新主庫的鏈接信息通知給客戶端,讓它們把請求操做發到新主庫上。
我畫了一張圖片,展現了這三個任務以及它們各自的目標。
在這三個任務中,通知任務相對來講比較簡單,哨兵只須要把新主庫信息發給從庫和客戶端,讓它們和新主庫創建鏈接就行,並不涉及決策的邏輯。可是,在監控和選主這兩個任務中,哨兵須要作出兩個決策:
在監控任務中,哨兵須要判斷主庫是否處於下線狀態;
在選主任務中,哨兵也要決定選擇哪一個從庫實例做爲主庫。
接下來,咱們就先說說如何判斷主庫的下線狀態。
你首先要知道的是,哨兵對主庫的下線判斷有「主觀下線」和「客觀下線」兩種。那麼,爲何會存在兩種判斷呢?它們的區別和聯繫是什麼呢?
主觀下線和客觀下線
哨兵進程會使用 PING 命令檢測它本身和主、從庫的網絡鏈接狀況,用來判斷實例的狀態。若是哨兵發現主庫或從庫對 PING 命令的響應超時了,那麼,哨兵就會先把它標記爲「主觀下線」。
若是檢測的是從庫,那麼,哨兵簡單地把它標記爲「主觀下線」就好了,由於從庫的下線影響通常不太大,集羣的對外服務不會間斷。
可是,若是檢測的是主庫,那麼,哨兵還不能簡單地把它標記爲「主觀下線」,開啓主從切換。由於頗有可能存在這麼一個狀況:那就是哨兵誤判了,其實主庫並無故障。但是,一旦啓動了主從切換,後續的選主和通知操做都會帶來額外的計算和通訊開銷。
爲了不這些沒必要要的開銷,咱們要特別注意誤判的狀況。
首先,咱們要知道啥叫誤判。很簡單,就是主庫實際並無下線,可是哨兵誤覺得它下線了。誤判通常會發生在集羣網絡壓力較大、網絡擁塞,或者是主庫自己壓力較大的狀況下。
一旦哨兵判斷主庫下線了,就會開始選擇新主庫,並讓從庫和新主庫進行數據同步,這個過程自己就會有開銷,例如,哨兵要花時間選出新主庫,從庫也須要花時間和新主庫同步。而在誤判的狀況下,主庫自己根本就不須要進行切換的,因此這個過程的開銷是沒有價值的。正由於這樣,咱們須要判斷是否有誤判,以及減小誤判。
那怎麼減小誤判呢?在平常生活中,當咱們要對一些重要的事情作判斷的時候,常常會和家人或朋友一塊兒商量一下,而後再作決定。
哨兵機制也是相似的,它一般會採用多實例組成的集羣模式進行部署,這也被稱爲哨兵集羣。引入多個哨兵實例一塊兒來判斷,就能夠避免單個哨兵由於自身網絡情況很差,而誤判主庫下線的狀況。同時,多個哨兵的網絡同時不穩定的機率較小,由它們一塊兒作決策,誤判率也能下降。
如何選定新主庫?
通常來講,我把哨兵選擇新主庫的過程稱爲「篩選 + 打分」。簡單來講,咱們在多個從庫中,先按照必定的篩選條件,把不符合條件的從庫去掉。而後,咱們再按照必定的規則,給剩下的從庫逐個打分,將得分最高的從庫選爲新主庫,以下圖所示:
第一輪:優先級最高的從庫得分高。
用戶能夠經過 slave-priority 配置項,給不一樣的從庫設置不一樣優先級。好比,你有兩個從庫,它們的內存大小不同,你能夠手動給內存大的實例設置一個高優先級。在選主時,哨兵會給優先級高的從庫打高分,若是有一個從庫優先級最高,那麼它就是新主庫了。若是從庫的優先級都同樣,那麼哨兵開始第二輪打分。
第二輪:和舊主庫同步程度最接近的從庫得分高。
這個規則的依據是,若是選擇和舊主庫同步最接近的那個從庫做爲主庫,那麼,這個新主庫上就有最新的數據。
第三輪:ID 號小的從庫得分高。
每一個實例都會有一個 ID,這個 ID 就相似於這裏的從庫的編號。目前,Redis 在選主庫時,有一個默認的規定:在優先級和複製進度都相同的狀況下,ID 號最小的從庫得分最高,會被選爲新主庫。
總結
哨兵機制,它是實現 Redis 不間斷服務的重要保證。具體來講,主從集羣的數據同步,是數據可靠的基礎保證;而在主庫發生故障時,自動的主從切換是服務不間斷的關鍵支撐。
Redis 的哨兵機制自動完成了如下三大功能,從而實現了主從庫的自動切換,能夠下降 Redis 集羣的運維開銷:
監控主庫運行狀態,並判斷主庫是否客觀下線;
在主庫客觀下線後,選取新主庫;
選出新主庫後,通知從庫和客戶端。