Redis Sentinel

1.概述

Sentinel(哨崗迅栅、哨兵)是Redis高可用性的解決方案:由一個或多個Sentinel實例組成的Sentinel系統(tǒng)可以監(jiān)視任意多個主服務器暂吉,以及這個主服務器下的從服務器,并在被監(jiān)視主服務器下線時江锨,自動將下線主服務器下的某個從服務器升級為新的主服務器巫财,然后由新的主服務器代替已下線的主服務器繼續(xù)處理命令請求净赴。


Sentinel系統(tǒng)

當主服務器下線時,Sentinel會采取如下操作:


主服務器下線

Sentinel會選出一個從服務器作為新的主服務器驮捍,假設此時選出的從服務器為:從服務器2疟呐,此時系統(tǒng)會如下圖所示:
新主服務器上線

當已下線的主服務器重新上線后,變?yōu)槿缦滤荆?/p>

下線的主服務器重新上線

2.啟動并初始化Sentinel

啟動Sentinel可以使用命令:

redis-sentinel /path/to/your/sentinel.conf
#或者命令
redis-server /path/to/your/sentinel.conf --sentinel

這兩個命令的效果完全一樣东且。
一個Sentinel實例啟動時启具,它需要執(zhí)行以下步驟:

  1. 初始化服務器
  2. 將普通Redis服務器使用的代扣替換為Sentinel專用代碼
  3. 初始化Sentinel 狀態(tài)
  4. 根據(jù)給定的配置文件,初始化Sentinel的監(jiān)視主服務器列表
  5. 創(chuàng)建連向主服務器的網(wǎng)絡連接

2.1 初始化服務器

Sentinel本質上是一個運行在特殊模式下的Redis服務器珊泳,Sentinel的啟動第一步就是啟動一個普通的Redis服務器鲁冯。但是Sentinel和普通Redis服務器執(zhí)行的工作不一樣囤踩,所以Sentinel的初始化過程和普通Redis服務器并不完全相同。
Sentinel在初始化時晓褪,不需要載入RDB文件或者AOF文件堵漱。
并且Sentinel向外提供的命令和普通Redis服務器也不是完全一樣的,像SET這一類命令Sentinel是沒有的涣仿。

2.2 使用Sentinel專用代碼

  • 使用與普通Redis服務器不同的默認端口號
  • 載入Sentinel需要使用的命令列表

Sentinle支持:PING勤庐、SENTINEL、INFO好港、SUBSCRIBE愉镰、UNSUBSCRIBE、PSUBSCRIBE和PUNSUBSCRIBE這七個命令

2.3 初始化Sentinel狀態(tài)

在應用了Sentinel的專用代碼之后钧汹,接下來服務器會初始化一個snetinel.c/sentinelState的結構丈探,這個結構中保存了服務器中所有和Sentinel功能相關的狀態(tài)。
比較重要的一個屬性:

#保存了所有這個Sentinle監(jiān)視的主服務器
#字典的鍵是主服務器的名字
#字典的值則是一個指向sentinelRedisInstance結構的指針
dict *masters;

2.4 初始化Sentinel狀態(tài)的masters屬性

對Sentinel狀態(tài)的初始化會引起對于masters字典的初始化拔莱,即初始化Sentinel監(jiān)控的所有主服務器碗降,它是根據(jù)Sentinel的配置文件來進行初始化的。
配置文件示例如下:

# master1 configure
sentinel monitor master1 127.0.0.1 6379 2
sentinel down-after-milliseconds master1 30000
sentinel parallel-syncs master1 1
sentinel failover-timeout master1 900000

# master2 configure
sentinel monitor master2 127.0.0.1 6379 2
sentinel down-after-milliseconds master2 30000
sentinel parallel-syncs master2 1
sentinel failover-timeout master2 900000

此時Sentinel將主服務器master1會創(chuàng)建為如下結構:


master1結構

此時Sentinel狀態(tài)的結構如下所示:


Sentinel狀態(tài)的結構

2.5 創(chuàng)建連向主服務器的連接

初始化Sentinel的最后一步是創(chuàng)建連向主服務器的網(wǎng)絡連接塘秦。Sentinel將成為主服務器的客戶端讼渊,它可以向主服務器發(fā)送命令,并從命令回復中獲取相關信息尊剔。
Sentinel對每個被監(jiān)視的主服務器會創(chuàng)建兩個異步網(wǎng)絡連接:

  • 命令連接爪幻,這個連接專門用于向主服務器發(fā)送命令,并接收命令回復
  • 訂閱連接须误,這個連接專門用于訂閱主服務器的sentinel:hello 頻道

為什么使用兩個連接挨稿?
Redis在使用訂閱功能時,如果在發(fā)送消息時京痢,想要接收信息的客戶端不在線或者斷線奶甘,那么這個客戶端就會丟失這條消息,因此為了不丟失sentinel:hello 頻道的任何信息历造,sentinel必須開通一條專門的連接來接收該頻道的消息甩十。但是由于Snetinel還必須向主服務器發(fā)送命令來獲取主服務器的相關信息,因此必須再開通一條命令連接吭产。
因為Sentinel需要與多個實例創(chuàng)建多個網(wǎng)絡連接侣监,所有Sentinel使用的異步連接

如下圖展示了一個Snetinel與兩個master建立連接的情況:


Snetinel與兩個master建立連接

3.獲取主服務器信息

Sentinel會以每10秒一次的頻率,通過命令連接向被監(jiān)視的主服務器發(fā)送INFO命令臣淤,并通過分析INFO的回復來獲取主服務器當前的狀態(tài)橄霉。
通過分析INFO的回復,Sentinel可以獲取以下兩個方面的信息:

  • 主服務器本身的信息邑蒋,包括run_id域記錄的服務器運行ID姓蜂,以及role域記錄的服務器角色
  • 主服務器下從服務器的信息按厘,每個從服務器都由一個slave字符串開頭的行記錄,每行的ip記錄了從服務器的IP地址钱慢,port記錄了從服務器的端口號逮京,根據(jù)ipport的信息Sentinel無需用戶來配置從服務器信息,即可自動發(fā)現(xiàn)從服務器束莫。

根據(jù)run_id和role記錄的信息懒棉,Sentinel對主服務器的實例進行更新。
從服務器的信息會更新至主服務器實例結構中的slaves字典中览绿,這個字典記錄了主服務器下從服務器的名單:

  • 字典的鍵是由Sentinel自動設置的從服務器的名字策严,格式為:ip:port
  • 字典的值則是對應從服務器的實例結構。

具體結構如下圖所示:


Sentinel主服務器實例中帶有從服務器信息

注意:從服務器的flags值為SRI_SLAVE

4.獲取從服務器信息

當Sentinel發(fā)現(xiàn)主服務器有新的從服務器出現(xiàn)時饿敲,Sentinel除了會為這個新的從服務器創(chuàng)建相應的實體結構之外妻导,Sentinel還會創(chuàng)建連接到從服務器的命令連接和訂閱連接。
在創(chuàng)建命令連接后怀各,會以每10秒一次的頻率發(fā)送INFO命令倔韭,并解析返回的信息。提取出如下信息對從服務器實例進行更新:

  • 從服務器運行run_id
  • 從服務器角色role
  • 主服務器的ip地址和端口號
  • 主服務器的連接狀態(tài):master_link_status
  • 從服務器器優(yōu)先級:slave_priority
  • 從服務器的復制偏移量:slave_repl_offset

更新后從服務器結構如下所示:


從服務器結構

5.向主服務器和從服務器發(fā)送消息

默認情況下Sentinel會以兩秒每次的頻率渠啤,通過命令連接向所有被監(jiān)視的主服務器和從服務器發(fā)送如下格式的命令:

#s開頭的參數(shù)是Sentinel的信息
#m開頭的信息是主服務器的信息:如果Sentinel正在監(jiān)視的為主服務器那么就是主服務器自身的信息狐肢;
#如果Sentinel監(jiān)視的是從服務器那么就是從服務器復制的主服務器的信息
PUBLISH __sentinel__:hello "<s_ip>,<s_port>,<s_runid>,<s_epoch>,<m_name>,<m_ip>,<m_port>,<m_epoch>"

具體參數(shù):

參數(shù) 含義
s_ip Sentinel的ip
s_port Sentinel的port
s_runid Sentinel的runid
s_epoch Sentinel當前的配置紀元(在選舉領頭Sentinel時使用)
m_name 主服務器的名字
m_ip 主服務器的ip
m_port 主服務器的port
m_epoch 主服務器的配置紀元

6.接收來自主服務器和從服務器的頻道信息

Sentinel當與一個主服務器或從服務器建立器訂閱連接之后添吗,Sentinel就會通過訂閱連接向服務器發(fā)送以下命令來進行訂閱消息:

SUBSCRIBE __sentinel__:hello

Senetinel會一直對sentinel:hello繼續(xù)訂閱直到Sentinel與服務器斷開連接為止沥曹。也就是說Sentinel既會通過命令連接向服務器發(fā)送sentinel:hello消息又會通過訂閱連接從服務器接收消息。
對于監(jiān)視同一個服務器的多個Sentinel來說碟联,一個Sentinel發(fā)送的消息會被其他Sentinel接收到妓美,這些信息會被用于更新其他Sentinel對于發(fā)送消息的Sentnel的認知,也會被用于更新其他Sentinel對于被監(jiān)視服務的認知鲤孵。
當一個Sentinel從sentinel:hello收到一條信息時壶栋,Sentinel會對這條信息進行分析,提取出信息中的<s_ip>,<s_port>,<s_runid>等上面提到的8個參數(shù):

  • 如果記錄的<s_ip>與當前Sentinel一致普监,那么說明是自身發(fā)送的消息爷耀, 那么會丟棄這條消息
  • 如果不一致盛撑,那么說明還有另外一個Sentinel在監(jiān)視同一個服務器,接收消息的Sentinel會對器監(jiān)視的主服務器實例結構中的sentinels字典進行更新

6.1 更新sentinels字典

  • sentinels字典中鍵為Sentinel的名字,格式:ip:port
  • sentinels字典中值為對應的Sentinel的實例結構

具體如下圖所示:


sentinels結構

6.2 創(chuàng)建連接其他Sentinel的命令連接

Sentinel與Sentinel之間只會創(chuàng)建命令連接窄做,不會創(chuàng)建訂閱連接,因為Sentinel需要通過接收主服務器和從服務器的訂閱信息來發(fā)現(xiàn)未知的Sentinel枣购,對于相互已知的Sentinel不需要再建立訂閱連接來進行通信剥汤。

7.檢測主觀下線狀態(tài)

默認情況下Sentinel會向其監(jiān)控的服務器(主服務器、從服務器允睹、Sentinel)以每秒一次的頻率發(fā)送PING命令运准,并通過PING命令的回復來判斷具體實例的在線狀態(tài)幌氮。實例回復可以分為以下兩種情況:

  • 有效回復:+PONG、-LOADING胁澳、-MASTERDOWN三種回復中的其中一種
  • 無效回復:+PONG该互、-LOADING、-MASTERDOWN三種回復之外的回復韭畸,或者在指定時間內(nèi)沒有回復

Sentinel的配置文件中的down-after-milliseconds指定了Sentinel判斷實例進入主觀下線的時間長度:如果一個實例在down-after-milliseconds毫秒內(nèi)連續(xù)向Sentinel返回無效回復慢洋,那么Sentinel會修改這個實例對應的實例結構,在flags屬性中打開SRI_S_DOWN標識陆盘,以此來表示實例進入主觀下線狀態(tài)普筹。
具體如下:

主觀下線

Sentinel的配置文件中的down-after-milliseconds不但用來判斷主服務器的主觀下線時間,還用于此主服務器下所有的從服務器的主觀下線狀態(tài)的判斷隘马。
每個Senttinel配置文件中down-after-milliseconds的配置不一定會一樣太防,因此對于同一個服務器而言,一個Sentinel認為其下線但是另外一個Sentinel可能沒有認為其主觀下線酸员。

8.檢測客觀下線狀態(tài)

當Sentinel將一個主服務器檢測為主觀下線后蜒车,為確認這個主服務器是否真的下線,它會向同時在監(jiān)控這臺主服務器的其他Sentinel進行詢問幔嗦,看他們是否也認為服務器進入下線狀態(tài)(可以是主觀下線或客觀下線)酿愧,如果Sentinel從其他Sentinel哪里接收到足夠的數(shù)量的已下線判斷后,Sentinel就會將主服務器判定為客觀下線邀泉,對其執(zhí)行故障轉移
檢測客觀下線主要分以下三步:

8.1 發(fā)送SENTINEL is-master-down-by-addr命令

命令格式:

SENTINEL is-master-down-by-addr <ip> <port> <current_epoch> <runid>

具體參數(shù)含義:

參數(shù) 含義
ip 被Sentinel判斷為主觀下線的主服務器ip地址
port 被Sentinel判斷為主觀下線的主服務器port地址
current_epoch Sentinel當前配置紀元嬉挡,用于選舉領頭Sentinel
runid 可以為或Sentinel的運行ID;當為時汇恤,代表命令僅用于檢測主服務器客觀下線狀態(tài)庞钢;當為Sentinel的運行ID時,則用于選舉領頭Sentinel

82. 接收SENTINEL is-master-down-by-addr命令

當一個Sentinel接收到另一個Sentinel發(fā)送的SENTINEL is-master-down-by-addr時因谎,會檢測當前監(jiān)控的主服務的主觀下線狀態(tài)基括,并做出如下格式的回復:

  1. <down_state>
  2. <leader_runid>
  3. <leader_epoch>

具體參數(shù)含義:

參數(shù) 含義
down_state 目標Sentinel主服務器主觀下線狀態(tài):1代表主服務已下線,0代表主服務器未下線
leader_runid 可以為或目標Sentinel的局部領頭Sentinel的運行ID财岔;當為時风皿,代表命令僅用于檢測主服務器客觀下線狀態(tài);當為目標Sentinel的局部領頭Sentinel的運行ID時匠璧,則用于選舉領頭Sentinel
leader_epoch 目標Sentinel局部領頭Sentinel的配置紀元桐款,僅在leader_runid部位時有效,如果leader_runid為患朱,則leader_epoch總是為0

8.3 接收SENTINEL is-master-down-by-addr命令回復

根據(jù)其他Sentinel返回的回復鲁僚,Sentinel將統(tǒng)計其他Sentinel同意主服務器已下線的數(shù)量,這一數(shù)量達到配置指定的判斷客觀下線所需的數(shù)量時,Sentinel會將主服務器實例結構中的flags屬性的SRI_O_DOWN打開冰沙,表示主服務器已進入客觀下線狀態(tài)侨艾。具體如下圖所示:

客觀下線

配置文件中對于客觀下線的配置:

#此表示表示總共需要兩個Sentinel認為主服務器已進入主觀下線狀態(tài),那么就可以判斷主服務為客觀下線
sentinel monitor master 127.0.0.1 6379 2

另:不同的Sentinel配置文件不同拓挥,因此對于同一主服務器認為其客觀下線的判斷也不一樣唠梨。

9.選舉領頭Sentinel

當一個主服務器被判定為主觀下線時,監(jiān)控這個主服務器的各個Sentinel會進行協(xié)商侥啤,選舉一個領頭Sentinel当叭,并由選舉出的這個領頭Sentinel對主服務器進行故障轉移。
具體選舉步驟如下:
1)所有在線Sentinel都有被選為領頭Sentinel的資格
2) 每次進行領頭Sentinel選舉之后盖灸,無論選舉是否成功蚁鳖,所有Sentinel的配置紀元值都會自增一次,配置紀元實際上就是一個計數(shù)器赁炎,并無其他特別之處
3) 在一個配置紀元里面醉箕,所有Sentinel都有一次將某個Sentinel設置為局部領頭Sentinel的機會,并且局部領頭Sentinel一旦設置徙垫,在這個配置紀元里面就不能在更改
4)每個發(fā)現(xiàn)主服務器客觀下線的Sentinel都會要求其他Sentinel將其設置為局部領頭Sentinel
5)當一個Sentinel向另一個Sentinel(目標)發(fā)送SENTINEL is-master-down-by-addr時讥裤,并且命令中runid不為*而是源Sentinel自身的runid時,即表示源Sentinel要求目標Sentinel將其設置為自己的局部領頭Sentinel姻报。設置局部領頭Sentinel的規(guī)則是先到先到己英,最先向目標Sentinel發(fā)送命令的源Sentinel被成功設置為目標Sentinel的局部領頭Sentinel。
6) 目標Sentinel在接收SENTINEL is-master-down-by-addr命令后吴旋,會向源Sentinel返回一條命令回復损肛,回復中的<leader_runid>和<leader_epoch>分別記錄了被成功設置為自身局部領頭Sentinel的runid和epoch,源Sentinel在收到目標Sentinel返回的命令回復后邮府,會對目標Sentinel回復的<leader_runid>和<leader_epoch>進行檢查荧关,如果都與自身信息一致則表示目標Sentinel將自身設置為局部領頭Sentinel
7) 如果有半數(shù)以上的Sentinel將源Sentinel設置為局部領頭Sentinel,那么這個Sentinel就成為領頭Sentinel褂傀。因為需要半數(shù)以上,因此每次最多會有一個領個Sentinel被選舉出加勤。
8) 如果在給定的時間內(nèi)仙辟,沒有選出領頭Sentinel,那么各個Sentinel將在一段時間后再次進行選舉鳄梅,直到選出領頭Sentinel

10.故障轉移

在選出領頭Sentinel之后叠国,該Sentinel會對被判定為客觀下線的主服務器執(zhí)行故障轉移:
1) 在已下線的主服務器屬下的從服務器里面挑選一個從服務器,并將其轉換為從服務器戴尸。
2) 讓已下線的主服務器下的剩余的從服務器改為復制新的主服務器
3) 將已下線的主服務器設置為新的主服務器的從服務器粟焊,當這個舊的主服務器重新上線時,它會成為新的主服務器的從服務器

10.1 選出新的主服務器

領頭Sentinel挑選出一個狀態(tài)良好、數(shù)據(jù)完整的從服務器项棠,然后向這個從服務器發(fā)送SLAVEOF no one命令悲雳,將這個從服務器轉換為主服務器。
具體挑選從服務器的規(guī)則如下:

  • 刪除列表中所有處于下線或斷線狀態(tài)的從服務器
  • 刪除最近5秒內(nèi)沒有回復過領頭Sentinel的INFO命令的從服務器
  • 刪除所有與已下線主服務器連接斷開查過 down-after-milliseconds*10時間的從服務器
  • 根據(jù)從服務器的優(yōu)先級進行排序
  • 如果有多個同優(yōu)先級的從服務器香追,那么按照復制偏移量進行排序
  • 如果復制偏移量相同的從服務器出現(xiàn)多臺合瓢,那么將從服務器的運行id進行排序,并選出運行id最小的從服務器

11.參考資料

《Redis設計與實現(xiàn)》

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末透典,一起剝皮案震驚了整個濱河市晴楔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌峭咒,老刑警劉巖税弃,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異凑队,居然都是意外死亡钙皮,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進店門顽决,熙熙樓的掌柜王于貴愁眉苦臉地迎上來短条,“玉大人,你說我怎么就攤上這事才菠∪资保” “怎么了?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵赋访,是天一觀的道長可都。 經(jīng)常有香客問我,道長蚓耽,這世上最難降的妖魔是什么渠牲? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮步悠,結果婚禮上签杈,老公的妹妹穿的比我還像新娘。我一直安慰自己鼎兽,他們只是感情好答姥,可當我...
    茶點故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著谚咬,像睡著了一般鹦付。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上择卦,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天敲长,我揣著相機與錄音郎嫁,去河邊找鬼。 笑死祈噪,一個胖子當著我的面吹牛泽铛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播钳降,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼厚宰,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了遂填?” 一聲冷哼從身側響起铲觉,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎吓坚,沒想到半個月后撵幽,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡礁击,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年盐杂,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片哆窿。...
    茶點故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡链烈,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出挚躯,到底是詐尸還是另有隱情强衡,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布码荔,位于F島的核電站漩勤,受9級特大地震影響,放射性物質發(fā)生泄漏缩搅。R本人自食惡果不足惜越败,卻給世界環(huán)境...
    茶點故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望硼瓣。 院中可真熱鬧究飞,春花似錦、人聲如沸巨双。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽筑累。三九已至,卻和暖如春丝蹭,著一層夾襖步出監(jiān)牢的瞬間慢宗,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留镜沽,地道東北人敏晤。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像缅茉,于是被迫代替她去往敵國和親嘴脾。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,543評論 2 349

推薦閱讀更多精彩內(nèi)容

  • [toc]Sentinel是Redis的高可用解決方案蔬墩,由一個或多個Sentinel實例組成的Sentinel系統(tǒng)...
    涵仔睡覺閱讀 256評論 0 0
  • Redis Sentinel 是一個分布式系統(tǒng)译打, 你可以在一個架構中運行多個 Sentinel 進程(progre...
    你是妖怪吧閱讀 897評論 0 0
  • Sentinel是Redis的高可用性解決方案,本文主要介紹Sentinel的初始化過程及其與一般Redis服務器...
    wenmingxing閱讀 3,085評論 1 5
  • 你是 秋水長天 你是山中的一泓清泉 奏著悅耳的琴聲 融化了皚皚白雪 你是海...
    秋水長天_42b2閱讀 234評論 0 1
  • 你問我怎么寫詩寫詩嘛就要像那蒲公英種子飛到哪便落到哪 20160529
    嚼冰閱讀 169評論 0 0