前言:先了解一下redis主從模式巧颈、哨兵模式畦木、cluster(集群)模式
1、主從模式:是三種集群方式里最簡單的砸泛。它主要是基于Redis的主從復(fù)制特性架構(gòu)的十籍。通常我們會(huì)設(shè)置一個(gè)主節(jié)點(diǎn),N個(gè)從節(jié)點(diǎn);默認(rèn)情況下唇礁,主節(jié)點(diǎn)負(fù)責(zé)處理使用者的IO操作勾栗,而從節(jié)點(diǎn)則會(huì)對主節(jié)點(diǎn)的數(shù)據(jù)進(jìn)行備份,并且也會(huì)對外提供讀操作的處理盏筐。主要的特點(diǎn)如下:
- 主從模式下围俘,當(dāng)某一節(jié)點(diǎn)損壞時(shí),因?yàn)槠鋾?huì)將數(shù)據(jù)備份到其它Redis實(shí)例上琢融,這樣做在很大程度上可以恢復(fù)丟失的數(shù)據(jù)界牡。
- 主從模式下,可以保證負(fù)載均衡漾抬,這里不再敘說了
- 主從模式下宿亡,主節(jié)點(diǎn)和從節(jié)點(diǎn)是讀寫分離的。使用者不僅可以從主節(jié)點(diǎn)上讀取數(shù)據(jù)纳令,還可以很方便的從從節(jié)點(diǎn)上讀取到數(shù)據(jù)挽荠,這在一定程度上緩解了主機(jī)的壓力。
- 從節(jié)點(diǎn)也是能夠支持寫入數(shù)據(jù)的泊碑,只不過從從節(jié)點(diǎn)寫入的數(shù)據(jù)不會(huì)同步到主節(jié)點(diǎn)以及其它的從節(jié)點(diǎn)下坤按。
- 從以上,我們不難看出Redis在主從模式下馒过,必須保證主節(jié)點(diǎn)不會(huì)宕機(jī)——一旦主節(jié)點(diǎn)宕機(jī)臭脓,其它節(jié)點(diǎn)不會(huì)競爭稱為主節(jié)點(diǎn),此時(shí)腹忽,Redis將喪失寫的能力来累。這點(diǎn)在生產(chǎn)環(huán)境中,是致命的窘奏。
2嘹锁、哨兵模式:是基于主從模式做的一定變化,它能夠?yàn)镽edis提供了高可用性着裹。在實(shí)際生產(chǎn)中领猾,服務(wù)器難免不會(huì)遇到一些突發(fā)狀況:服務(wù)器宕機(jī),停電,硬件損壞等摔竿。這些情況一旦發(fā)生面粮,其后果往往是不可估量的。而哨兵模式在一定程度上能夠幫我們規(guī)避掉這些意外導(dǎo)致的災(zāi)難性后果继低。其實(shí)熬苍,哨兵模式的核心還是主從復(fù)制。只不過相對于主從模式在主節(jié)點(diǎn)宕機(jī)導(dǎo)致不可寫的情況下袁翁,多了一個(gè)競選機(jī)制——從所有的從節(jié)點(diǎn)競選出新的主節(jié)點(diǎn)柴底。競選機(jī)制的實(shí)現(xiàn),是依賴于在系統(tǒng)中啟動(dòng)一個(gè)sentinel進(jìn)程粱胜。
sentinel特點(diǎn):
- 監(jiān)控:它會(huì)監(jiān)聽主服務(wù)器和從服務(wù)器之間是否在正常工作柄驻。
- 通知:它能夠通過API告訴系統(tǒng)管理員或者程序,集群中某個(gè)實(shí)例出了問題焙压。
- 故障轉(zhuǎn)移:它在主節(jié)點(diǎn)出了問題的情況下凿歼,會(huì)在所有的從節(jié)點(diǎn)中競選出一個(gè)節(jié)點(diǎn),并將其作為新的主節(jié)點(diǎn)冗恨。
- 提供主服務(wù)器地址:它還能夠向使用者提供當(dāng)前主節(jié)點(diǎn)的地址。這在故障轉(zhuǎn)移后味赃,使用者不用做任何修改就可以知道當(dāng)前主節(jié)點(diǎn)地址掀抹。
sentinel,也可以集群心俗,部署多個(gè)哨兵傲武,sentinel可以通過發(fā)布與訂閱來自動(dòng)發(fā)現(xiàn)Redis集群上的其它sentinel。sentinel在發(fā)現(xiàn)其它sentinel進(jìn)程后城榛,會(huì)將其放入一個(gè)列表中揪利,這個(gè)列表存儲(chǔ)了所有已被發(fā)現(xiàn)的sentinel。
- 集群中的所有sentinel不會(huì)并發(fā)著去對同一個(gè)主節(jié)點(diǎn)進(jìn)行故障轉(zhuǎn)移狠持。故障轉(zhuǎn)移只會(huì)從第一個(gè)sentinel開始疟位,當(dāng)?shù)谝粋€(gè)故障轉(zhuǎn)移失敗后,才會(huì)嘗試下一個(gè)喘垂。當(dāng)選擇一個(gè)從節(jié)點(diǎn)作為新的主節(jié)點(diǎn)后甜刻,故障轉(zhuǎn)移即成功了(而不會(huì)等到所有的從節(jié)點(diǎn)配置了新的主節(jié)點(diǎn)后)。這過程中正勒,如果重啟了舊的主節(jié)點(diǎn)得院,那么就會(huì)出現(xiàn)無主節(jié)點(diǎn)的情況,這種情況下章贞,只能重啟集群祥绞。
- 當(dāng)競選出新的主節(jié)點(diǎn)后,被選為新的主節(jié)點(diǎn)的從節(jié)點(diǎn)的配置信息會(huì)被sentinel改寫為舊的主節(jié)點(diǎn)的配置信息。完成改寫后蜕径,再將新主節(jié)點(diǎn)的配置廣播給所有的從節(jié)點(diǎn)两踏。
3、 Redis集群(cluster) Redis 集群是一個(gè)提供在多個(gè)Redis間節(jié)點(diǎn)間共享數(shù)據(jù)的程序集丧荐。
- Redis集群并不支持處理多個(gè)keys的命令缆瓣,因?yàn)檫@需要在不同的節(jié)點(diǎn)間移動(dòng)數(shù)據(jù),從而達(dá)不到像Redis那樣的性能虹统,在高負(fù)載的情況下可能會(huì)導(dǎo)致不可預(yù)料的錯(cuò)誤弓坞。
- Redis 集群通過分區(qū)來提供一定程度的可用性,在實(shí)際環(huán)境中當(dāng)某個(gè)節(jié)點(diǎn)宕機(jī)或者不可達(dá)的情況下繼續(xù)處理命令。
Redis 集群的優(yōu)勢:
- 自動(dòng)分割數(shù)據(jù)到不同的節(jié)點(diǎn)上车荔。
- 整個(gè)集群的部分節(jié)點(diǎn)失敗或者不可達(dá)的情況下能夠繼續(xù)處理命令渡冻。
- Redis 集群的數(shù)據(jù)分片 Redis 集群沒有使用一致性hash, 而是引入了 哈希槽的概念.
- Redis 集群有16384個(gè)哈希槽忧便,每個(gè)key通過CRC16校驗(yàn)后對16384取模來決定放置哪個(gè)槽族吻。集群的每個(gè)節(jié)點(diǎn)負(fù)責(zé)一部分hash槽,舉個(gè)例子珠增,比如當(dāng)前集群有3個(gè)節(jié)點(diǎn),那么:
節(jié)點(diǎn) A 包含 0 到 5500號哈希槽超歌。
節(jié)點(diǎn) B 包含5501 到 11000 號哈希槽。
節(jié)點(diǎn) C 包含11001 到 16384號哈希槽蒂教。 - 這種結(jié)構(gòu)很容易添加或者刪除節(jié)點(diǎn)巍举。比如如果我想新添加個(gè)節(jié)點(diǎn)D, 我需要從節(jié)點(diǎn) A凝垛、B懊悯、C中得部分槽到D上。如果我想移除節(jié)點(diǎn)A梦皮,需要將A中的槽移到B和C節(jié)點(diǎn)上炭分,然后將沒有任何槽的A節(jié)點(diǎn)從集群中移除即可。由于從一個(gè)節(jié)點(diǎn)將哈希槽移動(dòng)到另一個(gè)節(jié)點(diǎn)并不會(huì)停止服務(wù)剑肯,所以無論添加刪除或者改變某個(gè)節(jié)點(diǎn)的哈希槽的數(shù)量都不會(huì)造成集群不可用的狀態(tài)捧毛。
- Redis 集群的主從復(fù)制模型 為了使在部分節(jié)點(diǎn)失敗或者大部分節(jié)點(diǎn)無法通信的情況下集群仍然可用,所以集群使用了主從復(fù)制模型,每個(gè)節(jié)點(diǎn)都會(huì)有N-1個(gè)復(fù)制品.
- 在我們例子中具有A退子、B岖妄、C三個(gè)節(jié)點(diǎn)的集群,在沒有復(fù)制模型的情況下寂祥,如果節(jié)點(diǎn)B失敗了荐虐,那么整個(gè)集群就會(huì)以為缺少5501-11000這個(gè)范圍的槽而不可用。然而如果在集群創(chuàng)建的時(shí)候(或者過一段時(shí)間)我們?yōu)槊總€(gè)節(jié)點(diǎn)添加一個(gè)從節(jié)點(diǎn)A1丸凭、B1福扬、C1腕铸。那么整個(gè)集群便有三個(gè)master節(jié)點(diǎn)和三個(gè)slave節(jié)點(diǎn)組成,這樣在節(jié)點(diǎn)B失敗后铛碑,集群便會(huì)選舉B1為新的主節(jié)點(diǎn)繼續(xù)服務(wù)狠裹,整個(gè)集群便不會(huì)因?yàn)椴壅也坏蕉豢捎昧恕2贿^當(dāng)B和B1 都失敗后汽烦,集群是不可用的涛菠。
注意:Redis一致性保證Redis 并不能保證數(shù)據(jù)的強(qiáng)一致性。這意味這在實(shí)際中集群在特定的條件下可能會(huì)丟失寫操作撇吞。
- 第一個(gè)原因是因?yàn)榧菏怯昧水惒綇?fù)制俗冻,寫操作過程:
客戶端向主節(jié)點(diǎn)B寫入一條命令;
主節(jié)點(diǎn)B向客戶端回復(fù)命令狀態(tài)牍颈;
主節(jié)點(diǎn)將寫操作復(fù)制給他得從節(jié)點(diǎn) B1迄薄、B2、B3煮岁。
主節(jié)點(diǎn)對命令的復(fù)制工作發(fā)生在返回命令回復(fù)之后讥蔽, 因?yàn)槿绻看翁幚砻钫埱蠖夹枰却龔?fù)制操作完成的話, 那么主節(jié)點(diǎn)處理命令請求的速度將極大地降低 —— 我們必須在性能和一致性之間做出權(quán)衡画机。 注意:Redis 集群可能會(huì)在將來提供同步寫的方法冶伞。
- Redis 集群另外一種可能會(huì)丟失命令的情況是集群出現(xiàn)了網(wǎng)絡(luò)分區(qū), 并且一個(gè)客戶端與至少包括一個(gè)主節(jié)點(diǎn)在內(nèi)的少數(shù)實(shí)例被孤立步氏。
舉個(gè)例子 假設(shè)集群包含 A 碰缔、 B 、 C 戳护、 A1 、 B1 瀑焦、 C1 六個(gè)節(jié)點(diǎn)腌且, 其中 A 、B 榛瓮、C 為主節(jié)點(diǎn)铺董, A1 、B1 禀晓、C1 為A精续、B、C的從節(jié)點(diǎn)粹懒, 還有一個(gè)客戶端 Z1 假設(shè)集群中發(fā)生網(wǎng)絡(luò)分區(qū)重付,那么集群可能會(huì)分為兩方,大部分的一方包含節(jié)點(diǎn) A 凫乖、C 确垫、A1 弓颈、B1 和 C1 ,小部分的一方則包含節(jié)點(diǎn) B 和客戶端 Z1删掀。
Z1仍然能夠向主節(jié)點(diǎn)B中寫入翔冀,如果網(wǎng)絡(luò)分區(qū)發(fā)生時(shí)間較短,那么集群將會(huì)繼續(xù)正常運(yùn)作披泪,如果分區(qū)的時(shí)間足夠讓大部分的一方將B1選舉為新的master纤子,那么Z1寫入B中得數(shù)據(jù)便丟失了。
注意:在網(wǎng)絡(luò)分裂出現(xiàn)期間款票, 客戶端 Z1 可以向主節(jié)點(diǎn) B 發(fā)送寫命令的最大時(shí)間是有限制的控硼, 這一時(shí)間限制稱為節(jié)點(diǎn)超時(shí)時(shí)間(node timeout), 是 Redis 集群的一個(gè)重要的配置選項(xiàng):
解決方案:
redis中有兩個(gè)配置參數(shù):
』罩啊(舊版本)
min-slaves-to-write 3
min-slaves-max-lag 10
∠笥薄(新版本)
min-replicas-to-write 3
min-replicas-max-lag 10
第一個(gè)參數(shù)表示最少的salve節(jié)點(diǎn)為3個(gè),第二個(gè)參數(shù)表示數(shù)據(jù)復(fù)制和同步的延遲不能超過10秒
配置了這兩個(gè)參數(shù):如果發(fā)生腦裂:原master會(huì)在客戶端寫入操作的時(shí)候拒絕請求姆钉。這樣可以避免大量數(shù)據(jù)丟失