作用
Redis Sentinel,即Redis哨兵,在Redis 2.8版本開始引入。
主要提供了配置提供者,通知,哨兵的監控和自動故障轉移功能。哨兵的核心功能是主節點的自動故障轉移。
下面是Redis官方文檔對于哨兵功能的描述:
- 監控(Monitoring):哨兵會不斷地檢查主節點和從節點是否運作正常。
- 自動故障轉移(Automatic failover):當主節點不能正常工作時,哨兵會開始自動故障轉移操作,它會将失效主節點的其中一個從節點更新為新的主節點,并讓其他從節點改為複制新的主節點。
- 配置提供者(Configuration provider):用戶端在初始化時,通過連接配接哨兵來獲得目前Redis服務的主節點位址。
- 通知(Notification):哨兵可以将故障轉移的結果發送給用戶端。
其中,監控和自動故障轉移功能,使得哨兵可以及時發現主節點故障并完成轉移;而配置提供者和通知功能,則需要在與用戶端的互動中才能展現。
架構

它由兩部分組成,哨兵節點和資料節點:
- 哨兵節點:哨兵系統由一個或多個哨兵節點組成,哨兵節點是特殊的redis節點,不存儲資料。
- 資料節點:主節點和從節點都是資料節點。
部署
部署主從節點
哨兵系統中的主從節點,與普通的主從節點配置是一樣的,并不需要做任何額外配置。
#redis-6379.conf
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"
slaveof 192.168.92.128 6379
#redis-6381.conf
port 6381
daemonize yes
logfile "6381.log"
dbfilename "dump-6381.rdb"
slaveof 192.168.92.128 6379
配置完成後,依次啟動主節點和從節點:
redis-server redis-6379.conf
redis-server redis-6380.conf
redis-server redis-6381.conf
部署哨兵節點
哨兵節點本質上是特殊的Redis節點。
3個哨兵節點的配置幾乎是完全一樣的,主要差別在于端口号的不同(26379/26380/26381)。
#sentinel-26379.conf
port 26379
daemonize yes
logfile "26379.log"
sentinel monitor mymaster 192.168.92.128 6379 2
sentinel monitor mymaster 192.168.92.128 6379 2 配置的含義是:該哨兵節點監控192.168.92.128:6379這個主節點,該主節點的名稱是mymaster,最後的2的含義與主節點的故障判定有關:至少需要2個哨兵節點同意,才能判定主節點故障并進行故障轉移。
哨兵節點的啟動有兩種方式,二者作用是完全相同的:
redis-sentinel sentinel-26379.conf
redis-server sentinel-26379.conf --sentinel
此時如果檢視哨兵節點的配置檔案,會發現一些變化:
dir隻是顯式聲明了資料和日志所在的目錄(在哨兵語境下隻有日志);
known-slave和known-sentinel顯示哨兵已經發現了從節點和其他哨兵;
帶有epoch的參數與配置紀元有關(配置紀元是一個從0開始的計數器,每進行一次上司者哨兵選舉,都會+1;上司者哨兵選舉是故障轉移階段的一個操作)。
故障轉移
- 使用kill指令殺掉主節點 6379
- 如果此時立即在哨兵節點中使用info sentinel指令檢視,會發現主節點還沒有切換過來,因為哨兵發現主節點故障并轉移,需要一段時間。
- 一段時間以後,再次在哨兵節點中執行info Sentinel檢視,發現主節點已經切換成6380節點。
- 同時可以發現,哨兵節點認為新的主節點仍然有2個從節點,這是因為哨兵在将6380切換成主節點的同時将6379節點置為其從節點;
- 重新開機6379節點:可以看到6379節點成為了6380節點的從節點。
- 在故障轉移階段,哨兵和主從節點的配置檔案都會被改寫。
PS:
4 > 雖然6379從節點已經挂掉,但是由于哨兵并不會對從節點進行客觀下線(其含義将在原理部分介紹),是以認為該從節點一直存在。當6379節點重新啟動後,會自動變成6380節點的從節點。
6 > 對于主從節點,主要是slaveof配置的變化:新的主節點沒有了slaveof配置,其從節點則slaveof新的主節點。
6 > 對于哨兵節點,除了主從節點資訊的變化,紀元(epoch)也會變化,可以看到紀元相關的參數都+1了。
總結
哨兵系統的搭建過程,有幾點需要注意:
- 哨兵系統中的主從節點,與普通的主從節點并沒有什麼差別,故障發現和轉移是由哨兵來控制和完成的。
- 哨兵節點本質上是redis節點。
- 每個哨兵節點,隻需要配置監控主節點,便可以自動發現其他的哨兵節點和從節點。
- 在哨兵節點啟動和故障轉移階段,各個節點的配置檔案會被重寫(config rewrite)。
- 一個哨兵隻監控了一個主節點;實際上,一個哨兵可以監控多個主節點,通過配置多條sentinel monitor即可實作。
配置提供者和通知
通過用戶端原理的介紹,可以加深對哨兵功能的了解:
(1)配置提供者:用戶端可以通過哨兵節點+masterName擷取主節點資訊,在這裡哨兵起到的作用就是配置提供者。
需要注意的是,哨兵隻是配置提供者,而不是代理。二者的差別在于:
如果是配置提供者,用戶端在通過哨兵獲得主節點資訊後,會直接建立到主節點的連接配接,後續的請求(如set/get)會直接發向主節點;
如果是代理,用戶端的每一次請求都會發向哨兵,哨兵再通過主節點處理請求。
(2)通知:哨兵節點在故障轉移完成後,會将新的主節點資訊發送給用戶端,以便用戶端及時切換主節點。
基本原理
哨兵節點支援的指令
哨兵節點作為運作在特殊模式下的redis節點,其支援的指令與普通的redis節點不同。
在運維中可以通過這些指令查詢或修改哨兵系統;
哨兵系統要實作故障發現、故障轉移等各種功能,離不開哨兵節點之間的通信,而通信的很大一部分是通過哨兵節點支援的指令來實作的。
下面介紹哨兵節點支援的主要指令。
(1)基礎查詢:通過這些指令,可以查詢哨兵系統的拓撲結構、節點資訊、配置資訊等。
- info sentinel:擷取監控的所有主節點的基本資訊
- sentinel masters:擷取監控的所有主節點的詳細資訊
- sentinel master mymaster:擷取監控的主節點mymaster的詳細資訊
- sentinel slaves mymaster:擷取監控的主節點mymaster的從節點的詳細資訊
- sentinel sentinels mymaster:擷取監控的主節點mymaster的哨兵節點的詳細資訊
- sentinel get-master-addr-by-name mymaster:擷取監控的主節點mymaster的位址資訊
- sentinel is-master-down-by-addr:哨兵節點之間可以通過該指令詢問主節點是否下線,進而對是否客觀下線做出判斷
(2)增加/移除對主節點的監控
- sentinel monitor mymaster2 192.168.92.128 16379 2:與部署哨兵節點時配置檔案中的sentinel monitor功能完全一樣,不再詳述
- sentinel remove mymaster2:取消目前哨兵節點對主節點mymaster2的監控
(3)強制故障轉移
- sentinel failover mymaster:該指令可以強制對mymaster執行故障轉移,即便目前的主節點運作完好;例如,如果目前主節點所在機器即将報廢,便可以提前通過failover指令進行故障轉移。
基本概念
關鍵是了解以下幾個概念。
(1)定時任務:每個哨兵節點維護了3個定時任務。
- 通過向主從節點發送info指令擷取最新的主從結構;
- 通過釋出訂閱功能擷取其他哨兵節點的資訊;
- 通過向其他節點發送ping指令進行心跳檢測,判斷是否下線。
(2)主觀下線:在心跳檢測的定時任務中,如果其他節點超過一定時間沒有回複,哨兵節點就會将其進行主觀下線。主觀下線的意思是一個哨兵節點“主觀地”判斷下線;與主觀下線相對應的是客觀下線。
(3)客觀下線:哨兵節點在對主節點進行主觀下線後,會通過sentinel is-master-down-by-addr指令詢問其他哨兵節點該主節點的狀态;如果判斷主節點下線的哨兵數量達到一定數值,則對該主節點進行客觀下線。需要特别注意的是,客觀下線是主節點才有的概念;如果從節點和哨兵節點發生故障,被哨兵主觀下線後,不會再有後續的客觀下線和故障轉移操作。
(4)選舉上司者哨兵節點:當主節點被判斷客觀下線以後,各個哨兵節點會進行協商,選舉出一個上司者哨兵節點,并由該上司者節點對其進行故障轉移操作。監視該主節點的所有哨兵都有可能被選為上司者,選舉使用的算法是Raft算法;一般來說,哨兵選擇的過程很快,誰先完成客觀下線,一般就能成為上司者。
(5)故障轉移:選舉出的上司者哨兵,開始進行故障轉移操作,該操作大體可以分為3個步驟:
- 在從節點中選擇新的主節點:選擇的原則是,首先過濾掉不健康的從節點;然後選擇優先級最高的從節點(由slave-priority指定);如果優先級無法區分,則選擇複制偏移量最大的從節點;如果仍無法區分,則選擇runid最小的從節點。
- 更新主從狀态:通過slaveof no one指令,讓選出來的從節點成為主節點;并通過slaveof指令讓其他節點成為其從節點。
- 将已經下線的主節點(即6379)設定為新的主節點的從節點,當6379重新上線後,它會成為新的主節點的從節點。
配置與實踐建議
配置
(1) sentinel monitor {masterName} {masterIp} {masterPort} {quorum}
- masterName指定了主節點名稱,
- masterIp和masterPort指定了主節點位址,
- quorum是判斷主節點客觀下線的哨兵數量門檻值:當判定主節點下線的哨兵數量達到quorum時,對主節點進行客觀下線。建議取值為哨兵數量的一半加1。
(2) sentinel down-after-milliseconds {masterName} {time}
down-after-milliseconds的預設值是30000,即30s;
sentinel down-after-milliseconds與主觀下線的判斷有關:哨兵使用ping指令對其他節點進行心跳檢測。
如果其他節點超過down-after-milliseconds配置的時間沒有回複,哨兵就會将其進行主觀下線。該配置對主節點、從節點和哨兵節點的主觀下線判定都有效。
可以根據不同的網絡環境和應用要求來調整:值越大,對主觀下線的判定會越寬松,好處是誤判的可能性小,壞處是故障發現和故障轉移的時間變長,用戶端等待的時間也會變長。
(3) sentinel parallel-syncs {masterName} {number}
sentinel parallel-syncs與故障轉移之後從節點的複制有關:它規定了每次向新的主節點發起複制操作的從節點個數。
例如,假設主節點切換完成之後,有3個從節點要向新的主節點發起複制;
如果parallel-syncs=1,則從節點會一個一個開始複制;
如果parallel-syncs=3,則3個從節點會一起開始複制。
parallel-syncs取值越大,從節點完成複制的時間越快,但是對主節點的網絡負載、硬碟負載造成的壓力也越大;應根據實際情況設定。
例如,如果主節點的負載較低,而從節點對服務可用的要求較高,可以适量增加parallel-syncs取值。parallel-syncs的預設值是1。
(4) sentinel failover-timeout {masterName} {time}
sentinel failover-timeout與故障轉移逾時的判斷有關,但是該參數不是用來判斷整個故障轉移階段的逾時,而是其幾個子階段的逾時。
例如如果主節點晉升從節點時間超過timeout,或從節點向新的主節點發起複制操作的時間(不包括複制資料的時間)超過timeout,都會導緻故障轉移逾時失敗。
failover-timeout的預設值是180000,即180s;如果逾時,則下一次該值會變為原來的2倍。
實踐建議
(1)哨兵節點的數量應不止一個,一方面增加哨兵節點的備援,避免哨兵本身成為高可用的瓶頸;另一方面減少對下線的誤判。此外,這些不同的哨兵節點應部署在不同的實體機上。
(2)哨兵節點的數量應該是奇數,便于哨兵通過投票做出“決策”:上司者選舉的決策、客觀下線的決策等。
(3)各個哨兵節點的配置應一緻,包括硬體、參數等;此外,所有節點都應該使用ntp或類似服務,保證時間準确、一緻。
(4)哨兵的配置提供者和通知用戶端功能,需要用戶端的支援才能實作,如前文所說的Jedis;如果開發者使用的庫未提供相應支援,則可能需要開發者自己實作。
(5)當哨兵系統中的節點在docker(或其他可能進行端口映射的軟體)中部署時,應特别注意端口映射可能會導緻哨兵系統無法正常工作,因為哨兵的工作基于與其他節點的通信,而docker的端口映射可能導緻哨兵無法連接配接到其他節點。例如,哨兵之間互相發現,依賴于它們對外宣稱的IP和port,如果某個哨兵A部署在做了端口映射的docker中,那麼其他哨兵使用A宣稱的port無法連接配接到A。
作者:程式設計迷思
出處:http://www.cnblogs.com/kismetv/p/8654978.html