Redis哨兵原理詳解


一、概述

Redis哨兵(以下稱哨兵)是爲Redis提供一個高可靠解決方案,對一定程序上的錯誤,可以不需要人工干預自行解決。

哨兵功能還有監視、事件通知、配置功能。以下是哨兵的功能列表:

監控:不間斷的檢查主從服務是否如預期一樣正常工作

事件通知:對被監視的redis實例的異常,能通知系統管理員,或者以API接口通知其他應用程序。

智能援救:當被監視的主服務異常時,哨兵會智能的把某個從服務提升爲主服務,同時其他從服務與新的主服務之間的關係將得到重新的配置。應用程序將通過redis服務端重新得到新的主服務的地址並重新建立連接。

配置服務:客戶端可連接哨兵的接口,獲得主從服務的相關信息,如果發生改變,哨兵新通知客戶端。

 

哨兵的分佈式

哨兵是個分佈式系統,通過配置文件可以多個哨兵合作,以實現它的健壯性:

1.某個主服務是否正常,需要通過多個哨兵確認,這樣可保證誤判的低概率。

2.當哨兵工作的時候,總會有個別哨兵不能正常運行,如個別系統出現故障,所以多個哨兵合作運行,保證了系統的健壯性。

所有的哨兵、redis實例(包括主與從)和客戶端相互之間會有交互,這是一個大的分佈式系統,在此文檔中將由淺入深地介紹哨兵的基礎概念,以便更好的理解其基本屬性,然後是更復雜的特性,讓你理解它是如果精確的工作。

 

二、開始

1.獲得哨兵

哨兵當前爲Sentinel 2,它是在原來版本的基礎上用了更健壯更簡單的預演算法(後文有詳解)。

哨兵的穩定版本與redis2.8與redis3.0一起發佈,新特性的研發在不穩定版本分支時,當它被確認穩定後,將會被追加到redis2.8與redis3.0版本中。

與redis2.6一起發行的Sentinel 2版本,已淘汰不可用。

2.運行哨兵

如果有哨兵的可執行文件(或者與redis server執行文件有個符號連接(自己查閱Linux連接文件知識)),可通過如下的命令行啓動哨兵:

redis-sentinel /path/to/sentinel.conf

不然,就得通過redis server執行文件的哨兵模式直接用以下命令啓動:

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

以上兩個方式的效果是一樣的。

但是當哨兵正運行時,必須使用配置文件,它可以記載哨兵運行狀態,當哨兵重啓時可重用(重新載入配置文件)。如果沒指定配置文件,或者路徑不可寫(因爲需要往配置文件更新運行時狀態)那哨兵將不能正常啓動的。

哨兵的默認開啓的TCP服務端口是26379,所以需要把此端口的防火牆、端口映射之類的工作做好,以便其他哨兵能與其交互、協商相關的工作,不然對redis的援救之類的工作就無法運行了。

3.佈置前你必須知道的

1.你最少需要三個哨兵實例,以提高健壯性。

2.三個實例可以佈置在不同計算機或者虛擬機中,然而需要確保他們出問題的話,互不影響,如它們運行在相互不影響的不同的物理機或者虛擬機中。

3.哨兵+redis分佈系統並不能保證100%的異常通信的寫安全,當故障發生時。但是可能有其他方式來調節“窗口”(自行查閱TCP/IP通信相關資料)來保證數據丟失控制在一定範圍內,如果沒有其他更好的解決方案的話。

4.你需要讓你的客戶端支持哨兵,設計好的客戶端都支持哨兵。

5.在開發環境中,如果沒有HA設置(對佈置的系統反覆測試),它也算安全的,但是在生產環境,那可能會導致一些未知錯誤,當你發現的時候可能已經晚了。歪國人真是廢話多,就是一句話,告訴你在生產環境中,最好要反覆測試。

6.對於哨兵、Docker或者其他尋址、端口映射工具要合理應用:Docker是端口從映射,偵測其他哨兵的存在與主服務的從服務列表,關於哨兵與Docker的詳細信息參見後文相關章節。

 

4.配置哨兵

與redis一起發佈的源文件中,有一個“sentinel.conf”自說明的配置文件模板,它是很好的官方配置說明,以下是最簡單的配置項:

sentinel monitor mymaster 127.0.0.1 6379 2

sentinel down-after-milliseconds mymaster60000

sentinel failover-timeout mymaster 180000

sentinel parallel-syncs mymaster 1

sentinel monitor resque 192.168.1.3 6380 4

sentinel down-after-milliseconds resque10000

sentinel failover-timeout resque 180000

sentinel parallel-syncs resque 5

只要設定待監控的主服務,並給它取一個唯一的名稱,從服務會被自動檢查到,不需要手動指定。哨兵將更新配置文件,當以下幾種情況發生時,1.新的從服務被偵測到,2.當異常發生,有從服務被提升爲主服務時,3.新的哨兵被偵測到時。

在以上示例中,有兩個redis實例被監控,一個主服務與一個未命名的從服務,分別叫mymaster和resque:

sentinel monitor <master-group-name> <ip> <port> <quorum>

sentienl monitor是告訴哨兵監控一個叫做mymaster的實例,它的地址與端口分別是127.0.0.1和6379,然後quorum是什麼意思呢?

c它是一個權重,如果爲2,也就是說最少有2個哨兵認爲此主服務down了,授權給它發起援救程序。

c事實上quorum只是用於檢測故障,而實行救援,將選舉出某個哨兵,並被授權負責救援工作才能實行,而只有在多數哨兵在崗的情況下才能實行選舉並實行這項任務。

例如有5個在崗哨兵,主服務的quorum被設置爲2,那將發生什麼情況:

c如果有兩個哨兵認爲主服務down了,那它們兩中的一個負責與救援工作。

c這裏最少有三個哨兵在崗,並想到能交互,救援工作才能被授權,真實的救援工作才能開始。

事實上,如果多數(這裏多數少數的概念應該是對半分,超過50%爲多數)的哨兵不在崗,不能相互交互,那救援工作是不可能實行的。

 

其他項的說明:

其他項的格式都是一樣的,如下:

sentinel <option_name> <master_name> <option_value>

cdown-after-milliseconds是哨兵在多少毫秒內無法聯繫上的話,這個實例將被認爲已經down了,它是個時限。

cparallel-syncs從服務通過地救援成爲新的主服務後,與新主服務進行再同步的從服務個數,此值越小,救援花費的時間越長(這個並沒有理解),但是越大就意味着越多的從服務因爲與主服務同步而不可用。所以把此值設置爲1,來保證每次只有一個從服務因爲同步而不可用。

其他項的介紹請參看後文,同時在與redis共同發佈的setinel.conf文件裏也有自說明。

所有的參數項都可能通過SENTINEL SET命令來修改,關於此指令的說明請參看後後續章節的“運行時哨兵重配置”。

三、配置樣例

1.概述

經過前章節的介紹,現在知道了關於哨兵的一些基本知識,現在也許你想知道我們應該把哨兵佈置在哪裏?需要多少哨兵實例?現在我們以簡單的圖例來說明如何佈置等問題:


一個這樣的框,我們叫它爲一個“盒子”,它可以是一個物理機或虛擬機,如果有失敗、故障它將是獨立的,不影響其他“盒子”。


如圖,M1表示主服務1,而S1表示哨兵1。


不同的盒子之間用線相連,表示他們之間是可以交互的。


網絡隔離不可相互交流的話,連線之間加雙斜線,表示隔離的。

總結如下:

c M1, M2, M3, ..., Mn代表主服務。

c R1, R2, R3, ..., Rn(R可以理解成Replica(複製))代表從服務。

c S1, S2, S3, ..., Sn代表哨兵。

c C1, C2, C3, ..., Cn代表客戶端。

c如果有的角色由於哨兵的調度轉變了,那用方括號把它括起來,如[M1]表示它現在是個主服務。

2.樣例1:兩個哨兵


只有兩個哨兵的情況,是無法正常開展救援工作的,因爲無法通過以獲得多數票來得到授權。

c如果M1主服務Down了的話,那R1將被提升爲主服務,在兩個哨兵能達成救援決議,因爲出席數(quorum)爲1,所以能發起救援程序,因爲獲得兩個哨兵的支持,爲多數方。所以很明顯它是能正常工作的。爲什麼又不能正常工作呢,請看下一種情況。

c如果M1所在的“盒子”停止了工作,那S1當然也是DOWN了,只剩下S2是無法拿到救援授權的,這樣的話整個系統就DOWN了。

所以最少三個哨兵佈置到三個不同的獨立環境中是非常必要的。

3.樣例2:標配(三個獨立環境)

最基本的配置,三個哨兵在三個不同的獨立環境中,每個環境跑一個redis實例與一個哨兵。如下圖:


如果M1主服務DOWN了的話,S2與S3能達成協議發起救援程序。然後,redis一般都設置爲異步通信的,所以必然會有一些數據還沒來得及同步到自己的從服務時,主服務Down了,而這裏從服務提升爲主服務,這個時候那必然會丟失一些數據,但是這裏有更可怕的風險,因爲客戶端與舊的主服務一起被隔離於其他實例。如下圖:


當M1所在的“盒子”與其他“盒子”失去聯繫,那S2與S3將達成救援協議,把R2提升爲主服務,但是可怕的是,因爲客戶端原先就與M1在同一邊的,可能C1與M1之間通信還是正常的,C1還不停的往M1注入數據呢,等到M1與其他redis實例之間的通信恢復後,哨兵會把M1降爲M2的從服務,M2纔是新的主服務,這個時候,M1(已經是S1)將以M2爲主服務,並以M2數據爲準進行同步,可悲的事情發生了,C1在M1與其他redis斷網期間寫入的數據,將徹底的丟失了。

這個問題可以通過以下的redis主從複製的特性得到解決,即當主服務無法將數據同步到自己的指定數量的從服務的時候,那就停止接收數據的寫入。

min-slaves-to-write 1

min-slaves-max-lag 10

以上配置效果是,當M1不能把自己的內容同步給最少一個從服務(S2、S3都寫入不了了),其實這種情況下,從服務也與主服務失去了連接,那主服務將拒絕客戶端的寫入。或者沒有收到任何一個從服務的回饋超過10秒鐘,也會導致一樣的效果。通過此配置,M1在10秒鐘之後將拒絕寫入,當M1的局部網絡恢復後,哨兵將重新配置他們的角色,C1也會重新找到誰是新的主服務,當然10秒鐘的數據丟失那也是難免的了。

然而,天下並沒有免費的午餐,如果兩個從服務同時down了的話,那主服務將拒絕寫入操作,這猶如該死的政治妥協,讓人不爽。

4.樣例3:哨兵在客戶端環境中

有的時候,我們只有兩個獨立的環境,一個佈置主服務,一個佈置從服務。那將發生樣例2中的情況了,我們這個時候可以把哨兵轉到客戶端環境中。


 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章