Redis哨兵機制(sentinel)

一、簡介:

一、是什麼:

    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較難支持在線擴容,在集羣容量達上限時在線擴容變的很複雜。

二、原理:

一、哨兵的工做方式:

  1. 每一個Sentinel(哨兵)進程以每秒鐘一次的頻率向整個redis集羣中的master主服務器、slave從服務器以及其餘的Sentinel(哨兵)進程發送一個ping命令。
  2. 若是一個實例距離最後一次有效回覆ping命令的時間超過down-after-milliseconds選項所指定的值則這個實例會被Sentinel標記爲主觀下線(SDOWN)。
  3. 如是是master主服務器被標記爲SDOWN,則正在監控這個服務器的全部Sentinel都要以每秒一次的頻率確認服務器是否真的已經進入SDOWN(主觀下線狀態)。
  4. 當有足夠數量(≥配置文件配置值)的Sentinel在指定的時間內確認了master進入了SDOWN狀態,則master被標記爲ODOWN(客觀下線狀態)。
  5. 在通常狀況下,每一個Sentinel會每10秒向redis 主服務器和從服務器發送Info命令。可是當master被標記爲客觀下線時,頻率改成1秒一次。
  6. 若沒有足夠數量的Sentinel贊成master服務器下線,則master的SDOWN狀態被移除,若master從新向Sentinel發送ping命令返回了有效回覆,則master的SDOWN狀態被移除。

二、原理

  1. Sentinel集羣經過給定的配置文件發現master,啓動時會監控master。經過向master發送info信息得到該服務下面的全部從服務器。
  2. Sentinel集羣經過命令鏈接向被監控的主從服務器發送hello信息(每秒一次),該信息包括Sentinel自己的ip、端口、id等內容,以此來向其餘Sentinel宣告本身的存在。
  3. Sentinel集羣經過訂閱鏈接接收其餘Sentinel發送的hello信息,以此來發現監視同一個主服務器的其餘Sentinel;集羣之間會互相建立命令鏈接用於通訊,由於已經有主從服務器做爲發送和接收hello信息的中介,Sentinel之間不會建立訂閱鏈接。
  4. Sentinel集羣使用Sentinel命令來檢測實例的狀態,若是指定的時間內(down-after-milliseconds)沒有回覆或者返回錯誤回覆,那麼該實例被判爲主觀下線SDOWN。
  5. 當failover主備切換被觸發後,failover並不會立刻進行,還須要Sentinel集羣中另外quorum個其餘Sentinel受權,成功後進入ODOWN客觀下線狀態,以後再進行failover。
  6. Sentinel向選爲master的slave發送slaveof no one 命令,選擇slave的條件是首先會根據slave的優先級來排序,優先級越小排名越靠前。若是相同,則查看複製的下標,哪一個接收master的複製數據越多哪一個越靠前,若是兩個都同樣就選擇進程ID較小的。
  7. 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

  1. sentinel對於不可用有兩種不一樣的見解,一個叫主觀不可用(SDOWN),另一個叫客觀不可用(ODOWN)。
  2. SDOWN是sentinel本身主觀上檢測到的關於master的狀態,ODOWN須要必定數量的sentinel達成一致意見才能認爲一個master客觀上已經宕掉,各個sentinel之間經過命令SENTINEL is_master_down_by_addr來得到其它sentinel對master的檢測結果。
  3. 從sentinel的角度來看,若是發送了PING心跳後,在必定時間內沒有收到合法的回覆,就達到了SDOWN的條件。這個時間在配置中經過is-master-down-after-milliseconds參數配置。
  4. 從SDOWN切換到ODOWN不須要任何一致性算法,只須要一個gossip協議:若是一個sentinel收到了足夠多的sentinel發來消息告訴它某個master已經down掉了,SDOWN狀態就會變成ODOWN狀態。若是以後master可用了,這個狀態就會相應地被清理掉。
  5. 真正進行failover須要一個受權的過程,可是全部的failover都開始於一個ODOWN狀態。
  6. ODOWN狀態只適用於master,對於不是master的redis節點sentinel之間不須要任何協商,slaves和sentinel不會有ODOWN狀態。

四、配置版本號

  1. 爲何要先得到大多數sentinel的承認時才能真正去執行failover呢?
  2. 當一個sentinel被受權後,它將會得到宕掉的master的一份最新配置版本號,當failover執行結束之後,這個版本號將會被用於最新的配置。由於大多數sentinel都已經知道該版本號已經被要執行failover的sentinel拿走了,因此其餘的sentinel都不能再去使用這個版本號。這意味着,每次failover都會附帶有一個獨一無二的版本號。咱們將會看到這樣作的重要性。
  3. 並且,sentinel集羣都遵照一個規則:若是sentinel A推薦sentinel B去執行failover,B會等待一段時間後,自行再次去對同一個master執行failover,這個等待的時間是經過failover-timeout配置項去配置的。從這個規則能夠看出,sentinel集羣中的sentinel不會再同一時刻併發去failover同一個master,第一個進行failover的sentinel若是失敗了,另一個將會在必定時間內進行從新進行failover,以此類推。
  4. redis sentinel保證了活躍性:若是大多數sentinel可以互相通訊,最終將會有一個被受權去進行failover.
    redis sentinel也保證了安全性:每一個試圖去failover同一個master的sentinel都會獲得一個獨一無二的版本號。

五、配置傳播

  1. 一旦一個sentinel成功地對一個master進行了failover,它將會把關於master的最新配置經過廣播形式通知其它sentinel,其它的sentinel則更新對應master的配置。
  2. 一個faiover要想被成功實行,sentinel必須可以向選爲master的slave發送SLAVEOF NO ONE命令,而後可以經過INFO命令看到新master的配置信息。
  3. 當將一個slave選舉爲master併發送SLAVEOF NO ONE後,即便其它的slave還沒針對新master從新配置本身,failover也被認爲是成功了的,而後全部sentinels將會發布新的配置信息。

新配在集羣中相互傳播的方式,就是爲何咱們須要當一個sentinel進行failover時必須被受權一個版本號的緣由。node

  1. 每一個sentinel使用##發佈/訂閱##的方式持續地傳播master的配置版本信息,配置傳播的##發佈/訂閱##管道是:__sentinel__:hello
  2. 由於每個配置都有一個版本號,因此以版本號最大的那個爲標準。

舉個栗子:

  1. 假設有一個名爲mymaster的地址爲192.168.1.50:6379。一開始,集羣中全部的sentinel都知道這個地址,因而爲mymaster的配置打上版本號1。
  2. 一段時候後mymaster死了,有一個sentinel被受權用版本號2對其進行failover。
  3. 若是failover成功了,假設地址改成了192.168.1.50:9000,此時配置的版本號爲2,進行failover的sentinel會將新配置廣播給其餘的sentinel
  4. 因爲其餘sentinel維護的版本號爲1,發現新配置的版本號爲2時,版本號變大了,說明配置更新了,因而就會採用最新的版本號爲2的配置。

這意味着sentinel集羣保證了第二種活躍性:一個可以互相通訊的sentinel集羣最終會採用版本號最高且相同的配置。redis

六、Sentinel之間和Slaves之間的自動發現機制

  1. 雖然sentinel集羣中各個sentinel都互相鏈接彼此來檢查對方的可用性以及互相發送消息。可是你不用在任何一個sentinel配置任何其它的sentinel的節點。由於sentinel利用了master的發佈/訂閱機制去自動發現其它也監控了統一master的sentinel節點。經過向名爲__sentinel__:hello的管道中發送消息來實現。
  2. 一樣,你也不須要在sentinel中配置某個master的全部slave的地址,sentinel會經過詢問master來獲得這些slave的地址的。
  3. 每一個sentinel經過向每一個master和slave的發佈/訂閱頻道__sentinel__:hello每秒發送一次消息,來宣佈它的存在。
  4. 每一個sentinel也訂閱了每一個master和slave的頻道__sentinel__:hello的內容,來發現未知的sentinel,當檢測到了新的sentinel,則將其加入到自身維護的master監控列表中。
  5. 每一個sentinel發送的消息中也包含了其當前維護的最新的master配置。若是某個sentinel發現本身的配置版本低於接收到的配置版本,則會用新的配置更新本身的master配置。
  6. 在爲一個master添加一個新的sentinel前,sentinel老是檢查是否已經有sentinel與新的sentinel的進程號或者是地址是同樣的。若是是那樣,這個sentinel將會被刪除,而把新的sentinel添加上去。

七、網絡隔離時的一致性

例子:算法

  1. 有三個主機,每一個主機分別運行一個redis和一個sentinel。初始狀態下redis3是master, redis1和redis2是slave。
  2. 以後redis3所在的主機網絡不可用了,sentinel1和sentinel2啓動了failover並把redis1選舉爲master。
  3. Sentinel集羣的特性保證了sentinel1和sentinel2獲得了關於master的最新配置。可是sentinel3依然是舊的配置,由於它與外界隔離了。

當網絡恢復之後,咱們知道sentinel3將會更新它的配置。可是,若是客戶端所鏈接的master被網絡隔離,會發生什麼呢?安全

  1. 客戶端將依然能夠向redis3寫數據,可是當網絡恢復後,redis3就會變成redis的一個slave,那麼,在網絡隔離期間,客戶端向redis3寫的數據將會丟失。
  2. 由於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候選人列表,並根據如下順序來進行排序:

  1. sentinel首先會根據slaves的優先級來進行排序,優先級越小排名越靠前。

  2. 若是優先級相同,則查看複製的下標,哪一個從master接收的複製數據多,哪一個就靠前。

  3. 若是優先級和下標都相同,就選擇進程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日誌可看到以下記錄

image

可看到+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

image

192.168.244.130

image

192.168.244.131

image

三、關閉主redis info命令查看

192.168.244.131 已經成爲主服務器

image

192.168.244.130 已經成爲131 的從服務器

image

四、能夠查看主服務器停掉以後sentinel的日誌是如何切換主備的


image

五、從新啓動後的主服務器變成了從服務器

image

 

整理自:http://www.javashuo.com/article/p-trqnlfbk-bg.html

           http://www.javashuo.com/article/p-pfxbqtku-cd.html

相關文章
相關標籤/搜索