Redis Sentinel 是 Redis 的官方高可用解決方案,是設(shè)計(jì)用來(lái)幫助管理 Redis 實(shí)例的系統(tǒng)。用于完成下面 4 個(gè)任務(wù):
Redis Sentinel 是一個(gè)分布式系統(tǒng),這意味著,你通常想要在你的基礎(chǔ)設(shè)施中運(yùn)行多個(gè) Sentinel 進(jìn)程,這些進(jìn)程使用 gossip 協(xié)議來(lái)判斷一臺(tái)主服務(wù)器是否下線(down),使用 agreement 協(xié)議來(lái)獲得授權(quán)以執(zhí)行故障轉(zhuǎn)移,并更新相關(guān)配置。
分布式系統(tǒng)具有特定的安全(safety)和活性(liveness)的問(wèn)題,為了更好地使用 Redis Sentinel,你應(yīng)該去理解 Sentinel 是如何作為一個(gè)分布式系統(tǒng)運(yùn)轉(zhuǎn)的,至少在較高的層面上。這會(huì)讓 Sentinel 變得更復(fù)雜,但是比單進(jìn)程系統(tǒng)更好,例如:
當(dāng)前版本的 Sentinel 被稱(chēng)為 Sentinel 2。使用了更強(qiáng)大和簡(jiǎn)單的算法來(lái)重寫(xiě)最初的 Sentinel 實(shí)現(xiàn) (本文后面會(huì)解釋)。
穩(wěn)定版本的 Redis Sentinel 被打包在 Redis 2.8 中,這是最新的 Redis 版本。
新的開(kāi)發(fā)在不穩(wěn)定的分支中進(jìn)行,新的特性一旦穩(wěn)定了就會(huì)合并回 2.8 分支。
重要:即使你使用的是 Redis 2.6,你也應(yīng)該使用 Redis 2.8 自帶的 Sentinel。Redis 2.6 自帶的 Sentinel,也就是 Sentinel 1,已經(jīng)不贊成使用,并且有很多的 bug??傊銘?yīng)該盡快把你的 Redis 和 Sentinel 實(shí)例都遷移到 Redis 2.8,以獲得更好的全面體驗(yàn)。
如果你使用 redis-sentinel 可執(zhí)行文件 (或者如果你有一個(gè)叫這個(gè)名字的到 redis-server 的符號(hào)鏈接),你可以使用下面的命令行來(lái)運(yùn)行 Sentinel:
redis-sentinel /path/to/sentinel.conf
另外,你可以直接使用 redis-server 可執(zhí)行文件并作為 Sentinel 模式啟動(dòng):
redis-server /path/to/sentinel.conf --sentinel
兩種方式是一樣的。
但是,運(yùn)行 Sentinel 強(qiáng)制使用配置文件,這個(gè)文件被系統(tǒng)用來(lái)保存當(dāng)前狀態(tài),在重啟時(shí)能重新加載。如果沒(méi)有指定配置文件,或者配置文件的路徑不可寫(xiě),Sentinel 將拒絕啟動(dòng)。
Sentinel 運(yùn)行時(shí)默認(rèn)監(jiān)聽(tīng) TCP 端口 26379,所以為了讓 Sentinel 正常運(yùn)行,你的服務(wù)器必須開(kāi)放 26379 端口,以接受從其他 Sentinel 實(shí)例 IP 地址的連接。否則,Sentinel 間就沒(méi)法通信,沒(méi)法協(xié)調(diào),也不會(huì)執(zhí)行故障轉(zhuǎn)移。
Redis 的源碼發(fā)行版中包含一個(gè)叫做 sentinel.conf 的自說(shuō)明示例配置文件,可以用來(lái)配置 Sentinel,一個(gè)典型的最小配置文件看起來(lái)就像下面這樣:
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
你只需要指定你要監(jiān)控的主服務(wù)器,并給每一個(gè)主服務(wù)器(可以擁有任意多個(gè)從服務(wù)器)一個(gè)不同的名字。沒(méi)有必要指定從服務(wù)器,因?yàn)樗鼈儠?huì)被自動(dòng)發(fā)現(xiàn)。Sentinel 會(huì)根據(jù)從服務(wù)器的額外信息來(lái)自動(dòng)更新配置(為了在重啟時(shí)還能保留配置)。每次故障轉(zhuǎn)移時(shí)將一臺(tái)從服務(wù)器提升為主服務(wù)器時(shí)都會(huì)重寫(xiě)配置文件。
上面的示例配置監(jiān)控了兩個(gè) Redis 實(shí)例集合,每個(gè)由一個(gè)主服務(wù)器和未知數(shù)量的從服務(wù)器組成。其中一個(gè)實(shí)例集合叫做 mymaster,另一個(gè)叫做 resque。
為了說(shuō)得再清楚一點(diǎn),我們一行一行地來(lái)看看這些配置選項(xiàng)是什么意思:
第一行告訴 Redis 監(jiān)控一個(gè)叫做 mymaster 的主服務(wù)器,地址為 127.0.0.1,端口為 6379,判斷這臺(tái)主服務(wù)器失效需要 2 個(gè) Sentinel 同意(如果同意數(shù)沒(méi)有達(dá)到,自動(dòng)故障轉(zhuǎn)移則不會(huì)開(kāi)始)。
但是要注意,無(wú)論你指定多少個(gè)同意來(lái)檢測(cè)實(shí)例是否正常工作,Sentinel 需要系統(tǒng)中已知的大多數(shù) Sentinel 的投票才能開(kāi)始故障轉(zhuǎn)移,并且在故障轉(zhuǎn)移之后獲取一個(gè)新的配置紀(jì)元(configuration Epoch) 賦予新的配置。
在例子中,仲裁人數(shù) (quorum) 被設(shè)置為 2,所以使用 2 個(gè) Sentinel 同意某臺(tái)主服務(wù)器不可到達(dá)或者在一個(gè)錯(cuò)誤的情況中,來(lái)觸發(fā)故障轉(zhuǎn)移(但是,你后面還會(huì)看到,觸發(fā)一個(gè)故障轉(zhuǎn)移還不足以開(kāi)始一次成功的故障轉(zhuǎn)移,還需要授權(quán))。
其他的選項(xiàng)基本上都是這樣的形式:
sentinel <option_name> <master_name> <option_value>
它們的作用如下:
down-after-milliseconds 表示要使 Sentinel 開(kāi)始認(rèn)為實(shí)例已下線(down),實(shí)例不可到達(dá)(沒(méi)有響應(yīng)我們的 PING,或者響應(yīng)一個(gè)錯(cuò)誤) 的毫秒數(shù)。這個(gè)時(shí)間過(guò)后,Sentinel 將標(biāo)記實(shí)例為主觀下線(subjectively down,也稱(chēng) SDOWN),這還不足以開(kāi)啟自動(dòng)故障轉(zhuǎn)移。但是,如果足夠的實(shí)例認(rèn)為具備主觀下線條件,實(shí)例就會(huì)被標(biāo)記為客觀下線(objectively down)。需要同意的 Sentinel 數(shù)量依賴(lài)于為這臺(tái)主服務(wù)器的配置。
parallel-syncs 設(shè)置在一次故障轉(zhuǎn)移之后,被配置為同時(shí)使用新主服務(wù)器的從服務(wù)器數(shù)量。這個(gè)數(shù)字越小,完成故障轉(zhuǎn)移過(guò)程需要的時(shí)間就越多,如果從服務(wù)器配置為服務(wù)舊數(shù)據(jù),你可能不太希望所有的從服務(wù)器同時(shí)從新的主服務(wù)器重同步,盡管復(fù)制過(guò)程通常不會(huì)阻塞從服務(wù)器,但是在重同步過(guò)程中仍然會(huì)有一段停下來(lái)的時(shí)間來(lái)加載來(lái)自于主服務(wù)器的大量數(shù)據(jù)。設(shè)置這個(gè)選項(xiàng)的值為 1 可以確保每次只有一個(gè)從服務(wù)器不可用。
其他的選項(xiàng)將在本文的剩余篇幅里介紹,Redis 發(fā)行版本中自帶的示例 sentinel.conf 文件中也有詳細(xì)的文檔。
所有的配置參數(shù)可以在運(yùn)行時(shí)用 SENTINEL SET 命令修改。請(qǐng)看下文中運(yùn)行時(shí)重新配置 Sentinel 這一部分獲取更多的信息。
本文前面的部分展示了每一個(gè)被 Sentinel 監(jiān)控的主服務(wù)器都關(guān)聯(lián)了一個(gè)仲裁人數(shù)的配置。它指定了同意主服務(wù)器不可達(dá)或者錯(cuò)誤條件需要的 Sentinel 進(jìn)程數(shù),以觸發(fā)一次故障轉(zhuǎn)移。
但是,故障轉(zhuǎn)移被觸發(fā)后,為了讓故障轉(zhuǎn)移真正執(zhí)行,必須至少大多數(shù)的 Sentinel 授權(quán)某個(gè) Sentinel 才能錯(cuò)誤轉(zhuǎn)移。
讓我們解釋的再清楚一些:
差別看起來(lái)很微妙,但是實(shí)際上理解和使用起來(lái)都相當(dāng)簡(jiǎn)單。例如,如果你有 5 個(gè) Sentinel 實(shí)例,然后設(shè)置仲裁人數(shù)為 2,只要有 2 個(gè) Sentinel 認(rèn)為主服務(wù)器不可達(dá)就會(huì)觸發(fā)一次故障轉(zhuǎn)移,這兩個(gè) Sentinel 僅當(dāng)?shù)玫街辽?3 個(gè) Sentinel 的授權(quán)時(shí)才能故障轉(zhuǎn)移。
如果設(shè)置仲裁人數(shù)為 5,所有的 Sentinel 都必須同意主服務(wù)器的錯(cuò)誤條件,故障轉(zhuǎn)移需要所有 Sentinel 的授權(quán)。
Sentinel 需要大多數(shù)的授權(quán)來(lái)開(kāi)啟故障轉(zhuǎn)移是有幾個(gè)重要原因的:
當(dāng)一個(gè) Sentinel 得到授權(quán)了,就會(huì)為故障轉(zhuǎn)移的主服務(wù)器獲得一個(gè)唯一的配置紀(jì)元。這是在故障轉(zhuǎn)移完成后用于標(biāo)記新的配置的一個(gè)版本數(shù)字。因?yàn)榇蠖鄶?shù)同意將一個(gè)指定的版本賦予一個(gè)指定的 Sentinel,所以其它的 Sentinel 不能使用它。這意味著,每一次故障轉(zhuǎn)移的配置都使用一個(gè)唯一的版本來(lái)標(biāo)記。我們會(huì)看到為什么這個(gè)是如此的重要。
另外,Sentinel 有一個(gè)規(guī)則:如果一個(gè) Sentinel 為了指定的主服務(wù)器故障轉(zhuǎn)移而投票給另一個(gè) Sentinel,將會(huì)等待一段時(shí)間后試圖再次故障轉(zhuǎn)移這臺(tái)主服務(wù)器。這個(gè)延時(shí)(delay)是 failover-timeout,你可以在 sentinel.conf 中配置。這意味著,Sentinel 不會(huì)同時(shí)故障轉(zhuǎn)移同一臺(tái)主服務(wù)器,第一個(gè)請(qǐng)求被授權(quán)的將會(huì)嘗試,如果失敗了,過(guò)一會(huì)后另一個(gè)將會(huì)嘗試,等等。
Redis Sentinel 保證活性(liveness)屬性,如果大多數(shù) Sentinel 能夠?qū)υ?,如果主服?wù)器下線,最后只會(huì)有一個(gè)被授權(quán)來(lái)故障轉(zhuǎn)移。
Redis Sentinel 也保證安全(safety)屬性,每個(gè) Sentinel 將會(huì)使用不同的配置紀(jì)元來(lái)故障轉(zhuǎn)移同一臺(tái)主服務(wù)器。
一旦一個(gè) Sentinel 能夠成功故障轉(zhuǎn)移一臺(tái)主服務(wù)器,會(huì)開(kāi)始廣播新的配置,從而使其他 Sentinel 更新關(guān)于這臺(tái)主服務(wù)器的信息。
為了認(rèn)定故障轉(zhuǎn)移是成功的,需要 Sentinel 能發(fā)送 SLAVEOF NO ONE 給選定的從服務(wù)器,并將其切換為主服務(wù)器,稍后可以在主服務(wù)器的 INFO 輸出中觀察到。
這時(shí),即使從服務(wù)器的重新配置還在進(jìn)行中,故障轉(zhuǎn)移被認(rèn)為是成功的,所有的 Sentinel 被要求開(kāi)始報(bào)告新的配置。
新配置傳播的方式,就是為什么我們需要每次 Sentinel 故障轉(zhuǎn)移時(shí)被授權(quán)一個(gè)不同的版本號(hào)(配置紀(jì)元)的原因。
每一個(gè) Sentinel 使用 Redis 的發(fā)布訂閱(Pub/Sub)消息不斷地廣播主服務(wù)器的配置版本,在主服務(wù)器上以及所有從服務(wù)器上。與此同時(shí),所有的 Sentinel 等待其它 Sentinel 通知的配置消息。
配置信息在__sentinel__:hello 頻道中廣播。
因?yàn)槊恳粋€(gè)配置有一個(gè)不同的版本號(hào),所以更大的版本號(hào)總是勝過(guò)更小的版本號(hào)。
例如,一開(kāi)始所有的 Sentinel 認(rèn)為主服務(wù)器 mymaster 的配置為 192.168.1.50:6379。這個(gè)配置擁有版本 1。一段時(shí)間以后,一個(gè) Sentinel 被授權(quán)以版本 2 來(lái)故障轉(zhuǎn)移。如果故障轉(zhuǎn)移成功,會(huì)廣播一個(gè)新的配置,比如說(shuō) 192.168.1.50:9000,作為版本 2。所有其他實(shí)例會(huì)看到這個(gè)配置,并相應(yīng)地更新它們的配置,因?yàn)樾碌呐渲脫碛幸粋€(gè)更大的版本號(hào)。
這意味著,Sentinel 保證第二個(gè)活性屬性:一個(gè)可以相互通信的 Sentinel 集合會(huì)統(tǒng)一到一個(gè)擁有更高版本號(hào)的相同配置上。
基本上,如果網(wǎng)絡(luò)是分割的,每個(gè)分區(qū)會(huì)統(tǒng)一到一個(gè)更高版本的本地配置。在沒(méi)有分割的特殊情況下,只有一個(gè)分區(qū),每個(gè) Sentinel 將會(huì)配置一致。
正如本文已經(jīng)簡(jiǎn)要提到的,Redis Sentinel 有兩個(gè)不同的下線概念,一個(gè)被稱(chēng)為主觀下線條件(SDOWN),一個(gè)本地 Sentinel 實(shí)例的下線條件。另一個(gè)稱(chēng)為客觀下線條件(ODOWN),當(dāng)足夠的 Sentinel(至少為主服務(wù)器 quorum 參數(shù)配置的數(shù)量) 具有 SDOWN 條件時(shí)就滿足 ODOWN,并且使用 SENTINEL is-master-down-by-addr 命令從其它 Sentinel 獲得反饋。
從 Sentinel 的角度來(lái)看,如果我們沒(méi)有在配置的 is-master-down-after-milliseconds 參數(shù)的指定時(shí)間內(nèi)收到一個(gè) PING 請(qǐng)求的合法響應(yīng),就達(dá)到了 SDOWN 的條件。
PING 的可接受響應(yīng)可以是以下其中之一:
其它回復(fù) (或者沒(méi)有回復(fù)) 都被認(rèn)為是不合法的。
注意,SDOWN 需要在配置的整個(gè)時(shí)間區(qū)間內(nèi)沒(méi)有收到可以接受的回復(fù),例如,如果間隔配置為 30000 毫秒(30 秒),我們每隔 29 秒收到一個(gè)可以接受的 ping 回復(fù),實(shí)例被認(rèn)為是正常工作的。
從 SDOWN 切換到 ODOWN 沒(méi)有使用強(qiáng)一致性算法,而僅僅是 gossip 的形式:如果一個(gè)指定的 Sentinel 在指定的時(shí)間范圍內(nèi)從足夠多的 Sentinel 那里獲得關(guān)于主服務(wù)器不工作的報(bào)告,SDOWN 就被提升為 ODOWN。如果這種報(bào)告不再收到,(ODOWN)標(biāo)記就會(huì)被清除。
正如已經(jīng)解釋過(guò)的,真正開(kāi)始故障轉(zhuǎn)移需要更嚴(yán)格的授權(quán),但是,如果沒(méi)有達(dá)到 ODOWN 狀態(tài),是不會(huì)觸發(fā)故障轉(zhuǎn)移的。
ODOWN 條件只適用于主服務(wù)器。對(duì)于其他的實(shí)例,Sentinel 不需要任何同意,所以從服務(wù)器和其它 Sentinel 永遠(yuǎn)都不會(huì)達(dá)到 ODOWN 狀態(tài)。
Sentinel 之間保持著連接來(lái)互相檢查彼此的可用性,互相交換信息,你不需要在每個(gè)你運(yùn)行的 Sentinel 實(shí)例中配置其他 Sentinel 的地址,因?yàn)?Sentinel 使用 Redis 主服務(wù)器的發(fā)布訂閱能力來(lái)發(fā)現(xiàn)監(jiān)控同一臺(tái)主服務(wù)器的其他 Sentinel。
這是通過(guò)向名為_(kāi)_sentinel__:hello 頻道發(fā)送問(wèn)候消息 (Hello Messages) 實(shí)現(xiàn)的。
同樣,你不需要配置連接在主服務(wù)器上的從服務(wù)器列表,因?yàn)?Sentinel 會(huì)通過(guò)詢(xún)問(wèn) Redis 自動(dòng)發(fā)現(xiàn)這個(gè)列表。