一、是什麼:
Redis-Sentinel是Redis官方推薦的高可用(HA)方案,當用Reids 作master-slave高可用方案時,假如master宕機了,redis自己(包括它的不少客服端)都沒有實現自動的主備切換,而Redis-Sentinel自己也是一個獨立運行的進程,它能監控多個master-slave集羣,發現master宕機後能自動切換。html
二、功能
- 不時監控redis是否按照預期的良好的運行。
- 若是發現某個redis節點運行出現情況,可以通知別外一個進程(如它的客戶端)。
- 可以進行自動切換。當一個master節點不可用時,可以選舉出master的多個slave(若是超過一個slave的話)中的一個來做爲新的master,其它的slave節點會將他的master地址改成新提高爲master的服務器的地址。
四、優缺點:
優勢:
- 哨兵模式是基於主從模式的,全部主從的優勢,哨兵模式都有。
- 主從能夠自動切換,系統更健壯,可用性更高
缺點:
- redis較難支持在線擴容,在集羣容量達上限時在線擴容變的很複雜。
一、哨兵的工做方式:
- 每一個Sentinel(哨兵)進程以每秒鐘一次的頻率向整個redis集羣中的master主服務器、slave從服務器以及其餘的Sentinel(哨兵)進程發送一個ping命令。
- 若是一個實例距離最後一次有效回覆ping命令的時間超過down-after-milliseconds選項所指定的值則這個實例會被Sentinel標記爲主觀下線(SDOWN)。
- 如是是master主服務器被標記爲SDOWN,則正在監控這個服務器的全部Sentinel都要以每秒一次的頻率確認服務器是否真的已經進入SDOWN(主觀下線狀態)。
- 當有足夠數量(≥配置文件配置值)的Sentinel在指定的時間內確認了master進入了SDOWN狀態,則master被標記爲ODOWN(客觀下線狀態)。
- 在通常狀況下,每一個Sentinel會每10秒向redis 主服務器和從服務器發送Info命令。可是當master被標記爲客觀下線時,頻率改成1秒一次。
- 若沒有足夠數量的Sentinel贊成master服務器下線,則master的SDOWN狀態被移除,若master從新向Sentinel發送ping命令返回了有效回覆,則master的SDOWN狀態被移除。
二、原理
- Sentinel集羣經過給定的配置文件發現master,啓動時會監控master。經過向master發送info信息得到該服務下面的全部從服務器。
- Sentinel集羣經過命令鏈接向被監控的主從服務器發送hello信息(每秒一次),該信息包括Sentinel自己的ip、端口、id等內容,以此來向其餘Sentinel宣告本身的存在。
- Sentinel集羣經過訂閱鏈接接收其餘Sentinel發送的hello信息,以此來發現監視同一個主服務器的其餘Sentinel;集羣之間會互相建立命令鏈接用於通訊,由於已經有主從服務器做爲發送和接收hello信息的中介,Sentinel之間不會建立訂閱鏈接。
- Sentinel集羣使用Sentinel命令來檢測實例的狀態,若是指定的時間內(down-after-milliseconds)沒有回覆或者返回錯誤回覆,那麼該實例被判爲主觀下線SDOWN。
- 當failover主備切換被觸發後,failover並不會立刻進行,還須要Sentinel集羣中另外quorum個其餘Sentinel受權,成功後進入ODOWN客觀下線狀態,以後再進行failover。
- Sentinel向選爲master的slave發送slaveof no one 命令,選擇slave的條件是首先會根據slave的優先級來排序,優先級越小排名越靠前。若是相同,則查看複製的下標,哪一個接收master的複製數據越多哪一個越靠前,若是兩個都同樣就選擇進程ID較小的。
- Sentinel被受權後會得到宕機的master的一份最新配置版本號(config-epoch)當failover結束後,這個版本號將會用於最新的配置,經過廣播的形式通知其餘Sentinel,其它的Sentinel則更新對應的master配置。
1-3是自動發現機制
- 以10秒一次的頻率,向被監控的master發送Info命令,根據回覆獲取當前master信息。
- 以1秒一次的頻率,向全部的redis服務器包括 Sentinel 發送ping命令,經過回覆判斷服務器是否在線
- 以2秒一次的頻率,經過 向全部被監控的master,slave服務器發送的當前Sentinel,master信息的消息。
四、是檢測機制,五、6是failover機制,7是更新配置機制。
注意:
- 由於redis採用的是異步複製,沒有辦法避免數據的丟失。但能夠經過如下配置來使得數據不會丟失:min-slaves-to-write 1 ; min-slaves-max-lag 10。
- 一個redis不管是master仍是slave,都必須在配置中指定一個slave優先級。
- 要注意到master也是有可能經過failover變成slave的。
- 若是一個redis的slave優先級配置爲0,那麼它將永遠不會被選爲master,可是它依然會從master哪裏複製數據。
三、SDOWN和ODOWN
- sentinel對於不可用有兩種不一樣的見解,一個叫主觀不可用(SDOWN),另一個叫客觀不可用(ODOWN)。
- SDOWN是sentinel本身主觀上檢測到的關於master的狀態,ODOWN須要必定數量的sentinel達成一致意見才能認爲一個master客觀上已經宕掉,各個sentinel之間經過命令
SENTINEL is_master_down_by_addr
來得到其它sentinel對master的檢測結果。- 從sentinel的角度來看,若是發送了PING心跳後,在必定時間內沒有收到合法的回覆,就達到了SDOWN的條件。這個時間在配置中經過
is-master-down-after-milliseconds
參數配置。- 從SDOWN切換到ODOWN不須要任何一致性算法,只須要一個gossip協議:若是一個sentinel收到了足夠多的sentinel發來消息告訴它某個master已經down掉了,SDOWN狀態就會變成ODOWN狀態。若是以後master可用了,這個狀態就會相應地被清理掉。
- 真正進行failover須要一個受權的過程,可是全部的failover都開始於一個ODOWN狀態。
- ODOWN狀態只適用於master,對於不是master的redis節點sentinel之間不須要任何協商,slaves和sentinel不會有ODOWN狀態。
四、配置版本號
- 爲何要先得到大多數sentinel的承認時才能真正去執行failover呢?
- 當一個sentinel被受權後,它將會得到宕掉的master的一份最新配置版本號,當failover執行結束之後,這個版本號將會被用於最新的配置。由於大多數sentinel都已經知道該版本號已經被要執行failover的sentinel拿走了,因此其餘的sentinel都不能再去使用這個版本號。這意味着,每次failover都會附帶有一個獨一無二的版本號。咱們將會看到這樣作的重要性。
- 並且,sentinel集羣都遵照一個規則:若是sentinel A推薦sentinel B去執行failover,B會等待一段時間後,自行再次去對同一個master執行failover,這個等待的時間是經過
failover-timeout
配置項去配置的。從這個規則能夠看出,sentinel集羣中的sentinel不會再同一時刻併發去failover同一個master,第一個進行failover的sentinel若是失敗了,另一個將會在必定時間內進行從新進行failover,以此類推。- redis sentinel保證了活躍性:若是大多數sentinel可以互相通訊,最終將會有一個被受權去進行failover.
redis sentinel也保證了安全性:每一個試圖去failover同一個master的sentinel都會獲得一個獨一無二的版本號。五、配置傳播
- 一旦一個sentinel成功地對一個master進行了failover,它將會把關於master的最新配置經過廣播形式通知其它sentinel,其它的sentinel則更新對應master的配置。
- 一個faiover要想被成功實行,sentinel必須可以向選爲master的slave發送
SLAVEOF NO ONE
命令,而後可以經過INFO
命令看到新master的配置信息。- 當將一個slave選舉爲master併發送
SLAVEOF NO ONE
後,即便其它的slave還沒針對新master從新配置本身,failover也被認爲是成功了的,而後全部sentinels將會發布新的配置信息。新配在集羣中相互傳播的方式,就是爲何咱們須要當一個sentinel進行failover時必須被受權一個版本號的緣由。node
- 每一個sentinel使用##發佈/訂閱##的方式持續地傳播master的配置版本信息,配置傳播的##發佈/訂閱##管道是:
__sentinel__:hello
。- 由於每個配置都有一個版本號,因此以版本號最大的那個爲標準。
舉個栗子:
- 假設有一個名爲mymaster的地址爲192.168.1.50:6379。一開始,集羣中全部的sentinel都知道這個地址,因而爲mymaster的配置打上版本號1。
- 一段時候後mymaster死了,有一個sentinel被受權用版本號2對其進行failover。
- 若是failover成功了,假設地址改成了192.168.1.50:9000,此時配置的版本號爲2,進行failover的sentinel會將新配置廣播給其餘的sentinel
- 因爲其餘sentinel維護的版本號爲1,發現新配置的版本號爲2時,版本號變大了,說明配置更新了,因而就會採用最新的版本號爲2的配置。
這意味着sentinel集羣保證了第二種活躍性:一個可以互相通訊的sentinel集羣最終會採用版本號最高且相同的配置。redis
六、Sentinel之間和Slaves之間的自動發現機制
- 雖然sentinel集羣中各個sentinel都互相鏈接彼此來檢查對方的可用性以及互相發送消息。可是你不用在任何一個sentinel配置任何其它的sentinel的節點。由於sentinel利用了master的發佈/訂閱機制去自動發現其它也監控了統一master的sentinel節點。經過向名爲
__sentinel__:hello
的管道中發送消息來實現。- 一樣,你也不須要在sentinel中配置某個master的全部slave的地址,sentinel會經過詢問master來獲得這些slave的地址的。
- 每一個sentinel經過向每一個master和slave的發佈/訂閱頻道
__sentinel__:hello
每秒發送一次消息,來宣佈它的存在。- 每一個sentinel也訂閱了每一個master和slave的頻道
__sentinel__:hello
的內容,來發現未知的sentinel,當檢測到了新的sentinel,則將其加入到自身維護的master監控列表中。- 每一個sentinel發送的消息中也包含了其當前維護的最新的master配置。若是某個sentinel發現本身的配置版本低於接收到的配置版本,則會用新的配置更新本身的master配置。
- 在爲一個master添加一個新的sentinel前,sentinel老是檢查是否已經有sentinel與新的sentinel的進程號或者是地址是同樣的。若是是那樣,這個sentinel將會被刪除,而把新的sentinel添加上去。
七、網絡隔離時的一致性
例子:算法
- 有三個主機,每一個主機分別運行一個redis和一個sentinel。初始狀態下redis3是master, redis1和redis2是slave。
- 以後redis3所在的主機網絡不可用了,sentinel1和sentinel2啓動了failover並把redis1選舉爲master。
- Sentinel集羣的特性保證了sentinel1和sentinel2獲得了關於master的最新配置。可是sentinel3依然是舊的配置,由於它與外界隔離了。
當網絡恢復之後,咱們知道sentinel3將會更新它的配置。可是,若是客戶端所鏈接的master被網絡隔離,會發生什麼呢?安全
- 客戶端將依然能夠向redis3寫數據,可是當網絡恢復後,redis3就會變成redis的一個slave,那麼,在網絡隔離期間,客戶端向redis3寫的數據將會丟失。
- 由於redis採用的是異步複製,在這樣的場景下,沒有辦法避免數據的丟失。然而,你能夠經過如下配置來配置redis3和redis1,使得數據不會丟失。
min-slaves-to-write 1 min-slaves-max-lag 10
- 經過上面的配置,當一個redis是master時,若是它不能向至少一個slave寫數據(上面的min-slaves-to-write指定了slave的數量),它將會拒絕接受客戶端的寫請求。
- 因爲複製是異步的,master沒法向slave寫數據意味着slave要麼斷開鏈接了,要麼不在指定時間內向master發送同步數據的請求了(上面的min-slaves-max-lag指定了這個時間)。
八、Slave選舉與優先級
當一個sentinel準備好了要進行failover,而且收到了其餘sentinel的受權,那麼就須要選舉出一個合適的slave來作爲新的master。服務器
slave的選舉主要會評估slave的如下幾個方面:網絡
與master斷開鏈接的次數併發
Slave的優先級less
數據複製的下標(用來評估slave當前擁有多少master的數據)異步
進程ID
若是一個slave與master失去聯繫超過10次,而且每次都超過了配置的最大失聯時間(
down-after-milliseconds
),若是sentinel在進行failover時發現slave失聯,那麼這個slave就會被sentinel認爲不適合用來作新master的。更嚴格的定義是,若是一個slave持續斷開鏈接的時間超過
(down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state就會被認爲失去選舉資格。
符合上述條件的slave纔會被列入master候選人列表,並根據如下順序來進行排序:
sentinel首先會根據slaves的優先級來進行排序,優先級越小排名越靠前。
若是優先級相同,則查看複製的下標,哪一個從master接收的複製數據多,哪一個就靠前。
若是優先級和下標都相同,就選擇進程ID較小的那個。
一個redis不管是master仍是slave,都必須在配置中指定一個slave優先級。要注意到master也是有可能經過failover變成slave的。
若是一個redis的slave優先級配置爲0,那麼它將永遠不會被選爲master。可是它依然會從master哪裏複製數據。
一、redis.conf 配置
################################# REPLICATION ################################# #複製選項,slave複製對應的master。 # slaveof <masterip> <masterport> #若是master設置了requirepass,那麼slave要連上master,須要有master的密碼才行。masterauth就是用來配置master的密碼,這樣能夠在連上master後進行認證。 # masterauth <master-password> #當從庫同主機失去鏈接或者複製正在進行,從機庫有兩種運行方式:1) 若是slave-serve-stale-data設置爲yes(默認設置),從庫會繼續響應客戶端的請求。2) 若是slave-serve-stale-data設置爲no,除去INFO和SLAVOF命令以外的任何請求都會返回一個錯誤」SYNC with master in progress」。 slave-serve-stale-data yes #做爲從服務器,默認狀況下是隻讀的(yes),能夠修改爲NO,用於寫(不建議)。 slave-read-only yes #是否使用socket方式複製數據。目前redis複製提供兩種方式,disk和socket。若是新的slave連上來或者重連的slave沒法部分同步,就會執行全量同步,master會生成rdb文件。有2種方式:disk方式是master建立一個新的進程把rdb文件保存到磁盤,再把磁盤上的rdb文件傳遞給slave。socket是master建立一個新的進程,直接把rdb文件以socket的方式發給slave。disk方式的時候,當一個rdb保存的過程當中,多個slave都能共享這個rdb文件。socket的方式就的一個個slave順序複製。在磁盤速度緩慢,網速快的狀況下推薦用socket方式。 repl-diskless-sync no #diskless複製的延遲時間,防止設置爲0。一旦複製開始,節點不會再接收新slave的複製請求直到下一個rdb傳輸。因此最好等待一段時間,等更多的slave連上來。 repl-diskless-sync-delay 5 #slave根據指定的時間間隔向服務器發送ping請求。時間間隔能夠經過 repl_ping_slave_period 來設置,默認10秒。 # repl-ping-slave-period 10 #複製鏈接超時時間。master和slave都有超時時間的設置。master檢測到slave上次發送的時間超過repl-timeout,即認爲slave離線,清除該slave信息。slave檢測到上次和master交互的時間超過repl-timeout,則認爲master離線。須要注意的是repl-timeout須要設置一個比repl-ping-slave-period更大的值,否則會常常檢測到超時。 # repl-timeout 60 #是否禁止複製tcp連接的tcp nodelay參數,可傳遞yes或者no。默認是no,即便用tcp nodelay。若是master設置了yes來禁止tcp nodelay設置,在把數據複製給slave的時候,會減小包的數量和更小的網絡帶寬。可是這也可能帶來數據的延遲。默認咱們推薦更小的延遲,可是在數據量傳輸很大的場景下,建議選擇yes。 repl-disable-tcp-nodelay no #複製緩衝區大小,這是一個環形複製緩衝區,用來保存最新複製的命令。這樣在slave離線的時候,不須要徹底複製master的數據,若是能夠執行部分同步,只須要把緩衝區的部分數據複製給slave,就能恢復正常複製狀態。緩衝區的大小越大,slave離線的時間能夠更長,複製緩衝區只有在有slave鏈接的時候才分配內存。沒有slave的一段時間,內存會被釋放出來,默認1m。 # repl-backlog-size 5mb #master沒有slave一段時間會釋放複製緩衝區的內存,repl-backlog-ttl用來設置該時間長度。單位爲秒。 # repl-backlog-ttl 3600 #當master不可用,Sentinel會根據slave的優先級選舉一個master。最低的優先級的slave,當選master。而配置成0,永遠不會被選舉。 slave-priority 100 #redis提供了可讓master中止寫入的方式,若是配置了min-slaves-to-write,健康的slave的個數小於N,mater就禁止寫入。master最少得有多少個健康的slave存活才能執行寫命令。這個配置雖然不能保證N個slave都必定能接收到master的寫操做,可是能避免沒有足夠健康的slave的時候,master不能寫入來避免數據丟失。設置爲0是關閉該功能。 # min-slaves-to-write 3 #延遲小於min-slaves-max-lag秒的slave才認爲是健康的slave。 # min-slaves-max-lag 10二、sentinel.conf配置
port 20086 #默認端口26379 dir "/tmp" logfile "/var/log/redis/sentinel_20086.log" daemonize yes #格式:sentinel <option_name> <master_name> <option_value>;#該行的意思是:監控的master的名字叫作T1(自定義),地址爲127.0.0.1:10086,行尾最後的一個2表明在sentinel集羣中,多少個sentinel認爲masters死了,才能真正認爲該master不可用了。 sentinel monitor T1 127.0.0.1 10086 2 #sentinel會向master發送心跳PING來確認master是否存活,若是master在「必定時間範圍」內不迴應PONG 或者是回覆了一個錯誤消息,那麼這個sentinel會主觀地(單方面地)認爲這個master已經不可用了(subjectively down, 也簡稱爲SDOWN)。而這個down-after-milliseconds就是用來指定這個「必定時間範圍」的,單位是毫秒,默認30秒。 sentinel down-after-milliseconds T1 15000 #failover過時時間,當failover開始後,在此時間內仍然沒有觸發任何failover操做,當前sentinel將會認爲這次failoer失敗。默認180秒,即3分鐘。 sentinel failover-timeout T1 120000 #在發生failover主備切換時,這個選項指定了最多能夠有多少個slave同時對新的master進行同步,這個數字越小,完成failover所需的時間就越長,可是若是這個數字越大,就意味着越多的slave由於replication而不可用。能夠經過將這個值設爲 1 來保證每次只有一個slave處於不能處理命令請求的狀態。 sentinel parallel-syncs T1 1 #sentinel 鏈接設置了密碼的主和從 #sentinel auth-pass <master_name> xxxxx #發生切換以後執行的一個自定義腳本:如發郵件、vip切換等 ##sentinel notification-script <master-name> <script-path> ##不會執行,疑問? #sentinel client-reconfig-script <master-name> <script-path> ##這個會執行例子:
port 20086 dir "/var/lib/sentinel_20086" logfile "/var/log/redis/sentinel_20086.log" daemonize yes sentinel monitor T1 127.0.0.1 10086 2 sentinel down-after-milliseconds T1 15000 sentinel failover-timeout T1 120000 sentinel parallel-syncs T1 1 #發生切換以後執行的一個自定義腳本:如發郵件、vip切換等 #sentinel notification-script <master-name> <script-path>主要配置sentinel monitor 主服務器的地址,其餘配置按須要調整。
可添加 logfile 路徑做爲 sentinel 的日誌文件。
關鍵配置:sentinel monitor T1 127.0.0.1 10086 2
三、啓動命令
redis-sentinel sentinel.conf
注意:當一個master配置爲須要密碼才能鏈接時,客戶端和slave在鏈接時都須要提供密碼。master經過requirepass設置自身的密碼,不提供密碼沒法鏈接到這個master。slave經過masterauth來設置訪問master時的密碼。客戶端須要auth提供密碼,可是當使用了sentinel時,
因爲一個master可能會變成一個slave,一個slave也可能會變成master,因此須要同時設置上述兩個配置項,而且sentinel須要鏈接master和slave,須要設置參數:sentinel auth-pass <master_name> xxxxx。
一、分別查看sentinel日誌可看到以下記錄
可看到+monitor master mymaster 192.168.244.128 6379 quorum 2
+sentinel sentinel f578550308896289052a62744d7fd711f8e19d3f 192.168.244.130 26379 @ mymaster 192.168.244.128 6379
+sentinel sentinel b1538910277b0df2ea52c653cb2eed2a521c6ca1 192.168.244.131 26379 @ mymaster 192.168.244.128 6379
以下說明sentinel集羣啓動成功
二、服務器info 命令查看信息
192.168.244.128
192.168.244.130
192.168.244.131
三、關閉主redis info命令查看
192.168.244.131 已經成爲主服務器
192.168.244.130 已經成爲131 的從服務器
四、能夠查看主服務器停掉以後sentinel的日誌是如何切換主備的
五、從新啓動後的主服務器變成了從服務器