Redis Sentinel機制與用法(一)

概述

Redis-Sentinel是Redis官方推薦的高可用性(HA)解決方案,當(dāng)用Redis做Master-slave的高可用方案時,假如master宕機了,Redis本身(包括它的很多客戶端)都沒有實現(xiàn)自動進行主備切換,而Redis-sentinel本身也是一個獨立運行的進程,它能監(jiān)控多個master-slave集群,發(fā)現(xiàn)master宕機后能進行自懂切換。

它的主要功能有以下幾點

不時地監(jiān)控redis是否按照預(yù)期良好地運行;

如果發(fā)現(xiàn)某個redis節(jié)點運行出現(xiàn)狀況,能夠通知另外一個進程(例如它的客戶端);

能夠進行自動切換。當(dāng)一個master節(jié)點不可用時,能夠選舉出master的多個slave(如果有超過一個slave的話)中的一個來作為新的master,其它的slave節(jié)點會將它所追隨的master的地址改為被提升為master的slave的新地址。


Sentinel支持集群

很顯然,只使用單個sentinel進程來監(jiān)控redis集群是不可靠的,當(dāng)sentinel進程宕掉后(sentinel本身也有單點問題,single-point-of-failure)整個集群系統(tǒng)將無法按照預(yù)期的方式運行。所以有必要將sentinel集群,這樣有幾個好處:

即使有一些sentinel進程宕掉了,依然可以進行redis集群的主備切換;

如果只有一個sentinel進程,如果這個進程運行出錯,或者是網(wǎng)絡(luò)堵塞,那么將無法實現(xiàn)redis集群的主備切換(單點問題);

如果有多個sentinel,redis的客戶端可以隨意地連接任意一個sentinel來獲得關(guān)于redis集群中的信息。

Sentinel版本

Sentinel當(dāng)前最新的穩(wěn)定版本稱為Sentinel 2(與之前的Sentinel 1區(qū)分開來)。隨著redis2.8的安裝包一起發(fā)行。安裝完Redis2.8后,可以在redis2.8/src/里面找到Redis-sentinel的啟動程序。

強烈建議

如果你使用的是redis2.6(sentinel版本為sentinel 1),你最好應(yīng)該使用redis2.8版本的sentinel 2,因為sentinel 1有很多的Bug,已經(jīng)被官方棄用,所以強烈建議使用redis2.8以及sentinel 2。

運行Sentinel

運行sentinel有兩種方式:

第一種

redis-sentinel /path/to/sentinel.conf

第二種

redis-server /path/to/sentinel.conf--sentinel

以上兩種方式,都必須指定一個sentinel的配置文件sentinel.conf,如果不指定,將無法啟動sentinel。sentinel默認監(jiān)聽26379端口,所以運行前必須確定該端口沒有被別的進程占用。

Sentinel的配置

Redis源碼包中包含了一個sentinel.conf文件作為sentinel的配置文件,配置文件自帶了關(guān)于各個配置項的解釋。典型的配置項如下所示:

sentinelmonitormymaster 127.0.0.1 6379 2sentinel down-after-milliseconds mymaster 60000sentinel failover-timeout mymaster 180000sentinel parallel-syncs mymaster 1sentinelmonitorresque 192.168.1.3 6380 4sentinel down-after-milliseconds resque 10000sentinel failover-timeout resque 180000sentinel parallel-syncs resque 5

上面的配置項配置了兩個名字分別為mymaster和resque的master,配置文件只需要配置master的信息就好啦,不用配置slave的信息,因為slave能夠被自動檢測到(master節(jié)點會有關(guān)于slave的消息)。需要注意的是,配置文件在sentinel運行期間是會被動態(tài)修改的,例如當(dāng)發(fā)生主備切換時候,配置文件中的master會被修改為另外一個slave。這樣,之后sentinel如果重啟時,就可以根據(jù)這個配置來恢復(fù)其之前所監(jiān)控的redis集群的狀態(tài)。

接下來我們將一行一行地解釋上面的配置項

sentinelmonitormymaster 127.0.0.1 6379 2

這一行代表sentinel監(jiān)控的master的名字叫做mymaster,地址為127.0.0.1:6379,行尾最后的一個2代表什么意思呢?我們知道,網(wǎng)絡(luò)是不可靠的,有時候一個sentinel會因為網(wǎng)絡(luò)堵塞而誤以為一個master redis已經(jīng)死掉了,當(dāng)sentinel集群式,解決這個問題的方法就變得很簡單,只需要多個sentinel互相溝通來確認某個master是否真的死了,這個2代表,當(dāng)集群中有2個sentinel認為master死了時,才能真正認為該master已經(jīng)不可用了。(sentinel集群中各個sentinel也有互相通信,通過gossip協(xié)議)。

除了第一行配置,我們發(fā)現(xiàn)剩下的配置都有一個統(tǒng)一的格式:

sentinel

接下來我們根據(jù)上面格式中的option_name一個一個來解釋這些配置項:

down-after-milliseconds

sentinel會向master發(fā)送心跳PING來確認master是否存活,如果master在“一定時間范圍”內(nèi)不回應(yīng)PONG或者是回復(fù)了一個錯誤消息,那么這個sentinel會主觀地(單方面地)認為這個master已經(jīng)不可用了(subjectively down, 也簡稱為SDOWN)。而這個down-after-milliseconds就是用來指定這個“一定時間范圍”的,單位是毫秒。

不過需要注意的是,這個時候sentinel并不會馬上進行failover主備切換,這個sentinel還需要參考sentinel集群中其他sentinel的意見,如果超過某個數(shù)量的sentinel也主觀地認為該master死了,那么這個master就會被客觀地(注意哦,這次不是主觀,是客觀,與剛才的subjectively down相對,這次是objectively down,簡稱為ODOWN)認為已經(jīng)死了。需要一起做出決定的sentinel數(shù)量在上一條配置中進行配置。

parallel-syncs

在發(fā)生failover主備切換時,這個選項指定了最多可以有多少個slave同時對新的master進行同步,這個數(shù)字越小,完成failover所需的時間就越長,但是如果這個數(shù)字越大,就意味著越多的slave因為replication而不可用??梢酝ㄟ^將這個值設(shè)為 1 來保證每次只有一個slave處于不能處理命令請求的狀態(tài)。

其他配置項在sentinel.conf中都有很詳細的解釋。

所有的配置都可以在運行時用命令SENTINEL SET command動態(tài)修改。

Sentinel的“仲裁會”

前面我們談到,當(dāng)一個master被sentinel集群監(jiān)控時,需要為它指定一個參數(shù),這個參數(shù)指定了當(dāng)需要判決master為不可用,并且進行failover時,所需要的sentinel數(shù)量,本文中我們暫時稱這個參數(shù)為票數(shù)

不過,當(dāng)failover主備切換真正被觸發(fā)后,failover并不會馬上進行,還需要sentinel中的大多數(shù)sentinel授權(quán)后才可以進行failover。

當(dāng)ODOWN時,failover被觸發(fā)。failover一旦被觸發(fā),嘗試去進行failover的sentinel會去獲得“大多數(shù)”sentinel的授權(quán)(如果票數(shù)比大多數(shù)還要大的時候,則詢問更多的sentinel)

這個區(qū)別看起來很微妙,但是很容易理解和使用。例如,集群中有5個sentinel,票數(shù)被設(shè)置為2,當(dāng)2個sentinel認為一個master已經(jīng)不可用了以后,將會觸發(fā)failover,但是,進行failover的那個sentinel必須先獲得至少3個sentinel的授權(quán)才可以實行failover。

如果票數(shù)被設(shè)置為5,要達到ODOWN狀態(tài),必須所有5個sentinel都主觀認為master為不可用,要進行failover,那么得獲得所有5個sentinel的授權(quán)。

配置版本號

為什么要先獲得大多數(shù)sentinel的認可時才能真正去執(zhí)行failover呢?

當(dāng)一個sentinel被授權(quán)后,它將會獲得宕掉的master的一份最新配置版本號,當(dāng)failover執(zhí)行結(jié)束以后,這個版本號將會被用于最新的配置。因為大多數(shù)sentinel都已經(jīng)知道該版本號已經(jīng)被要執(zhí)行failover的sentinel拿走了,所以其他的sentinel都不能再去使用這個版本號。這意味著,每次failover都會附帶有一個獨一無二的版本號。我們將會看到這樣做的重要性。

而且,sentinel集群都遵守一個規(guī)則:如果sentinel A推薦sentinel B去執(zhí)行failover,B會等待一段時間后,自行再次去對同一個master執(zhí)行failover,這個等待的時間是通過failover-timeout配置項去配置的。從這個規(guī)則可以看出,sentinel集群中的sentinel不會再同一時刻并發(fā)去failover同一個master,第一個進行failover的sentinel如果失敗了,另外一個將會在一定時間內(nèi)進行重新進行failover,以此類推。

redis sentinel保證了活躍性:如果大多數(shù)sentinel能夠互相通信,最終將會有一個被授權(quán)去進行failover.

redis sentinel也保證了安全性:每個試圖去failover同一個master的sentinel都會得到一個獨一無二的版本號。

配置傳播

一旦一個sentinel成功地對一個master進行了failover,它將會把關(guān)于master的最新配置通過廣播形式通知其它sentinel,其它的sentinel則更新對應(yīng)master的配置。

一個faiover要想被成功實行,sentinel必須能夠向選為master的slave發(fā)送SLAVE OF NO ONE命令,然后能夠通過INFO命令看到新master的配置信息。

當(dāng)將一個slave選舉為master并發(fā)送SLAVE OF NO ONE`后,即使其它的slave還沒針對新master重新配置自己,failover也被認為是成功了的,然后所有sentinels將會發(fā)布新的配置信息。

新配在集群中相互傳播的方式,就是為什么我們需要當(dāng)一個sentinel進行failover時必須被授權(quán)一個版本號的原因。

每個sentinel使用##發(fā)布/訂閱##的方式持續(xù)地傳播master的配置版本信息,配置傳播的##發(fā)布/訂閱##管道是:__sentinel__:hello。

因為每一個配置都有一個版本號,所以以版本號最大的那個為標(biāo)準(zhǔn)。

舉個栗子:假設(shè)有一個名為mymaster的地址為192.168.1.50:6379。一開始,集群中所有的sentinel都知道這個地址,于是為mymaster的配置打上版本號1。一段時候后mymaster死了,有一個sentinel被授權(quán)用版本號2對其進行failover。如果failover成功了,假設(shè)地址改為了192.168.1.50:9000,此時配置的版本號為2,進行failover的sentinel會將新配置廣播給其他的sentinel,由于其他sentinel維護的版本號為1,發(fā)現(xiàn)新配置的版本號為2時,版本號變大了,說明配置更新了,于是就會采用最新的版本號為2的配置。

這意味著sentinel集群保證了第二種活躍性:一個能夠互相通信的sentinel集群最終會采用版本號最高且相同的配置。

SDOWN和ODOWN的更多細節(jié)

sentinel對于不可用有兩種不同的看法,一個叫主觀不可用(SDOWN),另外一個叫客觀不可用(ODOWN)。SDOWN是sentinel自己主觀上檢測到的關(guān)于master的狀態(tài),ODOWN需要一定數(shù)量的sentinel達成一致意見才能認為一個master客觀上已經(jīng)宕掉,各個sentinel之間通過命令SENTINEL is_master_down_by_addr來獲得其它sentinel對master的檢測結(jié)果。

從sentinel的角度來看,如果發(fā)送了PING心跳后,在一定時間內(nèi)沒有收到合法的回復(fù),就達到了SDOWN的條件。這個時間在配置中通過is-master-down-after-milliseconds參數(shù)配置。

當(dāng)sentinel發(fā)送PING后,以下回復(fù)之一都被認為是合法的:

PINGrepliedwith+PONG.PINGrepliedwith-LOADING error.PINGrepliedwith-MASTERDOWN error.

其它任何回復(fù)(或者根本沒有回復(fù))都是不合法的。

從SDOWN切換到ODOWN不需要任何一致性算法,只需要一個gossip協(xié)議:如果一個sentinel收到了足夠多的sentinel發(fā)來消息告訴它某個master已經(jīng)down掉了,SDOWN狀態(tài)就會變成ODOWN狀態(tài)。如果之后master可用了,這個狀態(tài)就會相應(yīng)地被清理掉。

正如之前已經(jīng)解釋過了,真正進行failover需要一個授權(quán)的過程,但是所有的failover都開始于一個ODOWN狀態(tài)。

ODOWN狀態(tài)只適用于master,對于不是master的redis節(jié)點sentinel之間不需要任何協(xié)商,slaves和sentinel不會有ODOWN狀態(tài)。

Sentinel之間和Slaves之間的自動發(fā)現(xiàn)機制

雖然sentinel集群中各個sentinel都互相連接彼此來檢查對方的可用性以及互相發(fā)送消息。但是你不用在任何一個sentinel配置任何其它的sentinel的節(jié)點。因為sentinel利用了master的發(fā)布/訂閱機制去自動發(fā)現(xiàn)其它也監(jiān)控了統(tǒng)一master的sentinel節(jié)點。

通過向名為__sentinel__:hello的管道中發(fā)送消息來實現(xiàn)。

同樣,你也不需要在sentinel中配置某個master的所有slave的地址,sentinel會通過詢問master來得到這些slave的地址的。

每個sentinel通過向每個master和slave的發(fā)布/訂閱頻道__sentinel__:hello每秒發(fā)送一次消息,來宣布它的存在。

每個sentinel也訂閱了每個master和slave的頻道__sentinel__:hello的內(nèi)容,來發(fā)現(xiàn)未知的sentinel,當(dāng)檢測到了新的sentinel,則將其加入到自身維護的master監(jiān)控列表中。

每個sentinel發(fā)送的消息中也包含了其當(dāng)前維護的最新的master配置。如果某個sentinel發(fā)現(xiàn)

自己的配置版本低于接收到的配置版本,則會用新的配置更新自己的master配置。

在為一個master添加一個新的sentinel前,sentinel總是檢查是否已經(jīng)有sentinel與新的sentinel的進程號或者是地址是一樣的。如果是那樣,這個sentinel將會被刪除,而把新的sentinel添加上去。

網(wǎng)絡(luò)隔離時的一致性

redis sentinel集群的配置的一致性模型為最終一致性,集群中每個sentinel最終都會采用最高版本的配置。然而,在實際的應(yīng)用環(huán)境中,有三個不同的角色會與sentinel打交道:

Redis實例.

Sentinel實例.

客戶端.

為了考察整個系統(tǒng)的行為我們必須同時考慮到這三個角色。

下面有個簡單的例子,有三個主機,每個主機分別運行一個redis和一個sentinel:

+-------------+? ? ? ? ? ? |Sentinel 1|<--- Client A|Redis 1 (M)|? ? ? ? ? ? +-------------+? ? ? ? ? ? ? ? ? ? || +-------------+? ? |+------------+|Sentinel 2|-----+-- / partition / ----|Sentinel 3|<--- Client B|Redis 2 (S)||Redis 3 (M)| +-------------+? ? ? ? ? ? ? ? ? ? ? ? ? +------------+

在這個系統(tǒng)中,初始狀態(tài)下redis3是master, redis1和redis2是slave。之后redis3所在的主機網(wǎng)絡(luò)不可用了,sentinel1和sentinel2啟動了failover并把redis1選舉為master。

Sentinel集群的特性保證了sentinel1和sentinel2得到了關(guān)于master的最新配置。但是sentinel3依然持著的是就的配置,因為它與外界隔離了。

當(dāng)網(wǎng)絡(luò)恢復(fù)以后,我們知道sentinel3將會更新它的配置。但是,如果客戶端所連接的master被網(wǎng)絡(luò)隔離,會發(fā)生什么呢?

客戶端將依然可以向redis3寫數(shù)據(jù),但是當(dāng)網(wǎng)絡(luò)恢復(fù)后,redis3就會變成redis的一個slave,那么,在網(wǎng)絡(luò)隔離期間,客戶端向redis3寫的數(shù)據(jù)將會丟失。

也許你不會希望這個場景發(fā)生:

如果你把redis當(dāng)做緩存來使用,那么你也許能容忍這部分?jǐn)?shù)據(jù)的丟失。

但如果你把redis當(dāng)做一個存儲系統(tǒng)來使用,你也許就無法容忍這部分?jǐn)?shù)據(jù)的丟失了。

因為redis采用的是異步復(fù)制,在這樣的場景下,沒有辦法避免數(shù)據(jù)的丟失。然而,你可以通過以下配置來配置redis3和redis1,使得數(shù)據(jù)不會丟失。

min-slaves-to-write1min-slaves-max-lag10

通過上面的配置,當(dāng)一個redis是master時,如果它不能向至少一個slave寫數(shù)據(jù)(上面的min-slaves-to-write指定了slave的數(shù)量),它將會拒絕接受客戶端的寫請求。由于復(fù)制是異步的,master無法向slave寫數(shù)據(jù)意味著slave要么斷開連接了,要么不在指定時間內(nèi)向master發(fā)送同步數(shù)據(jù)的請求了(上面的min-slaves-max-lag指定了這個時間)。

Sentinel狀態(tài)持久化

snetinel的狀態(tài)會被持久化地寫入sentinel的配置文件中。每次當(dāng)收到一個新的配置時,或者新創(chuàng)建一個配置時,配置會被持久化到硬盤中,并帶上配置的版本戳。這意味著,可以安全的停止和重啟sentinel進程。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.1 資料 ,最好的入門小冊子,可以先于一切文檔之前看,免費。 作者Antirez的博客,Antirez維護的R...
    JefferyLcm閱讀 17,293評論 1 51
  • Codis高可用方案官方推薦使用Sentinel Redis 本身就是最終一致性的。Master 掛了,Promo...
    三杯水Plus閱讀 2,979評論 2 8
  • NOSQL類型簡介鍵值對:會使用到一個哈希表,表中有一個特定的鍵和一個指針指向特定的數(shù)據(jù),如redis,volde...
    MicoCube閱讀 4,150評論 2 27
  • 想做一個世外高人 隱于市、隱于林 一套嶄新的生活哲學(xué) 不媚不俗 遠離遍地的無聊 只惠及偶遇的人們 既光明 又美好
    湖底笛閱讀 267評論 0 0
  • 這兩天,伴隨著教師節(jié)的到來,朋友圈里到處彌漫著各種致敬恩師的圖文信息,雖然我們很多人可能已經(jīng)記不起小學(xué)、初中教師長...
    3e59d1ae9361閱讀 885評論 0 0

友情鏈接更多精彩內(nèi)容