En 400-6655-581
5
返回列表
> 資源中心 > 技術(shù)干貨 | Redis的哨兵和集群

技術(shù)干貨 | Redis的哨兵和集群

2019-11-29瀏覽次數(shù):1577

Redis全稱REmote DIctionary Server,是一個開源的使用ANSI C語言編寫、遵守BSD協(xié)議、支持網(wǎng)絡(luò)、可基于內(nèi)存亦可持久化的日志型、Key-Value數(shù)據(jù)庫,并提供多種語言的API。它通常被稱為數(shù)據(jù)結(jié)構(gòu)服務(wù)器,因?yàn)橹?/span>(value)可以是字符串(String), 哈希(Hash), 列表(list), 集合(sets) 和有序集合(sorted sets)等類型。


Redis經(jīng)常會被用于數(shù)據(jù)的緩存,session共享等場景下,Redis的本身的高可用就特別值得關(guān)注,我們來針對常用的兩種高可用架構(gòu)進(jìn)行說明。



Redis Sentinel(哨兵)


Redis Sentinel集群是由若干Sentinel節(jié)點(diǎn)組成的分布式集群,可以實(shí)現(xiàn)故障發(fā)現(xiàn)、故障自動轉(zhuǎn)移、配置中心和客戶端通知。Redis Sentinel的節(jié)點(diǎn)數(shù)量要滿足2n+1(n>=1)的奇數(shù)個。


哨兵模式其實(shí)是有2個集群在同時工作,一個是sentinel的集群,一個是數(shù)據(jù)節(jié)點(diǎn)的集群。典型的一個高可用架構(gòu)如下圖所示:



Sentinel架構(gòu)的主要作用是解決主從模式下主節(jié)點(diǎn)的故障轉(zhuǎn)移工作的。這里如果主節(jié)點(diǎn)因?yàn)楣收舷戮€,那么某個sentinel節(jié)點(diǎn)發(fā)送檢測消息給主節(jié)點(diǎn)時,如果在指定時間內(nèi)收不到回復(fù),那么該sentinel就會主觀的判斷該主節(jié)點(diǎn)已經(jīng)下線,那么其會發(fā)送消息給其余的sentinel節(jié)點(diǎn),詢問其是否“認(rèn)為”該主節(jié)點(diǎn)已下線,其余的sentinel收到消息后也會發(fā)送檢測消息給主節(jié)點(diǎn),如果其認(rèn)為該主節(jié)點(diǎn)已經(jīng)下線,那么其會回復(fù)向其詢問的sentinel節(jié)點(diǎn),告知其也認(rèn)為主節(jié)點(diǎn)已經(jīng)下線,當(dāng)該sentinel節(jié)點(diǎn)最先收到超過指定數(shù)目(配置文件中配置的數(shù)目和當(dāng)前sentinel節(jié)點(diǎn)集合數(shù)的一半,這里兩個數(shù)目的較大值)的sentinel節(jié)點(diǎn)回復(fù)說當(dāng)前主節(jié)點(diǎn)已下線,那么其就會對主節(jié)點(diǎn)進(jìn)行故障轉(zhuǎn)移工作。轉(zhuǎn)移完成后,sentinel也會通知客戶端進(jìn)行節(jié)點(diǎn)的轉(zhuǎn)移。


客戶端實(shí)現(xiàn)


客戶端從過去直接連接Redis ,變成先連接一個Sentinel實(shí)例使用 SENTINEL get-master-addr-by-name master-name 獲取Redis地址信息。


連接返回的Redis地址信息,通過ROLE命令查詢是否是Master。如果是,連接進(jìn)入正常的服務(wù)環(huán)節(jié)。否則應(yīng)該斷開重新查詢。


(可選)客戶端可以通過SENTINEL sentinels 來更新自己的Sentinel實(shí)例列表。當(dāng)Sentinel發(fā)起failover后,切換了新的Master,Sentinel會發(fā)送 CLIENT KILL TYPE normal命令給客戶端,客戶端需要主動斷開對老的Master的鏈接,然后重新查詢新的Master地址,再重復(fù)走上面的流程。這樣的方式仍然相對不夠?qū)崟r,可以通過Sentinel提供的Pub/Sub來更快地監(jiān)聽到failover事件,加快重連。


生產(chǎn)環(huán)境推薦



對于一個最小集群,Redis應(yīng)該是一個Master帶上兩個Slave,并且開啟下列選項(xiàng):


min-slaves-to-write 1

min-slaves-max-lag 10


這樣能保證寫入Master的同時至少寫入一個Slave,如果出現(xiàn)網(wǎng)絡(luò)分區(qū)阻隔并發(fā)生failover的時候,可以保證寫入的數(shù)據(jù)最終一致而不是丟失,寫入老的Master會直接失敗。


Slave可以適當(dāng)設(shè)置優(yōu)先級,除了0之外(0表示永遠(yuǎn)不提升為Master),越小的優(yōu)先級,越有可能被提示為Master。如果Slave分布在多個機(jī)房,可以考慮將和Master同一個機(jī)房的Slave的優(yōu)先級設(shè)置的更低以提升他被選為新的Master的可能性。


考慮到可用性和選舉的需要,Sentinel進(jìn)程至少為3個,推薦為5個。如果有網(wǎng)絡(luò)分區(qū),應(yīng)當(dāng)適當(dāng)分布(比如2個在A機(jī)房, 2個在B機(jī)房,一個在C機(jī)房)等。


Redis Cluster(集群)


Sentinel模式雖然解決了高可用的問題,但是單機(jī)的容量還是受到了限制,無法實(shí)現(xiàn)redis的分布式集群,限制了整個集群的容量和并發(fā)性能。


Redis Cluster集群節(jié)點(diǎn)最小配置6個節(jié)點(diǎn)以上(3主3從),其中主節(jié)點(diǎn)提供讀寫操作,從節(jié)點(diǎn)作為備用節(jié)點(diǎn),不提供請求,只作為故障轉(zhuǎn)移使用。



Cluster模式有眾多的優(yōu)點(diǎn):


? 無中心架構(gòu);

? 數(shù)據(jù)按照slot存儲分布在多個節(jié)點(diǎn),節(jié)點(diǎn)間數(shù)據(jù)共享,可動態(tài)調(diào)整數(shù)據(jù)分布;

? 可擴(kuò)展性:可線性擴(kuò)展到1000多個節(jié)點(diǎn),節(jié)點(diǎn)可動態(tài)添加或刪除;

? 高可用性:部分節(jié)點(diǎn)不可用時,集群仍可用。通過增加Slave做standby數(shù)據(jù)副本,能夠?qū)崿F(xiàn)故障自動failover,節(jié)點(diǎn)之間通過gossip協(xié)議交換狀態(tài)信息,用投票機(jī)制完成Slave到Master的角色提升;

? 降低運(yùn)維成本,提高系統(tǒng)的擴(kuò)展性和可用性。


限制條件


看起來很美好,cluster集群模式還是受到了一些使用上的限制:


1.Key批量操作支持有限。目前只支持同slot內(nèi)的key執(zhí)行批量操作(如mget,mset)。

2.Key事務(wù)操作支持有限。只支持多key在同一個節(jié)點(diǎn)上的事務(wù)操作,多個key分布在不同節(jié)點(diǎn)上時無法使用事務(wù)功能。

3.Key作為數(shù)據(jù)分區(qū)的最小粒度,因此不能將一個大的鍵值對象如hash,list等映射到不同節(jié)點(diǎn)。

4.不支持多數(shù)據(jù)庫空間,集群模式下只能使用db0空間。

5.復(fù)制結(jié)構(gòu)只支持一層,從節(jié)點(diǎn)只能復(fù)制主節(jié)點(diǎn),不支持嵌套樹狀復(fù)制結(jié)構(gòu)。


故障切換過程


故障節(jié)點(diǎn)變?yōu)榭陀^下線后,如果下線節(jié)點(diǎn)是持有槽的主節(jié)點(diǎn),則需要在它的從節(jié)點(diǎn)中選出一個替換它。從而保證集群高可用。下線主節(jié)點(diǎn)的所有從節(jié)點(diǎn)承擔(dān)故障恢復(fù)的義務(wù),當(dāng)從節(jié)點(diǎn)通過內(nèi)部定時任務(wù)發(fā)現(xiàn)自身復(fù)制的主節(jié)點(diǎn)進(jìn)入客觀下線時,將會觸發(fā)故障恢復(fù)流程。


Sentinel模式提供了高可用的功能,由于redis本身的性能優(yōu)異,很多企業(yè)內(nèi)部的系統(tǒng)用這種模式足以應(yīng)對。如果有些2C的應(yīng)用,則推薦采用redis的cluster模式。