Redis筆記 - 07

哨兵(Sentinel)機制

如果主服務器掛了,由於我們的寫請求由主服務器處理,只有一臺主服務器,那就無法處理寫請求了嘛?

Redis提供了哨兵(Sentinel)機制供我們解決上面的情況。如果主服務器掛了,我們可以將從服務器升級爲主服務器,等到舊的主服務器(掛掉的那個)重連上來,會將它(掛掉的主服務器)變成從服務器。這個過程叫做主備切換(故障轉移)

在正常的情況下,主從加哨兵(Sentinel)機制是這樣子的:

主服務器掛了,主從複製操作就中止了,並且哨兵系統是可以察覺出主服務掛了。

Redis提供哨兵機制可以將選舉一臺從服務器變成主服務器

然後舊的主服務器如果重連了,會變成從服務器:

 Sentinel可以讓我們的Redis實現高可用,Sentinel作爲這麼一個組件,自身也必然是高可用的(不可能是單點的)

啓動和初始化Sentinel

首先我們要知道的是:Sentinel本質上只是一個運行在特殊模式下的Redis服務器。因爲Sentinel做的事情和Redis服務器是不一樣的,所以它們的初始化是有所區別的(比如,Sentinel在初始化的時候並不會載入AOF/RDB文件,因爲Sentinel根本就不用數據庫)。然後,在啓動的時候會將普通Redis服務器的代碼替換成Sentinel專用代碼。(所以Sentinel雖然作爲Redis服務器,但是它不能執行SET、DBSIZE等等命令,因爲命令表的代碼被替換了)。接着,初始化Sentinel的狀態,並根據給定的配置文件初始化Sentinel監視的主服務器列表。

最後,Sentinel會創建兩個連向主服務器的網絡連接:

  • 命令連接(發送和接收命令)
  • 訂閱連接(訂閱主服務器的sentinel:hello頻道)

獲取和更新信息

Sentinel通過主服務器發送INFO命令來獲得主服務器屬下所有從服務器的地址信息,併爲這些從服務器創建相應的實例結構。

當發現有新的從服務器出現時,除了創建對應的從服務器實例結構,Sentinel還會創建命令連接和訂閱連接。

在Sentinel運行的過程中,通過命令連接會以每兩秒一次的頻率向監視的主從服務器的_sentinel_:hello頻道發送命令(主要發送Sentinel本身的信息,監聽主從服務器的信息),並通過訂閱連接接收_sentinel_:hello頻道的信息。

這樣一來一回,我們就可以更新每個Sentinel實例結構的信息。

判斷主服務器是否下線了

判斷主服務器是否下線有兩種情況:

主觀下線

  • Sentinel會以每秒一次的頻率向與它創建命令連接的實例(包括主從服務器和其他的Sentinel)發送PING命令,通過PING命令返回的信息判斷實例是否在線
  • 如果一個主服務器在down-after-milliseconds毫秒內連續向Sentinel發送無效回覆,那麼當前Sentinel就會主觀認爲該主服務器已經下線了。

客觀下線

  • 當Sentinel將一個主服務器判斷爲主觀下線以後,爲了確認該主服務器是否真的下線,它會向同樣監視該主服務器的Sentinel詢問,看它們是否也認爲該主服務器是否下線。
  • 如果足夠多的Sentinel認爲該主服務器是下線的,那麼就判定該主服務爲客觀下線,並對主服務器執行故障轉移操作。

在多少毫秒內無效回覆才認定主服務器是主觀下線的,以及多少個Sentinel認爲主服務器是下線的,才認定爲客觀下線。這都是可以配置的

選舉領頭Sentinel和故障轉移

當一個主服務器認爲爲客觀下線以後,監視這個下線的主服務器的各種Sentinel會進行協商,選舉出一個領頭的Sentinel,領頭的Sentinel會對下線的主服務器執行故障轉移操作。

選舉領頭Sentinel的規則也比較多,總的來說就是先到先得(哪個快,就選哪個)

選舉出領頭的Sentinel之後,領頭的Sentinel會對已下線的主服務器執行故障轉移操作,包括三個步驟:

  • 在已下線主服務器屬下的從服務器中,挑選一個轉換爲主服務器
  • 讓已下線主服務器屬下的所有從服務器改爲複製新的主服務器
  • 已下線的主服務器重新連接時,讓他成爲新的主服務器的從服務器

挑選某一個從服務器作爲主服務器也是有策略的,大概如下:

  • 跟master斷開連接的時長
  • slave優先級
  • 複製offset
  • run id

 

目前爲止的主從+哨兵架構可以說Redis是高可用的,但要清楚的是:Redis還是會丟失數據的

丟失數據有兩種情況:

1)、異步複製導致的數據丟失

  • 有部分數據還沒複製到從服務器,主服務器就宕機了,此時這些部分數據就丟失了

2)、腦裂導致的數據丟失

  • 有時候主服務器脫離了正常網絡,跟其他從服務器不能連接。此時哨兵可能就會認爲主服務器下線了(然後開啓選舉,將某個從服務器切換成了主服務器),但是實際上主服務器還運行着。這個時候,集羣裏就會有兩個服務器(也就是所謂的腦裂)。
  • 雖然某個從服務器被切換成了主服務器,但是可能客戶端還沒來得及切換到新的主服務器,客戶端還繼續寫向舊主服務器寫數據。舊的服務器重新連接時,會作爲從服務器複製新的主服務器(這意味着舊數據丟失)。

可以通過以下兩個配置儘量減少數據丟失的可能:

min-slaves-to-write 1
min-slaves-max-lag 10

 

  • 事前:Redis 高可用,主從+哨兵,Redis cluster,避免全盤崩潰。
  • 事中:本地 ehcache 緩存 + Hystrix 限流+降級,避免MySQL被打死。
  • 事後:Redis 持久化 RDB+AOF,一旦重啓,自動從磁盤上加載數據,快速恢復緩存數據。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章