十年網(wǎng)站開(kāi)發(fā)經(jīng)驗(yàn) + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊(duì)
量身定制 + 運(yùn)營(yíng)維護(hù)+專業(yè)推廣+無(wú)憂售后,網(wǎng)站問(wèn)題一站解決
前言
Redis作為內(nèi)存數(shù)據(jù)庫(kù),需要具備高可用的特點(diǎn),不然如果服務(wù)器宕機(jī),還在內(nèi)存里的數(shù)據(jù)就會(huì)丟失。我們最常用的高可用方法就是搭建集群,master機(jī)器掛了,可以讓slave機(jī)器頂上,繼續(xù)提供服務(wù)。但是Redis集群是不會(huì)自動(dòng)進(jìn)行主從切換的,也就是說(shuō),如果主節(jié)點(diǎn)非常不爭(zhēng)氣的在凌晨3點(diǎn)掛了,那么運(yùn)維同學(xué)就要馬上起床,把從節(jié)點(diǎn)改成主節(jié)點(diǎn),這樣的操作是非常繁瑣低效的。為此,Redis官方提供了一種解決方案:Redis Sentinel
簡(jiǎn)介
Redis Sentinel集群通常由3到5個(gè)節(jié)點(diǎn)組成,如果個(gè)別節(jié)點(diǎn)掛了,集群還可以正常運(yùn)作。它負(fù)責(zé)監(jiān)控Redis集群的健康情況。如果主節(jié)點(diǎn)掛掉,Sentinel集群會(huì)通過(guò)投票選擇一個(gè)新的主節(jié)點(diǎn)。當(dāng)原來(lái)的主節(jié)點(diǎn)恢復(fù)時(shí),它會(huì)被當(dāng)做新的主節(jié)點(diǎn)的從節(jié)點(diǎn)重新加入Redis集群。
基本原理
Sentinel集群通過(guò)指定的配置文件發(fā)現(xiàn)master,對(duì)其進(jìn)行監(jiān)控,并且會(huì)發(fā)送info指令獲取master的從節(jié)點(diǎn)信息。Sentinel集群中的節(jié)點(diǎn)通過(guò)向其監(jiān)控的主從節(jié)點(diǎn)發(fā)送hello信息(包含Sentinel本身的ip、端口和id等內(nèi)容)來(lái)向其他Sentinel宣告自己的存在。
Sentinel集群通過(guò)訂閱連接來(lái)接收其他Sentinel的hello信息。
Sentinel集群通過(guò)ping命令來(lái)檢查監(jiān)控的實(shí)例狀態(tài),如果在指定時(shí)間內(nèi)沒(méi)有返回,則認(rèn)為該實(shí)例下線。
Sentinel觸發(fā)failover主從切換后,并不會(huì)馬上進(jìn)行,只有指定(quorum)Sentinel授權(quán)后,master節(jié)點(diǎn)被標(biāo)記為ODOWN狀態(tài)。這時(shí)才真正開(kāi)始投票選擇新的master。
Sentinel選擇新的master的原則是:首先判斷優(yōu)先級(jí),選擇優(yōu)先級(jí)較小的;如果優(yōu)先級(jí)相同,查看復(fù)制下標(biāo),選擇復(fù)制數(shù)據(jù)較多的;如果復(fù)制下標(biāo)也相同,就選擇進(jìn)程ID較小的。
Sentinel被授權(quán)后,它將會(huì)獲得宕掉的master的一份最新配置版本號(hào)(config-epoch),當(dāng)failover執(zhí)行結(jié)束以后,這個(gè)版本號(hào)將會(huì)被用于最新的配置,通過(guò)廣播形式通知其它Sentinel,其它的Sentinel則更新對(duì)應(yīng)master的配置。
基本使用
我們以Python為例,簡(jiǎn)單說(shuō)明一下在客戶端如何使用Sentinel
from redis.sentinel import Sentinel if __name__ == '__main__': sentinel = Sentinel(['localhost', 26379], socket_timeout=0.1) print(sentinel.discover_master('mymaster')) print(sentinel.discover_slaves('mymaster')) master = sentinel.master_for('mymaster', socket_timeout=0.1) slave = sentinel.slave_for('mymaster', socket_timeout=0.1) master.set('follow', 'Jackeyzhe2018') follow = slave.get('follow') print(follow)