Redis哨兵機制(sentinel)


1、簡介:

1、是什么:

    Redis-Sentinel是Redis官方推薦的高可用(HA)方案,當用Reids 做master-slave高可用方案時,假如master宕機了,redis本身(包括它的很多客服端)都沒有實現自動的主備切換,而Redis-Sentinel本身也是一個獨立運行的進程,它能監控多個master-slave集群,發現master宕機后能自動切換。

2、功能

  • 不時監控redis是否按照預期的良好的運行。
  • 如果發現某個redis節點運行出現狀況,能夠通知別外一個進程(如它的客戶端)。
  • 能夠進行自動切換。當一個master節點不可用時,能夠選舉出master的多個slave(如果超過一個slave的話)中的一個來作為新的master,其它的slave節點會將他的master地址改為新提升為master的服務器的地址。

4、優缺點:

優點:

  • 哨兵模式是基於主從模式的,所有主從的優點,哨兵模式都有。
  • 主從可以自動切換,系統更健壯,可用性更高

缺點:

  • redis較難支持在線擴容,在集群容量達上限時在線擴容變的很復雜。

2、原理:

1、哨兵的工作方式:

  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狀態被移除。

2、原理

  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信息的消息。

4、是檢測機制,5、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哪里復制數據。

3、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狀態。

4、配置版本號

  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都會得到一個獨一無二的版本號。

5、配置傳播

  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時必須被授權一個版本號的原因。

  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集群最終會采用版本號最高且相同的配置。

6、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添加上去。

7、網絡隔離時的一致性

例子:

  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指定了這個時間)。

8、Slave選舉與優先級

當一個sentinel准備好了要進行failover,並且收到了其他sentinel的授權,那么就需要選舉出一個合適的slave來做為新的master。

slave的選舉主要會評估slave的以下幾個方面:

  • 與master斷開連接的次數

  • Slave的優先級

  • 數據復制的下標(用來評估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哪里復制數據。

3、配置

1、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

2、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

3、啟動命令

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

4、驗證

1、分別查看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集群啟動成功

2、服務器info 命令查看信息

192.168.244.128

image

192.168.244.130

image

192.168.244.131

image

3、關閉主redis info命令查看

192.168.244.131 已經成為主服務器

image

192.168.244.130 已經成為131 的從服務器

image

4、可以查看主服務器停掉之后sentinel的日志是如何切換主備的


image

5、重新啟動后的主服務器變成了從服務器

image

 

整理自:https://www.cnblogs.com/zhoujinyi/p/5570024.html

           https://www.cnblogs.com/zhoujinyi/p/5569462.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM