Redis-Sentinel是Redis官方推薦的高可用性(HA)解決方案。實際上這意味着你可使用Sentinel模式建立一個能夠不用人爲干預而應對各類故障的Redis部署。html
它的主要功能有如下幾點正則表達式
監控:Sentinel不斷的檢查master和slave是否正常的運行。redis
通知:若是發現某個redis節點運行出現問題,能夠經過API通知系統管理員和其餘的應用程序。算法
自動故障轉移:可以進行自動切換。當一個master節點不可用時,可以選舉出master的多個slave中的一個來做爲新的master,其它的slave節點會將它所追隨的master的地址改成被提高爲master的slave的新地址。segmentfault
配置提供者:哨兵做爲Redis客戶端發現的權威來源:客戶端鏈接到哨兵請求當前可靠的master的地址。若是發生故障,哨兵將報告新地址。緩存
很顯然,只使用單個sentinel進程來監控redis集羣是不可靠的,當sentinel進程宕掉後(sentinel自己也有單點問題,single-point-of-failure)整個集羣系統將沒法按照預期的方式運行。因此有必要將sentinel集羣,這樣有幾個好處:安全
即便有一些sentinel進程宕掉了,依然能夠進行redis集羣的主備切換;ruby
若是隻有一個sentinel進程,若是這個進程運行出錯,或者是網絡堵塞,那麼將沒法實現redis集羣的主備切換(單點問題);網絡
若是有多個sentinel,redis的客戶端能夠隨意地鏈接任意一個sentinel來得到關於redis集羣中的信息。併發
當前的哨兵版本是sentinel 2。它是基於最初哨兵的實現,使用更健壯的和更簡單的預算算法(在這個文檔裏有解釋)重寫的。
Redis2.8和Redis3.0附帶穩定的哨兵版本。他們是Redis的兩個最新穩定版本。
在不穩定版本的分支上執行新的改進,且有時一些新特性一旦被認爲是穩定的就會被移植到Redis2.8和Redis3.0分支中。
Redis2.6附帶Redis sentinel 1,它是棄用的不建議使用。
運行Sentinel有兩種方式,以下:
redis-sentinel /path/to/sentinel.conf
redis-server /path/to/sentinel.conf --sentinel
兩種方式效果都是同樣的。
然而在啓動哨兵時必須使用一個配置文件,由於這個配置文件將用於系統保存當前狀態和在重啓時從新加載。哨兵會在沒有指定配置文件或指定的配置文件不可寫的時候拒絕啓動。
Redis 哨兵默認監聽26379 TCP端口,因此爲了哨兵的正常工做,你的26379端口必須開放接收其餘哨兵實例的IP地址的鏈接。不然哨兵不能通訊和商定作什麼,故障轉移將永不會執行。
一個健壯的部署至少須要三個哨兵實例。
三個哨兵實例應該放置在客戶使用獨立方式確認故障的計算機或虛擬機中。例如不一樣的物理機或不一樣可用區域的虛擬機。
sentinel + Redis實例不保證在故障期間保留確認的寫入,由於Redis使用異步複製。然而有方式部署哨兵使丟失數據限制在特定時刻,雖然有更安全的方式部署它。
你的客戶端要支持哨兵,流行的客戶端都支持哨兵,但不是所有。
沒有HA設置是安全的,若是你不常常的在開發環境測試,在生產環境他們會更好。你可能會有一個明顯的錯誤配置只是當太晚的時候。
Sentinel,Docker,或者其餘形式的網絡地址交換或端口映射須要加倍當心:Docker執行端口從新映射,破壞Sentinel自動發現其餘的哨兵進程和master的slave列表。稍後在這個文檔裏檢查關於Sentinel和Docker的部分,瞭解更多信息。
Redis源碼發佈包包含一個sentinel.conf的文件,默認的配置文件中有關於各個配置項的詳細解釋,一個典型的最小的配置文件就像下面的配置:
sentinel monitor mymaster 127.0.0.1 6379 2 sentinel down-after-milliseconds mymaster 60000 sentinel failover-timeout mymaster 180000 sentinel parallel-syncs mymaster 1
sentinel monitor resque 192.168.1.3 6380 4 sentinel down-after-milliseconds resque 10000 sentinel failover-timeout resque 180000 sentinel parallel-syncs resque 5
上面的配置項配置了兩個名字分別爲mymaster和resque的master,配置文件只須要配置master的信息就好啦,不用配置slave的信息,由於slave可以被自動檢測到(master節點中有關於slave的消息)。
爲了更清晰,咱們逐行的解釋每一個選項的含義:
第一行的格式以下:
sentinel monitor [master-group-name] [ip] [port] [quorum]
master-group-name:master名稱
quorun:本文叫作票數,Sentinel須要協商贊成master是否可到達的數量。
sentinel monitor mymaster 127.0.0.1 6379 2
這一行用於告訴Redis監控一個master叫作mymaster,它的地址在127.0.0.1,端口爲6379,票數是2。
這裏的票數須要解釋下:舉個栗子,redis集羣中有5個sentinel實例,其中master掛掉啦,若是這裏的票數是2,表示有2個sentinel認爲master掛掉啦,才能被認爲是正真的掛掉啦。其中sentinel集羣中各個sentinel也有互相通訊,經過gossip協議。
除啦第一行其餘的格式以下:
sentinel [option_name] [master_name] [option_value]
down-after-milliseconds
sentinel會向master發送心跳PING來確認master是否存活,若是master在「必定時間範圍」內不迴應PONG 或者是回覆了一個錯誤消息,那麼這個sentinel會主觀地認爲這個master已經不可用了。而這個down-after-milliseconds就是用來指定這個「必定時間範圍」的,單位是毫秒。
parallel-syncs
在發生failover主從切換時,這個選項指定了最多能夠有多少個slave同時對新的master進行同步,這個數字越小,完成主從故障轉移所需的時間就越長,可是若是這個數字越大,就意味着越多的slave由於主從同步而不可用。能夠經過將這個值設爲1來保證每次只有一個slave處於不能處理命令請求的狀態。
前面咱們談到,主從故障轉移時,須要的sentinel承認的票數達到設置的值才能夠。
不過,當failover主備切換真正被觸發後,failover並不會立刻進行,還須要sentinel中的大多數sentinel受權後才能夠進行failover。
當sentinel承認不可用的票數達到時(ODOWN),failover被觸發。failover一旦被觸發,嘗試去進行failover的sentinel會去得到「大多數」sentinel的受權(若是票數比大多數還要大的時候,則詢問更多的sentinel)
這個區別看起來很微妙,可是很容易理解和使用。例如,集羣中有5個sentinel,票數被設置爲2,當2個sentinel認爲一個master已經不可用了之後,將會觸發failover,可是,進行failover的那個sentinel必須先得到至少3個sentinel的受權才能夠實行failover。
若是票數被設置爲5,要達到ODOWN狀態,必須全部5個sentinel都主觀認爲master爲不可用,要進行failover,那麼得得到全部5個sentinel的受權。
爲何要先得到大多數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發送SLAVE OF NO ONE
命令,而後可以經過INFO
命令看到新master的配置信息。
當將一個slave選舉爲master併發送SLAVE OF NO ONE
`後,即便其它的slave還沒針對新master從新配置本身,failover也被認爲是成功了的,而後全部sentinels將會發布新的配置信息。
新配在集羣中相互傳播的方式,就是爲何咱們須要當一個sentinel進行failover時必須被受權一個版本號的緣由。
每一個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集羣最終會採用版本號最高且相同的配置。
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
參數配置。
當sentinel發送PING後,如下回復都被認爲是合法的,除此以外,其它任何回覆(或者根本沒有回覆)都是不合法的。
PING replied with +PONG. PING replied with -LOADING error. PING replied with -MASTERDOWN error.
從SDOWN切換到ODOWN不須要任何一致性算法,只須要一個gossip協議:若是一個sentinel收到了足夠多的sentinel發來消息告訴它某個master已經down掉了,SDOWN狀態就會變成ODOWN狀態。若是以後master可用了,這個狀態就會相應地被清理掉。
正如以前已經解釋過了,真正進行failover須要一個受權的過程,可是全部的failover都開始於一個ODOWN狀態。
ODOWN狀態只適用於master,對於不是master的redis節點sentinel之間不須要任何協商,slaves和sentinel不會有ODOWN狀態。
雖然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集羣的配置的一致性模型爲最終一致性,集羣中每一個sentinel最終都會採用最高版本的配置。然而,在實際的應用環境中,有三個不一樣的角色會與sentinel打交道:
Redis實例.
Sentinel實例.
客戶端.
爲了考察整個系統的行爲咱們必須同時考慮到這三個角色。
下面有個簡單的例子,有三個主機,每一個主機分別運行一個redis和一個sentinel:
+-------------+
| Sentinel 1 | <--- Client A | Redis 1 (M) | +-------------+ | | +-------------+ | +------------+ | Sentinel 2 |-----+-- / partition / ----| Sentinel 3 | <--- Client B | Redis 2 (S) | | Redis 3 (M)| +-------------+ +------------+
在這個系統中,初始狀態下redis3是master, redis1和redis2是slave。以後redis3所在的主機網絡不可用了,sentinel1和sentinel2啓動了failover並把redis1選舉爲master。
Sentinel集羣的特性保證了sentinel1和sentinel2獲得了關於master的最新配置。可是sentinel3依然持着的是就的配置,由於它與外界隔離了。
當網絡恢復之後,咱們知道sentinel3將會更新它的配置。可是,若是客戶端所鏈接的master被網絡隔離,會發生什麼呢?
客戶端將依然能夠向redis3寫數據,可是當網絡恢復後,redis3就會變成redis的一個slave,那麼,在網絡隔離期間,客戶端向redis3寫的數據將會丟失。
也許你不會但願這個場景發生:
若是你把redis當作緩存來使用,那麼你也許能容忍這部分數據的丟失。
但若是你把redis當作一個存儲系統來使用,你也許就沒法容忍這部分數據的丟失了。
由於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指定了這個時間)。
snetinel的狀態會被持久化地寫入sentinel的配置文件中。每次當收到一個新的配置時,或者新建立一個配置時,配置會被持久化到硬盤中,並帶上配置的版本戳。這意味着,能夠安全的中止和重啓sentinel進程。
即便當前沒有failover正在進行,sentinel依然會使用當前配置去設置監控的master。特別是:
根據最新配置確認爲slaves的節點卻聲稱本身是master(參考上文例子中被網絡隔離後的的redis3),這時它們會被從新配置爲當前master的slave。
若是slaves鏈接了一個錯誤的master,將會被改正過來,鏈接到正確的master。
當一個sentinel準備好了要進行failover,而且收到了其餘sentinel的受權,那麼就須要選舉出一個合適的slave來作爲新的master。
slave的選舉主要會評估slave的如下幾個方面:
與master斷開鏈接的次數
Slave的優先級
數據複製的下標(用來評估slave當前擁有多少master的數據)
進程ID
若是一個slave與master失去聯繫超過10次,而且每次都超過了配置的最大失聯時間(down-after-milliseconds option
),而且,若是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哪裏複製數據。
當一個master配置爲須要密碼才能鏈接時,客戶端和slave在鏈接時都須要提供密碼。
master經過requirepass
設置自身的密碼,不提供密碼沒法鏈接到這個master。
slave經過masterauth
來設置訪問master時的密碼。
可是當使用了sentinel時,因爲一個master可能會變成一個slave,一個slave也可能會變成master,因此須要同時設置上述兩個配置項。
Sentinel默認運行在26379端口上,sentinel支持redis協議,因此可使用redis-cli客戶端或者其餘可用的客戶端來與sentinel通訊。
有兩種方式可以與sentinel通訊:
一種是直接使用客戶端向它發消息
另一種是使用發佈/訂閱模式來訂閱sentinel事件,好比說failover,或者某個redis實例運行出錯,等等。
sentinel支持的合法命令以下:
PING
sentinel回覆PONG
.
SENTINEL masters
顯示被監控的全部master以及它們的狀態.
SENTINEL master <master name>
顯示指定master的信息和狀態;
SENTINEL slaves <master name>
顯示指定master的全部slave以及它們的狀態;
SENTINEL get-master-addr-by-name <master name>
返回指定master的ip和端口,若是正在進行failover或者failover已經完成,將會顯示被提高爲master的slave的ip和端口。
SENTINEL reset <pattern>
重置名字匹配該正則表達式的全部的master的狀態信息,清楚其以前的狀態信息,以及slaves信息。
SENTINEL failover <master name>
強制sentinel執行failover,而且不須要獲得其餘sentinel的贊成。可是failover後會將最新
從redis2.8.4開始,sentinel提供了一組API用來添加,刪除,修改master的配置。
須要注意的是,若是你經過API修改了一個sentinel的配置,sentinel不會把修改的配置告訴其餘sentinel。你須要本身手動地對多個sentinel發送修改配置的命令。
如下是一些修改sentinel配置的命令:
SENTINEL MONITOR <name> <ip> <port> <quorum>
這個命令告訴sentinel去監聽一個新的master
SENTINEL REMOVE <name>
命令sentinel放棄對某個master的監聽
SENTINEL SET <name> <option> <value>
這個命令很像Redis的CONFIG SET
命令,用來改變指定master的配置。支持多個<option><value>。例如如下實例:
SENTINEL SET objects-cache-master down-after-milliseconds 1000
只要是配置文件中存在的配置項,均可以用SENTINEL SET
命令來設置。這個還能夠用來設置master的屬性,好比說quorum(票數),而不須要先刪除master,再從新添加master。例如:
SENTINEL SET objects-cache-master quorum 5
因爲有sentinel自動發現機制,因此添加一個sentinel到你的集羣中很是容易,你所須要作的只是監控到某個Master上,而後新添加的sentinel就能得到其餘sentinel的信息以及masterd全部的slave。
若是你須要添加多個sentinel,建議你一個接着一個添加,這樣能夠預防網絡隔離帶來的問題。你能夠每一個30秒添加一個sentinel。最後你能夠用SENTINEL MASTER mastername
來檢查一下是否全部的sentinel都已經監控到了master。
刪除一個sentinel顯得有點複雜:由於sentinel永遠不會刪除一個已經存在過的sentinel,即便它已經與組織失去聯繫好久了。要想刪除一個sentinel,應該遵循以下步驟:
中止所要刪除的sentinel
發送一個SENTINEL RESET *
命令給全部其它的sentinel實例,若是你想要重置指定master上面的sentinel,只須要把*號改成特定的名字,注意,須要一個接一個發,每次發送的間隔不低於30秒。
檢查一下全部的sentinels是否都有一致的當前sentinel數。使用SENTINEL MASTER mastername
來查詢。
sentinel永遠會記錄好一個Master的slaves,即便slave已經與組織失聯很久了。這是頗有用的,由於sentinel集羣必須有能力把一個恢復可用的slave進行從新配置。
而且,failover後,失效的master將會被標記爲新master的一個slave,這樣的話,當它變得可用時,就會重新master上覆制數據。
而後,有時候你想要永久地刪除掉一個slave(有可能它曾經是個master),你只須要發送一個SENTINEL RESET master
命令給全部的sentinels,它們將會更新列表裏可以正確地複製master數據的slave。
客戶端能夠向一個sentinel發送訂閱某個頻道的事件的命令,當有特定的事件發生時,sentinel會通知全部訂閱的客戶端。須要注意的是客戶端只能訂閱,不能發佈。
訂閱頻道的名字與事件的名字一致。例如,頻道名爲sdown 將會發布全部與SDOWN相關的消息給訂閱者。
若是想要訂閱全部消息,只需簡單地使用PSUBSCRIBE *
如下是全部你能夠收到的消息的消息格式,若是你訂閱了全部消息的話。第一個單詞是頻道的名字,其它是數據的格式。
注意:如下的instance details的格式是:
<instance-type> <name> <ip> <port> @ <master-name> <master-ip> <master-port>
若是這個redis實例是一個master,那麼@以後的消息就不會顯示。
+reset-master <instance details> -- 當master被重置時. +slave <instance details> -- 當檢測到一個slave並添加進slave列表時. +failover-state-reconf-slaves <instance details> -- Failover狀態變爲reconf-slaves狀態時 +failover-detected <instance details> -- 當failover發生時 +slave-reconf-sent <instance details> -- sentinel發送SLAVEOF命令把它從新配置時 +slave-reconf-inprog <instance details> -- slave被從新配置爲另一個master的slave,但數據複製還未發生時。 +slave-reconf-done <instance details> -- slave被從新配置爲另一個master的slave而且數據複製已經與master同步時。 -dup-sentinel <instance details> -- 刪除指定master上的冗餘sentinel時 (當一個sentinel從新啓動時,可能會發生這個事件). +sentinel <instance details> -- 當master增長了一個sentinel時。 +sdown <instance details> -- 進入SDOWN狀態時; -sdown <instance details> -- 離開SDOWN狀態時。 +odown <instance details> -- 進入ODOWN狀態時。 -odown <instance details> -- 離開ODOWN狀態時。 +new-epoch <instance details> -- 當前配置版本被更新時。 +try-failover <instance details> -- 達到failover條件,正等待其餘sentinel的選舉。 +elected-leader <instance details> -- 被選舉爲去執行failover的時候。 +failover-state-select-slave <instance details> -- 開始要選擇一個slave當選新master時。 no-good-slave <instance details> -- 沒有合適的slave來擔當新master selected-slave <instance details> -- 找到了一個適合的slave來擔當新master failover-state-send-slaveof-noone <instance details> -- 當把選擇爲新master的slave的身份進行切換的時候。 failover-end-for-timeout <instance details> -- failover因爲超時而失敗時。 failover-end <instance details> -- failover成功完成時。 switch-master <master name> <oldip> <oldport> <newip> <newport> -- 當master的地址發生變化時。一般這是客戶端最感興趣的消息了。 +tilt -- 進入Tilt模式。 -tilt -- 退出Tilt模式。
redis sentinel很是依賴系統時間,例如它會使用系統時間來判斷一個PING回覆用了多久的時間。
然而,假如系統時間被修改了,或者是系統十分繁忙,或者是進程堵塞了,sentinel可能會出現運行不正常的狀況。
當系統的穩定性降低時,TILT模式是sentinel能夠進入的一種的保護模式。當進入TILT模式時,sentinel會繼續監控工做,可是它不會有任何其餘動做,它也不會去迴應is-master-down-by-addr
這樣的命令了,由於它在TILT模式下,檢測失效節點的能力已經變得讓人不可信任了。
若是系統恢復正常,持續30秒鐘,sentinel就會退出TITL模式。
注意:該功能還未實現。
當一個腳本的運行時間超過配置的運行時間時,sentinel會返回一個-BUSY 錯誤信號。若是這件事發生在觸發一個failover以前,sentinel將會發送一個SCRIPT KILL命令,若是script是隻讀的話,就能成功執行。
既然你知道了sentinel的基本信息,你能夠很想知道應該將Sentinel放置在哪裏,須要多少Sentinel進程等等。這個章節展現了幾個部署示例。
咱們爲了圖像化展現配置示例使用字符藝術,這是不一樣符號的意思:
+--------------------+ | This is a computer | | or VM that fails | | independently. We | | call it a "box" | +--------------------+
咱們寫在盒子裏表示他們正在運行什麼:
+-------------------+ | Redis master M1 | | Redis Sentinel S1 | +-------------------+
不一樣的盒子之間經過線條鏈接,表示他們能夠相互通訊:
+-------------+ +-------------+ | Sentinel S1 |---------------| Sentinel S2 | +-------------+ +-------------+
使用斜槓展現網絡斷開:
+-------------+ +-------------+ | Sentinel S1 |------ // ------| Sentinel S2 | +-------------+ +-------------+
還要注意:
Master 被叫作 M1,M2,M3 ... Mn。
Slave 被叫作 R1,R2,R3 ... Rn(replica的首字母)
Sentinels 被叫作 S1,S2,S3 ... Sn
Clients 被叫作 C1,C2,C3 ... Cn
當一個實例由於Sentinel的行爲改變了角色,咱們把它放在方括號裏,因此[M1]表示由於Sentinel的介入,M1如今是一個master。
注意永遠不會顯示的設置只是使用了兩個哨兵,由於爲了啓動故障轉移,Sentinel老是須要和其餘大多數的Sentinel通訊。
+----+ +----+ | M1 |---------| R1 | | S1 | | S2 | +----+ +----+ Configuration: quorum = 1
在這個設置中,若是master M1故障,R1將被晉升由於兩個Sentinel能夠達成協議而且還能夠受權一個故障轉移由於多數就是兩個。因此他表面上看起來是能夠工做的,然而檢查下一個點了解爲何這個設置是不行的。
若是運行M1的盒子中止工做了,S1也中止工做。運行在其餘盒子上的S2將不能受權故障轉移,因此係統將變成不可用。
注意爲了排列不一樣的故障轉移須要少數服從多數,而且稍後向全部的Sentinel傳播最新的配置。還要注意上面配置的故障轉移的能力,沒有任何協定,很是危險:
+----+ +------+ | M1 |----//-----| [M1] | | S1 | | S2 | +----+ +------+
在上面的配置中咱們使用完美的對稱方式建立了兩個master(假定S2能夠在未受權的狀況下進行故障轉移)。客戶端可能會不肯定往哪邊寫,而且沒有途徑知道何時分區配置是正確的,爲了預防一個永久的斷裂狀態。
全部請永遠部署至少三個Sentinel在三個不一樣的盒子裏。
這是個很是簡單的設置,它有簡單調整安全的優點。它基於三個盒子,每一個盒子同時運行一個Redis實例和一個Sentinel實例。
+----+ | M1 | | S1 | +----+ | +----+ | +----+ | R2 |----+----| R3 | | S2 | | S3 | +----+ +----+ Configuration: quorum = 2
若是M1故障,S2和S3將會商定故障並受權故障轉移,使客戶端能夠繼續。
在每一個Sentinel設置裏,Redis是異步主從複製,總會有丟失數據的風險,由於有可能當它成爲master的時候,一個確認的寫入操做尚未同步到slave。而後在上面的設置中有一個更高的風險因爲客戶端分區一直是老的master,就像下面的圖像所示:
+----+ | M1 | | S1 | [- C1 (writes will be lost) +----+ | / / +------+ | +----+ | [M2] |----+----| R3 | | S2 | | S3 | +------+ +----+
在這個案例中網絡分區隔離老的master M1,因此slave R2晉升爲master。然而客戶端,好比C1,還在原來的老的master的分區,可能繼續往老master寫數據。這個數據將會永久丟失,由於分區恢復時,master將會從新配置爲新master的slave,丟棄它的數據集。
這個問題可使用下面的Redis主從複製特性減輕,它可在master檢查到它再也不能傳輸它的寫入操做到指定數量的slave的時候中止接收寫入操做。
min-slaves-to-write 1
min-slaves-max-lag 10
使用上面的配置(請查看自帶的redis.conf示例瞭解更多信息)一個Redis實例,看成爲一個master,若是它不能寫入至少1個slave將中止接收寫入操做。(N個Slave以上不通就中止接收)
因爲主從複製是異步的不能真實的寫入,意味着slave斷開鏈接,或者再也不向咱們發送異步確認的指定的max-lag秒數。(斷定鏈接不通的超時時間)
在上面的示例中使用這個配置,老master M1將會在10秒鐘後變爲不可用。當分區恢復時,Sentinel配置將指向新的一個,客戶端C1將可以獲取到有效的配置而且將使用新master繼續工做。
然而天下沒有免費的午飯,這種改進,若是兩個slave掛掉,master將會中止接收寫入操做。這是個權衡。
有時咱們只有兩個Redis盒子可用,一個master和一個slave。在例二中的配置在那樣的狀況下是不可行的,所謂咱們能夠藉助下面的,Sentinel放置在客戶端:
+----+ +----+ | M1 |----+----| R1 | | S1 | | | S2 | +----+ | +----+ | +------------+------------+ | | | | | | +----+ +----+ +----+ | C1 | | C2 | | C3 | | S1 | | S2 | | S3 | +----+ +----+ +----+ Configuration: quorum = 2
在這個設置裏,Sentinel的視角和客戶端的視角相同:若是大多數的客戶端認爲master是能夠到達的,它就是好的。C1,C2,C3是通常的客戶端,這不意味着C1識別單獨的客戶端鏈接到Redis。它更像一些如應用服務,Rails應用之類的。
若是運行M1和S1的盒子故障,故障轉移將會發生,然而很容看到不一樣的網絡分區將致使不一樣的行爲。例如若是客戶端和Redis服務之間的斷開鏈接,Sentinel將不能設置,由於master和slave將都不可用。
注意若是使用M1獲取分區,咱們有一個和例二中描述的類似的問題,不一樣的是這裏咱們沒有辦法打破對稱,因爲只有一個slave和master,因此當它的master斷開鏈接時master不能中止接收查詢,不然在slave故障期間master將永不可用。
因此這是個有效的設置可是在例二中的設置有像更容易管理HA系統的優勢, 並有能力限制master接收寫入的時間。
在例3中若是客戶端少於3個就不能使用。在這個案例中咱們使用一個混合的設置:
+----+ +----+ | M1 |----+----| R1 | | S1 | | | S2 | +----+ | +----+ | +------+-----+ | | | | +----+ +----+ | C1 | | C2 | | S3 | | S4 | +----+ +----+ Configuration: quorum = 3
這裏和例3很是相似,可是這裏咱們在4個盒子裏運行四個哨兵。若是M1故障其餘的三個哨兵能夠執行故障轉移。
本文參考文檔:
https://redis.io/topics/sentinel
http://redis.majunwei.com/topics/sentinel.html
http://www.javashuo.com/article/p-vguqgocn-gw.html
http://www.javashuo.com/article/p-obsenvtg-go.html
接下來是你們最喜歡的總結內容啦,內容有二,以下:
一、但願能關注我其餘的文章。
二、博客裏面有沒有很清楚的說明白,或者你有更好的方式,那麼歡迎加入左上方的2個交流羣,咱們一塊兒學習探討。