一、引言
上一篇文章我們詳細的講解了Redis的主從集群模式,其實這個集群模式配置很簡單,只需要在Slave的節點上進行配置,Master主節點的配置不需要做任何更改,但是有一點,Master和Slave兩個節點的持久化配置盡量保持一致,否則會有奇怪的問題出現。從今天開始我們開始講Redis集群模式的第二模式,也就是“哨兵”模式,該模式是從Redis的2.6版本開始提供的,但是當時這個版本的模式是不穩定的,直到Redis的2.8版本以后,這個哨兵模式才穩定下來,在生產環境中,如果想要使用Redis的哨兵模式,也會盡量使用Redis的2.8版本之后的版本。無論是主從模式,還是哨兵模式,這兩個模式都有一個問題,不能水平擴容,並且這兩個模式的高可用特性都會受到Master主節點內存的限制。還有一點,實現哨兵模式的配置也不簡單,甚至可以說有些繁瑣,所以在工業場景里這兩個模式都不建議使用,如果要使用必須有相關的問題的解決方案,以免后續帶來的問題。
二、Redis Sentinel簡介
Sentinel(哨兵)進程是用於監控redis集群中Master主服務器工作的狀態,在Master主服務器發生故障的時候,可以實現Master和Slave服務器的切換,保證系統的高可用,其已經被集成在redis2.6+的版本中,Redis的哨兵模式到了2.8版本之后就穩定了下來。一般在生產環境也建議使用Redis的2.8版本的以后版本。哨兵(Sentinel) 是一個分布式系統,你可以在一個架構中運行多個哨兵(sentinel) 進程,這些進程使用流言協議(gossipprotocols)來接收關於Master主服務器是否下線的信息,並使用投票協議(Agreement Protocols)來決定是否執行自動故障遷移,以及選擇哪個Slave作為新的Master。每個哨兵(Sentinel)進程會向其它哨兵(Sentinel)、Master、Slave定時發送消息,以確認對方是否”活”着,如果發現對方在指定配置時間(可配置的)內未得到回應,則暫時認為對方已掉線,也就是所謂的”主觀認為宕機” ,英文名稱:Subjective Down,簡稱SDOWN。有主觀宕機,肯定就有客觀宕機。當“哨兵群”中的多數Sentinel進程在對Master主服務器做出 SDOWN 的判斷,並且通過 SENTINEL is-master-down-by-addr 命令互相交流之后,得出的Master Server下線判斷,這種方式就是“客觀宕機”,英文名稱是:Objectively Down, 簡稱 ODOWN。通過一定的vote算法,從剩下的slave從服務器節點中,選一台提升為Master服務器節點,然后自動修改相關配置,並開啟故障轉移(failover)。
哨兵(sentinel) 雖然有一個單獨的可執行文件 redis-sentinel ,但實際上它只是一個運行在特殊模式下的 Redis 服務器,你可以在啟動一個普通 Redis 服務器時通過給定 --sentinel 選項來啟動哨兵(sentinel),哨兵(sentinel) 的一些設計思路和zookeeper非常類似。
Sentinel集群之間會互相通信,溝通交流redis節點的狀態,做出相應的判斷並進行處理,這里的主觀下線狀態和客觀下線狀態是比較重要的狀態,它們決定了是否進行故障轉移,可以 通過訂閱指定的頻道信息,當服務器出現故障得時候通知管理員,客戶端可以將 Sentinel 看作是一個只提供了訂閱功能的 Redis 服務器,你不可以使用 PUBLISH 命令向這個服務器發送信息,但你可以用 SUBSCRIBE 命令或者 PSUBSCRIBE 命令, 通過訂閱給定的頻道來獲取相應的事件提醒。一個頻道能夠接收和這個頻道的名字相同的事件。 比如說, 名為 +sdown 的頻道就可以接收所有實例進入主觀下線(SDOWN)狀態的事件。
1、Sentinel(哨兵)進程的作用:
1】、監控(Monitoring): 哨兵(sentinel) 會不斷地檢查你的Master和Slave是否運作正常。
2】、提醒(Notification):當被監控的某個Redis節點出現問題時, 哨兵(sentinel) 可以通過 API 向管理員或者其他應用程序發送通知。
3】、自動故障遷移(Automatic failover):當一個Master不能正常工作時,哨兵(sentinel) 會開始一次自動故障遷移操作,它會將失效Master的其中一個Slave升級為新的Master, 並讓失效Master的其他Slave改為復制新的Master;當客戶端試圖連接失效的Master時,集群也會向客戶端返回新Master的地址,使得集群可以使用現在的Master替換失效Master。Master和Slave服務器切換后,Master的redis.conf、Slave的redis.conf和sentinel.conf的配置文件的內容都會發生相應的改變,即,Master主服務器的redis.conf配置文件中會多一行slaveof的配置,sentinel.conf的監控目標會隨之調換。
2、Sentinel(哨兵)進程的工作方式:
1】、每個Sentinel(哨兵)進程以每秒鍾一次的頻率向整個集群中的Master主服務器,Slave從服務器以及其他Sentinel(哨兵)進程發送一個 PING 命令。
2】、如果一個實例(instance)距離最后一次有效回復 PING 命令的時間超過 down-after-milliseconds 選項所指定的值, 則這個實例會被 Sentinel(哨兵)進程標記為主觀下線(SDOWN)。
3】、如果一個Master主服務器被標記為主觀下線(SDOWN),則正在監視這個Master主服務器的所有 Sentinel(哨兵)進程要以每秒一次的頻率確認Master主服務器的確進入了主觀下線狀態。
4】、當有足夠數量的 Sentinel(哨兵)進程(大於等於配置文件指定的值)在指定的時間范圍內確認Master主服務器進入了主觀下線狀態(SDOWN), 則Master主服務器會被標記為客觀下線(ODOWN)。
5】、在一般情況下, 每個 Sentinel(哨兵)進程會以每 10 秒一次的頻率向集群中的所有Master主服務器、Slave從服務器發送 INFO 命令。
6】、當Master主服務器被 Sentinel(哨兵)進程標記為客觀下線(ODOWN)時,Sentinel(哨兵)進程向下線的 Master主服務器的所有 Slave從服務器發送 INFO 命令的頻率會從 10 秒一次改為每秒一次。
7】、若沒有足夠數量的 Sentinel(哨兵)進程同意 Master主服務器下線, Master主服務器的客觀下線狀態就會被移除。若 Master主服務器重新向 Sentinel(哨兵)進程發送 PING 命令返回有效回復,Master主服務器的主觀下線狀態就會被移除。
3、哨兵模式的環境:
1】、Master主服務器配置信息:IP:192.168.127.128, Port:6379,OS:Linux
2】、Slave從服務器的配置信息:IP:192.168.127.129 Port:6379,OS:Linux
3】、在Slave從服務器上安裝了一個哨兵進程(Sentinel),在Master服務器也安裝了一個哨兵進程(Sentinel)。
由於兩個Redis服務器都是安裝在Linux操作系統上,而且這兩個Redis服務器會在Master主服務器發生故障的時候會進行切換,必須保證兩個Redis服務器的端口號已經增加進了防火牆,或者把兩個Linux操作系統的防火牆關閉,否則會提示Master-link-Status:down,沒有連接上Master主服務器。解決辦法有兩個:第一個辦法是關閉兩個Linux操作系統的防火牆;第二個辦法是把各個Redis服務的端口號增加到防火牆里面,允許通過該端口號進行通信。可以先使用命令 【firewall-cmd --query-port=6379/tcp】,如果結果是 No,那就繼續執行以下命令【firewall-cmd --add-port=6379/tcp】,命令執行后,返回Success,表示增加成功。這樣兩個Linux系統上的Redis服務器就可以順利切換,執行哨兵模式的操作。
三、哨兵模式的配置
下面是我使用的配置,需要修改的配置項我寫了出來,沒有更改的配置項就是用默認值,就不會寫出來:
1、###### Master config(redis.conf)
1.1、### NETWORK 設置: bind 192.168.127.128 //綁定IP地址,可以通過ifconfig 獲取Ip地址(在Linux系統下) port 6379 //保持默認值,也可以修改 timeout 30 //Client 端空閑斷開連接的時間 1.2、### GENERAL 設置: daemonize yes //默認值是no,把值修改為yes,以后台模式運行 logfile /root/application/program/redis-tool/logs/redis.log //日志文件的位置 1.3、### SNAPSHOTTING 設置: dir /root/application/program/redis-tool/datas //SNAPSHOTTING文件的路徑 1.4、### APPEND ONLY MODE 設置: appendonly yes //默認值是No,意思是不使用AOF增量持久化的方式,使用RDB全量持久化的方式。把No值改成Yes,使用AOF增量持久化的方式 appendfsync always
2、###### Slave Config(redis.conf)
2.1、### NETWORK 設置: bind 192.168.127.129 //綁定IP地址,可以通過ifconfig 獲取Ip地址(在Linux系統下) port 6379 //保持默認值,也可以修改 timeout 30 //Client 端空閑斷開連接的時間 2.2、### GENERAL 設置: daemonize yes //默認值是no,把值修改為yes,以后台模式運行 logfile /root/application/program/redis/logs/redis.log //日志文件的位置 2.3、### SNAPSHOTTING 設置: dir /root/application/program/redis/datas //SNAPSHOTTING文件的路徑 2.4、### REPLICATION 設置: slaveof 192.168.127.128 6379 //主服務器的Ip地址和Port端口號 slave-serve-stale-data no //如果slave 無法與master 同步,設置成slave不可讀,方便監控腳本發現問題。 2.5、### APPEND ONLY MODE 設置: appendonly yes //默認值是No,意思是不使用AOF增量持久化的方式,使用RDB全量持久化的方式。把No值改成Yes,使用AOF增量持久化的方式 appendfsync always
3、###### Sentinel Config(sentinel.conf,192.168.127.129 Slave從服務器)
3.1、 ### Port 設置: port 26379 //哨兵端口號保持不變,可以修改,但是我沒有修改 3.2、### dir 設置: dir /root/application/program/redis/sentinel/ //哨兵程序的日志路徑 3.3、### Sentinel Monitor 設置: sentinel monitor mymaster 192.168.127.129 6379 1 3.4、### Down-After-Milliseconds 設置: sentinel down-after-milliseconds mymaster 5000 //哨兵程序每5秒檢測一次Master是否正常 3.5、### Parallel-Syncs 設置: sentinel parallel-syncs mymaster 1 3.5、### Failover-Timeout 設置: sentinel failover-timeout mymaster 60000 3.5、### 啟動:redis-sentinel redis-server sentinel.conf --sentinel & //(&有這可以Ctrl +C退到命令行,沒有這個就直接退出哨兵進程) redis-sentinel /path/to/sentinel.conf & //對於 redis-sentinel 程序, 你可以用以下命令來啟動 Sentinel 系統 3.6、### 關閉:redis-sentinel pkill redis-server //這個會關掉Redis服務器和Sentinel(哨兵)進程 kill 進程號 //可以關掉指定進程號的進程
4、###### 模式測試
4.1、在Sentinel.conf配置文件設置 sentinel monitor:
4.2、在Sentinel.conf配置文件設置 sentinel down-after-milliseconds:
4.3、在Sentinel.conf配置文件設置 sentinel parallel-syncs:
4.4、Master 主服務器的配置詳情:
4.5、Slave 從服務器配置詳情:
4.6、啟動Sentinel(哨兵)進程,開始對Master主服務器進行監控:
4.7、我們人為模仿Master主服務器宕機:
4.8、實現Master主服務器和Slave從服務器的切換:
4.9、主從切換后,主服務器變成了Slave 從服務器,詳情如下:
4.10、主從切換后,從服務器變成了Master 主服務器,詳情如下:
注意:
① INFO
sentinel的基本狀態信息
②SENTINEL masters
列出所有被監視的主服務器,以及這些主服務器的當前狀態
③ SENTINEL slaves
列出給定主服務器的所有從服務器,以及這些從服務器的當前狀態
④SENTINEL get-master-addr-by-name
返回給定名字的主服務器的 IP 地址和端口號
⑤SENTINEL reset
重置所有名字和給定模式 pattern 相匹配的主服務器。重置操作清除主服務器目前的所有狀態, 包括正在執行中的故障轉移, 並移除目前已經發現和關聯的, 主服務器的所有從服務器和 Sentinel 。
⑥SENTINEL failover
當主服務器失效時, 在不詢問其他 Sentinel 意見的情況下, 強制開始一次自動故障遷移,但是它會給其他sentinel發送一個最新的配置,其他sentinel會根據這個配置進行更新
四、主觀下線和客觀下線
下面我們來解釋一下兩個“下線”的概念,一個是“主觀下線”,另一個就是“客觀下線”。
主觀下線(Subjectively Down, 簡稱 SDOWN)指的是單個 Sentinel 實例對服務器做出的下線判斷。
客觀下線(Objectively Down, 簡稱 ODOWN)指的是多個 Sentinel 實例在對同一個服務器做出 SDOWN 判斷,並且通過 SENTINEL is-master-down-by-addr 命令互相交流之后,得出的服務器下線判斷。(一個 Sentinel 可以通過向另一個 Sentinel 發送 SENTINEL is-master-down-by-addr 命令來詢問對方是否認為給定的服務器已下線。)
如果一個服務器沒有在 master-down-after-milliseconds 選項所指定的時間內,對向它發送 PING 命令的 Sentinel(哨兵)進程返回一個有效回復(valid reply),那么 Sentinel(哨兵)進程就會將這個服務器標記為主觀下線。
服務器對 PING 命令的有效回復可以是以下三種回復的其中一種:
1、返回 +PONG 。
2、返回 -LOADING 錯誤。
3、返回 -MASTERDOWN 錯誤。
如果服務器返回除以上三種回復之外的其他回復,又或者在指定時間內沒有回復 PING 命令,那么 Sentinel(哨兵)進程認為服務器返回的回復無效(non-valid)。
如果一個服務器在 master-down-after-milliseconds 毫秒內,一直返回無效回復才會被 Sentinel 標記為主觀下線。
舉個例子,如果 master-down-after-milliseconds 選項的值為 30000 毫秒(30 秒),那么只要服務器能在每 29 秒之內返回至少一次有效回復, 這個服務器就仍然會被認為是處於正常狀態的。
從“主觀下線”狀態切換到“客觀下線”狀態並沒有使用嚴格的法定人數算法(strong quorum algorithm),而是使用了流言協議,該協議解釋為:如果 Sentinel(哨兵)進程在給定的時間范圍內,從其他 Sentinel(哨兵)進程那里接收到了足夠數量的主服務器下線報告, 那么 Sentinel(哨兵)進程就會將主服務器的狀態從“主觀下線”改變為“客觀下線”。如果之后其他 Sentinel(哨兵)進程不再報告主服務器已下線,那么“客觀下線”狀態就會被移除。
“客觀下線”條件只適用於主服務器:對於任何其他類型的 Redis 實例, Sentinel(哨兵)進程在將它們判斷為下線前不需要進行協商,所以Slave從服務器或者其他 Sentinel(哨兵)進程永遠不會達到“客觀下線”條件。
只要有一個 Sentinel(哨兵)進程發現某個主服務器進入了“客觀下線”狀態,這個 Sentinel(哨兵)進程就可能會被其他 Sentinel(哨兵)進程推選出,並對失效的主服務器執行自動故障遷移操作。
五、Sentinel(哨兵)配置文件簡介
在Redis的源碼中包含了一個名為 sentinel.conf 的文件, 這個文件就是帶有注釋的Sentinel(哨兵)的配置文件的示例。
如果想要運行一個“哨兵”程序,以下配置項是最少配置:
sentinel monitor mymaster 127.0.0.1 6379 1
sentinel down-after-milliseconds mymaster 60000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1
第一行配置表示 Sentinel(哨兵)進程去監視一個名為 mymaster 的主服務器,這個主服務器的 IP 地址為 127.0.0.1 , 端口號為 6379,而將這個主服務器判斷為失效至少需要 1 個 Sentinel(哨兵)進程的同意。如果在架構系統中已經配置類多個Sentinel(哨兵)進程,在同意“Master主服務器”下線的 Sentinel(哨兵)進程的數量不達標的情況下,Sentinel(哨兵)進程就不會執行自動故障遷移。在設置多Sentinel(哨兵)進程的情況下,無論設置多少個 Sentinel(哨兵)進程同意才能判斷一個服務器失效,一個 Sentinel 都需要獲得架構系統中多數 Sentinel(哨兵)進程的支持, 才能發起一次自動故障遷移,並預留一個給定的配置紀元 (configuration Epoch ,一個配置紀元就是一個新主服務器配置的版本號)。如果您只配置了一個Sentinel(哨兵)進程來做監控,那一個Sentinel(哨兵)進程也可以決定“Master主服務器”是否下線。
其他選項的基本格式如下:sentinel <選項的名字> <主服務器的名字> <選項的值>
配置選項的解釋如下:
1、down-after-milliseconds : Sentinel(哨兵)進程判斷服務器已經掉線所需的毫秒數。
如果被監控的服務器在給定的毫秒數之內,並沒有返回 Sentinel(哨兵)進程發送的 PING 命令的回復,或者返回一個錯誤,那么 Sentinel(哨兵)進程將這個服務器標記為主觀下線(subjectively down,簡稱 SDOWN )。如果在架構系統中配置了多個Sentinel(哨兵)進程的情況下,只有一個Sentinel(哨兵)進程將服務器標記為主觀下線並不一定會引起服務器的自動故障遷移,只有在足夠數量的 Sentinel(哨兵)進程都將一個服務器標記為主觀下線之后,服務器才會被標記為客觀下線(objectively down, 簡稱 ODOWN ),這時才回執行自動故障遷移。另外一種情況是,在架構系統中只配置了一個Sentinel(哨兵)進程的話,那這Sentinel(哨兵)進程也可以決定被監控的服務器的是否“下線”。
將服務器標記為客觀下線所需的 Sentinel(哨兵)進程數量由對主服務器的配置決定。
2、parallel-syncs :在執行故障轉移時,最多可以有多少個從服務器同時對新的主服務器進行同步,這個數字越小,完成故障轉移所需的時間就越長。
如果“Slave從服務器”被設置為允許使用過期數據集(參見對 redis.conf 文件中對 slave-serve-stale-data 選項的說明),那么你可能不希望所有“Slave從服務器”都在同一時間向新的“Master主服務器”發送同步請求, 因為盡管復制過程的絕大部分步驟都不會阻塞“Slave從服務器”,但“Slave從服務器”在載入“Master主服務器”發來的 RDB 文件時, 仍然會造成“Slave從服務器”在一段時間內不能處理命令請求,如果全部“Slave從服務器”一起對新的“Master主服務器”進行同步, 那么就可能會造成所有“Slave從服務器”在短時間內全部不可用的情況出現。
你可以通過將這個值設為 1 來保證每次只有一個Slave從服務器處於不能處理命令請求的狀態。
3、failover-timeout:實現主從切換,完成故障轉移的所需要的最大時間值。若Sentinel(哨兵)進程在該配置值內未能完成故障轉移的操作(即故障時master/slave自動切換),則認為本次故障轉移操作失敗。
4、notification-script: 指定Sentinel(哨兵)進程檢測到Master-Name所指定的“Master主服務器”的實例異常的時候,所要調用的報警腳本。該配置項可選,但線上系統建議配置。
六、哨兵模式的優缺點
優點:
1、哨兵集群模式是基於主從模式的,所有主從的優點,哨兵模式同樣具有。
2、主從可以切換,故障可以轉移,系統可用性更好。
3、哨兵模式是主從模式的升級,系統更健壯,可用性更高。
缺點:
1、Redis較難支持在線擴容,在集群容量達到上限時在線擴容會變得很復雜。為避免這一問題,運維人員在系統上線時必須確保有足夠的空間,這對資源造成了很大的浪費。
七、結束
今天就寫到這里了,Redis的哨兵模式是以主從模式為基礎的,所以說,主從模式擁有的一些缺點,在哨兵模式下也具有。哨兵模式主要是監控Master主服務器的運行情況,當然也會監控Slave從服務器的運行情況,如果Master主服務器發生了故障,該模式可以保證Slave從服務器順利升級為Master主服務器繼續提供服務,以此提高系統的高可用性。雖然哨兵模式比主從模式提高了不少系統的高可用性,但是該模式不能水平擴容,不能動態的增、刪節點,這也是限制哨兵模式廣泛應用的主要原因。Redis也看到了這個情況,所在在Redis的3.x以后的版本提供了一個更加強大集群模式,那就是Cluster集群模式,這個模式也是我們下一篇文章的主題。