主從復(fù)制的問題
? 對于上篇文章redis持久化rdb及aof中,redis服務(wù)器重啟時(shí)的數(shù)據(jù)恢復(fù),在新版本中是不符合我畫的那個(gè)流程圖的。
? redis啟動的時(shí)候會去判斷是否開啟aof,如果開啟了,不存在aof文件的話,會去判斷是否存在rdb,但在新的版本中,如果開啟aof,不存在aof文件的時(shí)候,redis會主動創(chuàng)建aof文件并且加載aof,這就會導(dǎo)致數(shù)據(jù)丟失。解決方案如下:
- 關(guān)閉aof
- 啟動redis去加載rdb文件
- 動態(tài)開啟aof最終達(dá)到數(shù)據(jù)一致性
? 當(dāng)主機(jī)master宕機(jī)以后,需要人工解決切換,比如使用slaveof no one。實(shí)際上主從復(fù)制并沒有實(shí)現(xiàn)高可用。
高可用側(cè)重備份機(jī)器,利用集群中系統(tǒng)的冗余,當(dāng)系統(tǒng)中某臺機(jī)器發(fā)生損壞的時(shí)候,其它后備的機(jī)器可以迅速的接替它來啟動服務(wù)。

如何解決:
如果我們有一個(gè)監(jiān)控程序能夠監(jiān)控各個(gè)機(jī)器的狀態(tài)并及時(shí)調(diào)整,手動操作變?yōu)樽詣硬僮鳎?strong>Sentinel的出現(xiàn)就是為了解決這個(gè)問題。
哨兵機(jī)制的原理
? Reids Sentinel一個(gè)分布式架構(gòu),其中包含若干個(gè)Sentinel節(jié)點(diǎn)和Redis數(shù)據(jù)節(jié)點(diǎn),每個(gè)Sentinel節(jié)點(diǎn)會對數(shù)據(jù)節(jié)點(diǎn)和其余Sentinel節(jié)點(diǎn)進(jìn)行監(jiān)控,當(dāng)它發(fā)現(xiàn)節(jié)點(diǎn)不可達(dá)的時(shí)候,會對節(jié)點(diǎn)做下線標(biāo)識。
? 如果被標(biāo)識的是主節(jié)點(diǎn),它還會和其它Sentinel節(jié)點(diǎn)進(jìn)行協(xié)商,當(dāng)大多數(shù)Sentinel節(jié)點(diǎn)都認(rèn)為主節(jié)點(diǎn)不可達(dá)時(shí),它們會選舉出一個(gè)Sentinel節(jié)點(diǎn)來完成自動故障轉(zhuǎn)移的工作,同時(shí)會將這個(gè)變化實(shí)時(shí)通知給Redis應(yīng)用方。整個(gè)過程完全是自動的,不需要人工來介入,所以這套方案很有效地解決了Redis高可用的問題。

基本的故障轉(zhuǎn)移流程:
- 主節(jié)點(diǎn)出現(xiàn)故障,此時(shí)兩個(gè)從節(jié)點(diǎn)與主節(jié)點(diǎn)失去連接,主從復(fù)制失敗。
- 每個(gè)Sentinel節(jié)點(diǎn)通過定期監(jiān)控發(fā)現(xiàn)主節(jié)點(diǎn)出現(xiàn)了故障
- 多個(gè)Sentinel節(jié)點(diǎn)對主節(jié)點(diǎn)的故障達(dá)成一致會選舉出其中一個(gè)節(jié)點(diǎn)作為領(lǐng)導(dǎo)者負(fù)責(zé)故障轉(zhuǎn)移。
- Sentinel領(lǐng)導(dǎo)者節(jié)點(diǎn)執(zhí)行了故障轉(zhuǎn)移,整個(gè)過程基本是跟我們手動調(diào)整一致的,只不過是自動化完成的。
- 故障轉(zhuǎn)移后整個(gè)Redis Sentinel的結(jié)構(gòu),重新選舉了新的主節(jié)點(diǎn)。
Redis Sentinel具有的功能:
- 監(jiān)控:Sentinel節(jié)點(diǎn)會定期檢查Redis數(shù)據(jù)節(jié)點(diǎn)、其余Sentinel節(jié)點(diǎn)是否可達(dá)。
- 通知:Sentinel節(jié)點(diǎn)會將故障轉(zhuǎn)移的結(jié)果通知給應(yīng)用方。
- 主節(jié)點(diǎn)故障轉(zhuǎn)移:實(shí)現(xiàn)從節(jié)點(diǎn)晉升為主節(jié)點(diǎn)并維護(hù)后續(xù)正確的主從關(guān)系。
- 配置提供者:在Redis Sentinel結(jié)構(gòu)中,客戶端在初始化的時(shí)候連接的是Sentinel節(jié)點(diǎn)集合,從中獲取主節(jié)點(diǎn)信息。
同時(shí)Redis Sentinel包含了若干個(gè)Sentinel節(jié)點(diǎn),這樣做也帶了兩個(gè)好處:
- 對于節(jié)點(diǎn)的故障判斷是由多個(gè)Sentinel節(jié)點(diǎn)共同完成,這樣可以有效地防止誤判。
- Sentinel節(jié)點(diǎn)集合是由若干個(gè)Sentinel節(jié)點(diǎn)組成的,這樣即使個(gè)別Sentinel節(jié)點(diǎn)不可用,整個(gè)Sentinel節(jié)點(diǎn)集合依然是健壯的。
但是Sentinel節(jié)點(diǎn)本身就是獨(dú)立的Reids節(jié)點(diǎn),只不過它們有一些特殊,不存儲數(shù)據(jù),只支持部分命令。
docker-compose 實(shí)現(xiàn) redis-sentinel
| 容器名稱 | 容器IP | 映射端口號 | 服務(wù)運(yùn)行模式 |
|---|---|---|---|
| Redis-master | 192.168.3.2 | 6380->6379 | Master |
| Redis-slave1 | 192.168.3.3 | 6381->6379 | Slave |
| Redis-slave2 | 192.168.3.4 | 6382->6379 | Slave |
| Redis-sentinel1 | 192.168.3.11 | 26380->26379 | Sentinel |
| Redis-sentinel2 | 192.168.3.12 | 26381->26379 | Sentinel |
| Redis-sentinel3 | 192.168.3.13 | 26382->26379 | Sentinel |
在這里我用的鏡像是redis官方的6.0.5。去網(wǎng)上把配置文件下載下來(redis.conf、sentinel.conf)
然后開始進(jìn)行:

創(chuàng)建目錄,并且把配置文件拷貝進(jìn)去。
sentinel目錄下的所有配置文件進(jìn)行簡單的修改:
搜索sentinel monitor 改為 sentinel monitor mymaster 192.168.3.2 6379 2
server目錄下進(jìn)行修改:
bind 127.0.0.1改為bind 0.0.0.0
replicaof <masterip> <masterport>改為replicaof 192.168.3.2 6379(除master目錄)
創(chuàng)建docker-compose.yml:
version: "3.6"
services:
redis-master:
image: redis
container_name: "redis-master"
ports:
- "6380:6379"
volumes:
- /Users/gaobinzhan/Documents/Redis/server/master:/redis
command: redis-server /redis/conf/redis.conf
networks:
redis-test:
ipv4_address: 192.168.3.2
redis-slave1:
image: redis
container_name: "redis-slave1"
ports:
- "6381:6379"
volumes:
- /Users/gaobinzhan/Documents/Redis/server/slave1:/redis
command: redis-server /redis/conf/redis.conf
networks:
redis-test:
ipv4_address: 192.168.3.3
redis-slave2:
image: redis
container_name: "redis-slave2"
ports:
- "6382:6379"
volumes:
- /Users/gaobinzhan/Documents/Redis/server/slave2:/redis
command: redis-server /redis/conf/redis.conf
networks:
redis-test:
ipv4_address: 192.168.3.4
redis-sentinel1:
image: redis
container_name: "redis-sentinel1"
ports:
- "26380:26379"
volumes:
- /Users/gaobinzhan/Documents/Redis/sentinel/sentinel1:/redis
command: redis-sentinel /redis/conf/sentinel.conf
networks:
redis-test:
ipv4_address: 192.168.3.11
redis-sentinel2:
image: redis
container_name: "redis-sentinel2"
ports:
- "26381:26379"
volumes:
- /Users/gaobinzhan/Documents/Redis/sentinel/sentinel2:/redis
command: redis-sentinel /redis/conf/sentinel.conf
networks:
redis-test:
ipv4_address: 192.168.3.12
redis-sentinel3:
image: redis
container_name: "redis-sentinel3"
ports:
- "26382:26379"
volumes:
- /Users/gaobinzhan/Documents/Redis/sentinel/sentinel3:/redis
command: redis-sentinel /redis/conf/sentinel.conf
networks:
redis-test:
ipv4_address: 192.168.3.13
networks:
redis-test:
driver: bridge
ipam:
config:
- subnet: "192.168.3.0/24"
進(jìn)行docker-compose up,執(zhí)行完畢后:
redis-cli工具運(yùn)行redis-cli -p 26380輸入info:

出現(xiàn)以上信息即搭建成功。。
Sentinel的核心配置:
sentinel monitor mymaster 192.168.3.2 6379 2
監(jiān)控的主節(jié)點(diǎn)的名字、IP 和端口,最后一個(gè)2的意思是有幾臺 Sentinel發(fā)現(xiàn)有問題,就會發(fā)生故障轉(zhuǎn)移,例如 配置為2,代表至少有2個(gè) Sentinel 節(jié)點(diǎn)認(rèn)為主節(jié)點(diǎn)不可達(dá),那么這個(gè)不可達(dá)的判定才是客觀的。對于設(shè)置的越小,那么達(dá)到下線的條件越寬松,反之越嚴(yán)格。一般建議將其設(shè)置為 Sentinel 節(jié)點(diǎn)的一半加1。最后的參數(shù)不可大于Sentinel節(jié)點(diǎn)數(shù)。
sentinel down-after-millseconds mymaster 30000
這個(gè)是超時(shí)的時(shí)間(單位為毫米)。打個(gè)比方,當(dāng)你去ping一個(gè)機(jī)器的時(shí)候,多長時(shí)間后仍ping不通,那么就認(rèn)為它是有問題。
sentinel parallel-syncs my master 1
當(dāng)Sentinel節(jié)點(diǎn)集合對主節(jié)點(diǎn)故障判斷達(dá)成一致時(shí),Sentinel領(lǐng)導(dǎo)者節(jié)點(diǎn)會被做故障轉(zhuǎn)移操作,選出新的主節(jié)點(diǎn),原來的從節(jié)點(diǎn)會向新的主節(jié)點(diǎn)發(fā)起復(fù)制操作,paraller-syncs就是用來限制在一次故障轉(zhuǎn)移之后,每次向新的主節(jié)點(diǎn)發(fā)起復(fù)制操作的從節(jié)點(diǎn)個(gè)數(shù),指出Sentinel屬于并發(fā)還是串行。1代表每次只能復(fù)制一個(gè),可以減輕Master的壓力。
sentinel auth-pass <master-name> <password>
如果 Sentinel 監(jiān)控的主節(jié)點(diǎn)配置了密碼,sentinel auth-pass 配置通過添加主節(jié)點(diǎn)的密碼,防止 Sentinel 節(jié)點(diǎn)對主節(jié)點(diǎn)無法監(jiān)控。
sentinel failover-timeout mymaster 180000
表示故障轉(zhuǎn)移的時(shí)間。