本篇博客會簡單的介紹Redis的Sentinel相關(guān)的原理,同時也會在最后的文章給出硬核的實戰(zhàn)教程掂为,讓你在了解原理之后啡邑,能夠?qū)嶋H上手的體驗整個過程胞四。
之前的文章聊到了Redis的主從復(fù)制,聊到了其相關(guān)的原理和缺點闸翅,具體的建議可以看看我之前寫的文章Redis的主從復(fù)制再芋。
總的來說,為了滿足Redis在真正復(fù)雜的生產(chǎn)環(huán)境的高可用坚冀,僅僅是用主從復(fù)制是明顯不夠的济赎。例如,當(dāng)master節(jié)點宕機了之后,進行主從切換的時候司训,我們需要人工的去做failover构捡。
同時在流量方面,主從架構(gòu)只能通過增加slave節(jié)點來擴展讀請求壳猜,寫能力由于受到master單節(jié)點的資源限制是無法進行擴展的勾徽。
這也是為什么我們需要引入Sentinel。
Sentinel
功能概覽
Sentinel其大致的功能如下圖统扳。
Sentinel是Redis高可用的解決方案之一喘帚,本身也是分布式的架構(gòu),包含了多個Sentinel節(jié)點和多個Redis節(jié)點咒钟。而每個Sentinel節(jié)點會對Redis節(jié)點和其余的Sentinel節(jié)點進行監(jiān)控吹由。
當(dāng)其發(fā)現(xiàn)某個節(jié)點不可達時,如果是master節(jié)點就會與其余的Sentinel節(jié)點協(xié)商朱嘴。當(dāng)大多數(shù)的Sentinel節(jié)點都認為master不可達時倾鲫,就會選出一個Sentinel節(jié)點對master執(zhí)行故障轉(zhuǎn)移,并通知Redis的調(diào)用方相關(guān)的變更萍嬉。
相對于主從下的手動故障轉(zhuǎn)移乌昔,Sentinel的故障轉(zhuǎn)移是全自動的,無需人工介入帚湘。
Sentinel自身高可用
666玫荣,那我怎么知道滿足它自身的高可用需要部署多少個Sentinel節(jié)點?
因為Sentinel本身也是分布式的大诸,所以也需要部署多實例來保證自身集群的高可用捅厂,但是這個數(shù)量是有個最低的要求,最低需要3個资柔。
我去焙贷,你說3個就3個?我今天偏偏就只部署2個
你別杠...等我說了為什么就必須要3個...
因為哨兵執(zhí)行故障轉(zhuǎn)移需要大部分的哨兵都同意才行贿堰,如果只有兩個哨兵實例辙芍,正常運作還好,就像這樣羹与。
<img src="https://tva1.sinaimg.cn/large/0081Kckwgy1glf2ztrzuxj30uc0e0tad.jpg" alt="redis-sentinel" style="zoom: 67%;" />
如果哨兵所在的那臺機器由于機房斷電啊故硅,光纖被挖啊等極端情況整個掛掉了,那么另一臺哨兵即使發(fā)現(xiàn)了master故障之后想要執(zhí)行故障轉(zhuǎn)移纵搁,但是它無法得到任何其余哨兵節(jié)點的同意吃衅,此時也永遠無法執(zhí)行故障轉(zhuǎn)移,那Sentinel豈不是成了一個擺設(shè)腾誉?
所以我們需要至少3個節(jié)點徘层,來保證Sentinel集群自身的高可用峻呕。當(dāng)然,這三個Sentinel節(jié)點肯定都推薦部署到不同的機器上趣效,如果所有的Sentinel節(jié)點都部署到了同一臺機器上瘦癌,那當(dāng)這臺機器掛了,整個Sentinel也就不復(fù)存在了跷敬。
<img src="https://tva1.sinaimg.cn/large/0081Kckwgy1glf3ho05rwj31a20pkgp4.jpg" alt="redis-sentinel-success" style="zoom:67%;" />
quorum&majority
大部分讯私?大哥這可是要上生產(chǎn)環(huán)境,大部分這個數(shù)量未免也太敷衍了干花,咱就不能專業(yè)一點妄帘?
前面提到的大部分
哨兵同意涉及到兩個參數(shù),一個叫quorum
池凄,如果Sentinel集群有quorum
個哨兵認為master宕機了抡驼,就客觀的認為master宕機了。另一個叫majority
...
等等等等肿仑,不是已經(jīng)有了一個叫什么quorum的嗎致盟?為什么還需要這個majority?
你能不能等我把話說完...
quorum
剛剛講過了尤慰,其作用是判斷master是否處于宕機的狀態(tài)馏锡,僅僅是一個判斷作用。而我們在實際的生產(chǎn)中伟端,不是說只判斷master宕機就完了杯道, 我們不還得執(zhí)行故障轉(zhuǎn)移,讓集群正常工作嗎责蝠?
同理党巾,當(dāng)哨兵集群開始進行故障轉(zhuǎn)移時,如果有majority
個哨兵同意進行故障轉(zhuǎn)移霜医,才能夠最終選出一個哨兵節(jié)點齿拂,執(zhí)行故障轉(zhuǎn)移操作。
主觀宕機&客觀宕機
你剛剛是不是提到了客觀宕機肴敛?笑死署海,難不成還有主觀宕機這一說?
Sentinel中認為一個節(jié)點掛了有兩種類型:
- Subjective Down医男,簡稱sdown砸狞,主觀的認為master宕機
- Objective Down,簡稱odown镀梭,客觀的認為master宕機
當(dāng)一個Sentinel節(jié)點與其監(jiān)控的Redis節(jié)點A進行通信時趾代,發(fā)現(xiàn)連接不上,此時這個哨兵節(jié)點就會主觀的認為這個Redis數(shù)據(jù)A節(jié)點sdown了丰辣。為什么是主觀撒强?我們得先知道什么叫主觀
未經(jīng)分析推算,下結(jié)論笙什、決策和行為反應(yīng)飘哨,暫時不能與其他不同看法的對象仔細商討,稱為主觀琐凭。
簡單來說芽隆,因為有可能只是當(dāng)前的Sentinel節(jié)點和這個A節(jié)點的網(wǎng)絡(luò)通信有問題,其余的Sentinel節(jié)點仍然可以和A正常的通信统屈。
<img src="https://tva1.sinaimg.cn/large/0081Kckwgy1glhcj19q37j318o0lmgnb.jpg" alt="sentinel-sdown" style="zoom:50%;" />
這也是為什么我們需要引入odown胚吁,當(dāng)大于等于了quorum個Sentinel節(jié)點認為某個節(jié)點宕機了,我們就客觀的認為這個節(jié)點宕機了愁憔。
當(dāng)Sentinel集群客觀的認為master宕機腕扶,就會從所有的Sentinel節(jié)點中,選出一個Sentinel節(jié)點吨掌,來最終執(zhí)行master的故障轉(zhuǎn)移半抱。
那這個故障轉(zhuǎn)移具體要執(zhí)行些什么操作呢?我們通過一個圖來看一下膜宋。
<img src="https://tva1.sinaimg.cn/large/0081Kckwgy1glg76hj320j31cm0l240z.jpg" alt="sentinel-ops" style="zoom:67%;" />
通知調(diào)用的客戶端master發(fā)生了變化
通知其余的原slave節(jié)點窿侈,去復(fù)制Sentinel選舉出來的新的master節(jié)點
如果此時原來的master又重新恢復(fù)了,Sentinel也會讓其去復(fù)制新的master節(jié)點秋茫。成為一個新的slave節(jié)點史简。
硬核教程
硬核教程旨在用最快速的方法,讓你在本地體驗Redis主從架構(gòu)和Sentinel集群的搭建肛著,并體驗整個故障轉(zhuǎn)移的過程圆兵。
前置要求
- 安裝了docker
- 安裝了docker-compose
準備compose文件
首先需要準備一個目錄,然后分別建立兩個子目錄策泣。如下衙傀。
$ tree .
.
├── redis
│ └── docker-compose.yml
└── sentinel
├── docker-compose.yml
├── sentinel1.conf
├── sentinel2.conf
└── sentinel3.conf
2 directories, 5 files
搭建Redis主從服務(wù)器
redis目錄下的docker-compose.yml
內(nèi)容如下。
version: '3'
services:
master:
image: redis
container_name: redis-master
ports:
- 6380:6379
slave1:
image: redis
container_name: redis-slave-1
ports:
- 6381:6379
command: redis-server --slaveof redis-master 6379
slave2:
image: redis
container_name: redis-slave-2
ports:
- 6382:6379
command: redis-server --slaveof redis-master 6379
以上的命令萨咕,簡單解釋一下slaveof
就是讓兩個slave節(jié)點去復(fù)制container_name為redis-master的節(jié)點统抬,這樣就組成了一個簡單的3個節(jié)點的主從架構(gòu)
然后用命令行進入當(dāng)前目錄,直接敲命令docker-compose up
即可危队,剩下的事情交給docker-compose去做就好聪建,它會把我們所需要的節(jié)點全部啟動起來。
此時我們還需要拿到剛剛我們啟動的master節(jié)點的IP茫陆,簡要步驟如下:
-
通過
docker ps
找到對應(yīng)的master節(jié)點的containerID$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 9f682c199e9b redis "docker-entrypoint.s…" 3 seconds ago Up 2 seconds 0.0.0.0:6381->6379/tcp redis-slave-1 2572ab587558 redis "docker-entrypoint.s…" 3 seconds ago Up 2 seconds 0.0.0.0:6382->6379/tcp redis-slave-2 f70a9d9809bc redis "docker-entrypoint.s…" 3 seconds ago Up 2 seconds 0.0.0.0:6380->6379/tcp redis-master
也就是
f70a9d9809bc
金麸。 通過
docker inspect f70a9d9809bc
,拿到對應(yīng)容器的IP簿盅,在NetworkSettings -> Networks -> IPAddress字段挥下。
然后把這個值給記錄下來揍魂,此處我的值為172.28.0.3
。
搭建Sentinel集群
sentinel目錄下的docker-compose.yml
內(nèi)容如下棚瘟。
version: '3'
services:
sentinel1:
image: redis
container_name: redis-sentinel-1
ports:
- 26379:26379
command: redis-sentinel /usr/local/etc/redis/sentinel.conf
volumes:
- ./sentinel1.conf:/usr/local/etc/redis/sentinel.conf
sentinel2:
image: redis
container_name: redis-sentinel-2
ports:
- 26380:26379
command: redis-sentinel /usr/local/etc/redis/sentinel.conf
volumes:
- ./sentinel2.conf:/usr/local/etc/redis/sentinel.conf
sentinel3:
image: redis
container_name: redis-sentinel-3
ports:
- 26381:26379
command: redis-sentinel /usr/local/etc/redis/sentinel.conf
volumes:
- ./sentinel3.conf:/usr/local/etc/redis/sentinel.conf
networks:
default:
external:
name: redis_default
同樣在這里解釋一下命令
redis-sentinel 命令讓 redis 以 sentinel 的模式啟動现斋,本質(zhì)上就是一個運行在特殊模式的 redis 服務(wù)器。
和 redis-server 的區(qū)別在于偎蘸,他們分別載入了不同的命令表庄蹋,sentinel 中無法執(zhí)行各種redis中特有的 set get操作。
建立三份一模一樣的文件迷雪,分別命名為sentinel1.conf限书、sentinel2.conf和sentinel3.conf。其內(nèi)容如下:
port 26379
dir "/tmp"
sentinel deny-scripts-reconfig yes
sentinel monitor mymaster 172.28.0.3 6379 2
sentinel config-epoch mymaster 1
sentinel leader-epoch mymaster 1
可以看到章咧,我們對于sentinel的配置文件中倦西,sentinel monitor mymaster 172.28.0.3 6379 2
表示讓它去監(jiān)聽名為mymaster
的master節(jié)點,注意此處的IP一定要是你自己master節(jié)點的IP慧邮,然后最后面的2
就是我們之前提到的quorum
调限。
然后命令行進入名為sentinel的目錄下,敲docker-compose up
即可误澳。至此耻矮,Sentinel集群便啟動了起來。
手動模擬master掛掉
然后我們需要手動模擬master掛掉忆谓,來驗證我們搭建的Sentinel集群是否可以正常的執(zhí)行故障轉(zhuǎn)移裆装。
命令行進入名為redis的目錄下,敲入如下命令倡缠。
docker-compose pause master
此時就會將master容器給暫停運行哨免,讓我們等待10秒之后,就可以看到sentinel這邊輸出了如下的日志昙沦。
redis-sentinel-2 | 1:X 07 Dec 2020 01:58:05.459 # +sdown master mymaster 172.28.0.3 6379
......
......
......
redis-sentinel-1 | 1:X 07 Dec 2020 01:58:06.932 # +switch-master mymaster 172.28.0.3 6379 172.28.0.2 6379
得得得琢唾,你干什么就甩一堆日志文件上來?湊字數(shù)盾饮?你這樣鬼能看懂采桃?
的確,光從日志文件一行一行的看丘损,就算是我自己過兩周再來看普办,也是一臉懵逼。日志文件完整了描述了整個Sentinel集群從開始執(zhí)行故障轉(zhuǎn)移到最終執(zhí)行完成的所有細節(jié)徘钥,但是在這里直接放出來不方便大家的理解衔蹲。
所以為了讓大家能夠更加直觀的了解這個過程,我簡單的把過程抽象了成了一張圖呈础,大家看圖結(jié)合日志舆驶,應(yīng)該能夠更容易理解橱健。
里面關(guān)鍵的步驟步驟的相關(guān)解釋我也一并放入了圖片中。
最終的結(jié)果就是贞远,master已經(jīng)從我們最開始的172.28.0.3
切換到了172.28.0.2
畴博,后者則是原來的slave節(jié)點之一。此時我們也可以連接到172.28.0.2
這個容器里去蓝仲,通過命令來看一下其現(xiàn)在的情況。
role:master
connected_slaves:1
slave0:ip=172.28.0.4,port=6379,state=online,offset=18952,lag=0
master_replid:f0bf5d1c843ec3ab005c5ac2b864f7ffdc6a8217
master_replid2:72c43e1f9c05d4b08bea6bf9b2549997587e261c
master_repl_offset:18952
second_repl_offset:16351
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:18952
可以看到官疲,現(xiàn)在的172.28.0.2
這個節(jié)點的角色已經(jīng)變成了master袱结,與其相連接的slave節(jié)點只有1個,因為現(xiàn)在的原master還沒有啟動起來途凫,總共存活的只有2個實例垢夹。
原master重啟啟動
接下來我們模擬原master重新啟動,來看一下會發(fā)什么什么维费。
還是通過命令行進入到名為redis的本地目錄果元,通過docker-compose unpause master
來模擬原master故障恢復(fù)之后的上線。同樣我們連接到原master的機器上去犀盟。
$ docker exec -it f70a9d9809bc1e924a5be0135888067ad3eb16552f9eaf82495e4c956b456cd9 /bin/sh; exit
# redis-cli
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:172.28.0.2
master_port:6379
master_link_status:up
......
master斷線重連之后而晒,角色也變成了新的master(也就是172.28.0.2
這個節(jié)點)的一個slave。
然后我們也可以通過再看一下新master節(jié)點的replication情況作證阅畴。
# Replication
role:master
connected_slaves:2
slave0:ip=172.28.0.4,port=6379,state=online,offset=179800,lag=0
slave1:ip=172.28.0.3,port=6379,state=online,offset=179800,lag=1
......
原master短線重連之后倡怎,其connected_slaves變成了2,且原master172.28.0.3
被清晰的標注為了slave1贱枣,同樣與我們開篇和圖中所講的原理相符合监署。
好了以上就是本篇博客的全部內(nèi)容了,歡迎微信搜索關(guān)注【SH的全棧筆記】纽哥,回復(fù)【隊列】獲取MQ學(xué)習(xí)資料钠乏,包含基礎(chǔ)概念解析和RocketMQ詳細的源碼解析,持續(xù)更新中春塌。
如果你覺得這篇文章對你有幫助晓避,還麻煩點個贊,關(guān)個注摔笤,分個享够滑,留個言。