一、Sentinel介紹
Sentinel是redis的高可用性(HA)解決方案: 由一個(gè)或多個(gè)Sentinel實(shí)例組成的Sentinel系統(tǒng)可以監(jiān)視任意多個(gè)主服務(wù)器,以及這些主服務(wù)器屬下的所有從服務(wù)器,并在被監(jiān)視的主服務(wù)器進(jìn)行下線狀態(tài)時(shí),自動(dòng)將下線主服務(wù)器屬下的某個(gè)從服務(wù)器升級(jí)為新的主服務(wù)器,然后由新的主服務(wù)器代替已下線的主服務(wù)器繼續(xù)處理命令請(qǐng)求。
二、Sentinel的主從原理
Redis提供的sentinel(哨兵)機(jī)制,通過sentinel模式啟動(dòng)redis后,自動(dòng)監(jiān)控master/slave的運(yùn)行狀態(tài),基本原理是:心跳機(jī)制+投票裁決
- 監(jiān)控(Monitoring): Sentinel 會(huì)不斷地檢查你的主服務(wù)器和從服務(wù)器是否運(yùn)作正常。
- 提醒(Notification): 當(dāng)被監(jiān)控的某個(gè) Redis 服務(wù)器出現(xiàn)問題時(shí), Sentinel 可以通過 API 向管理員或者其他應(yīng)用程序發(fā)送通知。
- 自動(dòng)故障遷移(Automatic failover): 當(dāng)一個(gè)主服務(wù)器不能正常工作時(shí), Sentinel 會(huì)開始一次自動(dòng)故障遷移操作, 它會(huì)將失效主服務(wù)器的其中一個(gè)從服務(wù)器升級(jí)為新的主服務(wù)器, 并讓失效主服務(wù)器的其他從服務(wù)器改為復(fù)制新的主服務(wù)器; 當(dāng)客戶端試圖連接失效的主服務(wù)器時(shí), 集群也會(huì)向客戶端返回新主服務(wù)器的地址, 使得集群可以使用新主服務(wù)器代替失效服務(wù)器。
假設(shè)這時(shí)s1下線,s2、 s3、 s4停止對(duì)s1的復(fù)制,sentinel系統(tǒng)會(huì)察覺到s1下線;s1下線時(shí)長(zhǎng)超過用戶設(shè)定的下線時(shí)長(zhǎng)限制,sentinel就會(huì)開始故障轉(zhuǎn)移操作;
1、sentinel系統(tǒng)會(huì)挑選s1下的從服務(wù)器,并將它設(shè)置為新的主服務(wù)器(master);
- 如何選出新的master?
一、使用如下條件篩選備選node:
1)、刪除列表中處于下線或者斷線狀態(tài)的服務(wù)器【S_DOWN,O_DOWN,DISCONNECTED】,這樣可以保證列表中剩余的服務(wù)器都是正常在線的。
2)、刪除列表中最近5秒內(nèi)沒有回復(fù)領(lǐng)頭sentinel的INFO命令的服務(wù)器,保證列表中剩余的服務(wù)器都是最近成功進(jìn)行通信的。
3)、刪除列表中與原master服務(wù)器斷開超過down-after-milliseconds*10毫秒的從服務(wù)器,保證剩余的服務(wù)器沒有過早跟主服務(wù)器斷開連接的。或者說是剩下的從服務(wù)器保存的數(shù)據(jù)是最新的。
4)、Slave priority不等于0(這個(gè)是在配置文件中指定,默認(rèn)配置為100)。
二、從備選node中,按照如下順序選擇新的master
1)、選出優(yōu)先級(jí)比較高的服務(wù)器;
2)、較大的replication offset(每個(gè)slave在與master同步后offset自動(dòng)增加);
3)、較小的runid(每個(gè)redis實(shí)例,都會(huì)有一個(gè)runid,通常是一個(gè)40位的隨機(jī)字符串,在redis啟動(dòng)時(shí)設(shè)置,重復(fù)概率非常小)
4)、如果以上條件都不足以區(qū)別出唯一的節(jié)點(diǎn),則會(huì)看哪個(gè)slave節(jié)點(diǎn)處理之前master發(fā)送的command多,就選誰(shuí)。
2、sentinel會(huì)給s1下的其他服務(wù)器,發(fā)送新的復(fù)制指令,讓他們follow新的主服務(wù)器;當(dāng)所有服務(wù)器都開始follow新的主服務(wù)器,故障轉(zhuǎn)移成功;
3、sentinel也會(huì)配置s1也follow新的主服務(wù)器,當(dāng)s1重新上線時(shí),s1直接follow新主服務(wù)器;
三、主觀下線和客觀下線
redis sentinel關(guān)于被監(jiān)控的redis實(shí)例出現(xiàn)不響應(yīng)的判斷,內(nèi)部有兩種不同的概念:主觀下線和客觀下線
主觀下線(SDOWN):
當(dāng)只有單個(gè)sentinel實(shí)例對(duì)redis實(shí)例做出無響應(yīng)的判斷,此時(shí)進(jìn)入主觀判斷,不會(huì)觸發(fā)自動(dòng)故障轉(zhuǎn)移等操作。
一個(gè)服務(wù)器必須在 master-down-after-milliseconds 毫秒內(nèi), 一直返回?zé)o效回復(fù)才會(huì)被 Sentinel 標(biāo)記為主觀下線。并在主服務(wù)器實(shí)例的flags屬性中打開【SRI_S_DOWN】標(biāo)識(shí).
不同的sentinel節(jié)點(diǎn),對(duì)主觀下線的判斷時(shí)長(zhǎng)可以不一樣,主要看自己的節(jié)點(diǎn)配置。
客觀下線(ODOWN) :
多個(gè) Sentinel 實(shí)例在對(duì)同一個(gè)服務(wù)器做出 SDOWN 判斷, 并且通過 SENTINEL is-master-down-by-addr 命令互相交流之后, 得出的服務(wù)器下線判斷。 (一個(gè) Sentinel 可以通過向另一個(gè) Sentinel 發(fā)送 SENTINEL is-master-down-by-addr 命令來詢問對(duì)方是否認(rèn)為給定的服務(wù)器已下線)如果達(dá)到配置要求的數(shù)量(sentinel的啟動(dòng)配置參數(shù))反饋,則可以標(biāo)識(shí)為客觀下線。flags標(biāo)識(shí)為【SRI_O_DOWN】
從主觀下線狀態(tài)切換到客觀下線狀態(tài)并沒有使用嚴(yán)格的法定人數(shù)算法(strong quorum algorithm), 而是使用了流言協(xié)議: 如果 Sentinel 在給定的時(shí)間范圍內(nèi), 從其他 Sentinel 那里接收到了足夠數(shù)量的主服務(wù)器下線報(bào)告, 那么 Sentinel 就會(huì)將主服務(wù)器的狀態(tài)從主觀下線改變?yōu)榭陀^下線。 如果之后其他 Sentinel 不再報(bào)告主服務(wù)器已下線, 那么客觀下線狀態(tài)就會(huì)被移除。
客觀下線條件只適用于主服務(wù)器: 對(duì)于任何其他類型的 Redis 實(shí)例, Sentinel 在將它們判斷為下線前不需要進(jìn)行協(xié)商, 所以從服務(wù)器Slave或者其他 Sentinel 永遠(yuǎn)不會(huì)達(dá)到客觀下線條件。
客觀下線狀態(tài)的判斷條件
sentinel monitor master 127.0.0.1 6379 2 那么有兩個(gè)sentinel認(rèn)為主服務(wù)器已經(jīng)下線狀態(tài),當(dāng)前的sentinel就可以認(rèn)為主服務(wù)器客觀下線了。
不同的sentinel判斷客觀下線的條件可能不同
1、sentinel monitor master 127.0.0.1 6379 2 兩個(gè)sentinel認(rèn)為主服務(wù)器已經(jīng)下線狀態(tài),當(dāng)前的sentinel就可以認(rèn)為主服務(wù)器客觀下線了。
2、sentinel monitor master 127.0.0.1 6379 5 兩個(gè)sentinel認(rèn)為主服務(wù)器已經(jīng)下線狀態(tài),并不會(huì)將主服務(wù)器客觀下線,只有5個(gè)sentinel認(rèn)為主服務(wù)器已經(jīng)下線了,當(dāng)前的sentinel才可以認(rèn)為主服務(wù)器客觀下線了。
四、選取領(lǐng)頭的sentinel
當(dāng)sentinel發(fā)現(xiàn)主庫(kù)客觀下線時(shí)候會(huì)進(jìn)行【領(lǐng)頭sentinel】選舉進(jìn)行故障恢復(fù),其選舉算法采用Raft算法,其設(shè)計(jì)思想類似與zookpeer的選舉機(jī)制的zab比較類似,所有在線的sentinel都可以參與選舉,都有機(jī)會(huì)被選為領(lǐng)頭的sentinel。選舉過程大體如下:
1、 發(fā)現(xiàn)主庫(kù)客觀下線的哨兵節(jié)點(diǎn)(這里稱為A)向每個(gè)哨兵節(jié)點(diǎn)發(fā)送命令【SENTINEL is-master-down-by-addr】,并且命令中包含自己的運(yùn)行ID(runid),要求對(duì)方選舉自己為領(lǐng)頭哨兵(leader);
2、 如果目標(biāo)哨兵沒有選舉過其他人,則同意將A選舉為領(lǐng)頭哨兵;回復(fù)一條命令,回復(fù)中的leader_runid參數(shù)和leader_epoch參數(shù),分別記錄了領(lǐng)頭sentinel的運(yùn)行ID和配置紀(jì)元;
3、 如果A發(fā)現(xiàn)有超過半數(shù)且超過quorum參數(shù)值的哨兵節(jié)點(diǎn)同意選自己成為領(lǐng)頭哨兵,則A哨兵成功選舉為領(lǐng)頭哨兵。
4、 Sentinel設(shè)置局部領(lǐng)頭Sentinel的規(guī)則是先到先得,最先向目標(biāo)sentinel發(fā)送設(shè)置的源sentinel將成為領(lǐng)頭sentinel,而之后接受到的所有設(shè)置請(qǐng)求會(huì)被拒絕;
5、當(dāng)有多個(gè)哨兵節(jié)點(diǎn)同時(shí)參與領(lǐng)頭哨兵選舉時(shí),出現(xiàn)沒有任何節(jié)點(diǎn)當(dāng)選可能,此時(shí)每個(gè)參選節(jié)點(diǎn)等待一個(gè)隨機(jī)時(shí)間進(jìn)行下一輪選舉,直到選出領(lǐng)頭哨兵。