本篇博客會簡單的介紹Redis的Sentinel相關的原理,同時也會在最後的文章給出硬核的實戰教程,讓你在瞭解原理以後,可以實際上手的體驗整個過程。redis
以前的文章聊到了Redis的主從複製,聊到了其相關的原理和缺點,具體的建議能夠看看我以前寫的文章Redis的主從複製。docker
總的來講,爲了知足Redis在真正複雜的生產環境的高可用,僅僅是用主從複製是明顯不夠的。例如,當master節點宕機了以後,進行主從切換的時候,咱們須要人工的去作failover。bash
同時在流量方面,主從架構只能經過增長slave節點來擴展讀請求,寫能力因爲受到master單節點的資源限制是沒法進行擴展的。服務器
這也是爲何咱們須要引入Sentinel。微信
Sentinel其大體的功能以下圖。網絡
Sentinel是Redis高可用的解決方案之一,自己也是分佈式的架構,包含了多個Sentinel節點和多個Redis節點。而每一個Sentinel節點會對Redis節點和其他的Sentinel節點進行監控。數據結構
當其發現某個節點不可達時,若是是master節點就會與其他的Sentinel節點協商。當大多數的Sentinel節點都認爲master不可達時,就會選出一個Sentinel節點對master執行故障轉移,並通知Redis的調用方相關的變動。架構
相對於主從下的手動故障轉移,Sentinel的故障轉移是全自動的,無需人工介入。tcp
666,那我怎麼知道知足它自身的高可用須要部署多少個Sentinel節點?分佈式
由於Sentinel自己也是分佈式的,因此也須要部署多實例來保證自身集羣的高可用,可是這個數量是有個最低的要求,最低須要3個。
我去,你說3個就3個?我今天恰恰就只部署2個
你別槓...等我說了爲何就必需要3個...
由於哨兵執行故障轉移須要大部分的哨兵都贊成才行,若是隻有兩個哨兵實例,正常運做還好,就像這樣。
若是哨兵所在的那臺機器因爲機房斷電啊,光纖被挖啊等極端狀況整個掛掉了,那麼另外一臺哨兵即便發現了master故障以後想要執行故障轉移,可是它沒法獲得任何其他哨兵節點的贊成,此時也永遠沒法執行故障轉移,那Sentinel豈不是成了一個擺設?
因此咱們須要至少3個節點,來保證Sentinel集羣自身的高可用。固然,這三個Sentinel節點確定都推薦部署到不一樣的機器上,若是全部的Sentinel節點都部署到了同一臺機器上,那當這臺機器掛了,整個Sentinel也就不復存在了。
大部分?大哥這但是要上生產環境,大部分這個數量未免也太敷衍了,咱就不能專業一點?
前面提到的大部分
哨兵贊成涉及到兩個參數,一個叫quorum
,若是Sentinel集羣有quorum
個哨兵認爲master宕機了,就客觀的認爲master宕機了。另外一個叫majority
...
等等等等,不是已經有了一個叫什麼quorum的嗎?爲何還須要這個majority?
你能不能等我把話說完...
quorum
剛剛講過了,其做用是判斷master是否處於宕機的狀態,僅僅是一個判斷做用。而咱們在實際的生產中,不是說只判斷master宕機就完了, 咱們不還得執行故障轉移,讓集羣正常工做嗎?
同理,當哨兵集羣開始進行故障轉移時,若是有majority
個哨兵贊成進行故障轉移,纔可以最終選出一個哨兵節點,執行故障轉移操做。
你剛剛是否是提到了客觀宕機?笑死,難不成還有主觀宕機這一說?
Sentinel中認爲一個節點掛了有兩種類型:
當一個Sentinel節點與其監控的Redis節點A進行通訊時,發現鏈接不上,此時這個哨兵節點就會主觀的認爲這個Redis數據A節點sdown了。爲何是主觀?咱們得先知道什麼叫主觀
未經分析推算,下結論、決策和行爲反應,暫時不能與其餘不一樣見解的對象仔細商討,稱爲主觀。
簡單來講,由於有可能只是當前的Sentinel節點和這個A節點的網絡通訊有問題,其他的Sentinel節點仍然能夠和A正常的通訊。
這也是爲何咱們須要引入odown,當大於等於了quorum個Sentinel節點認爲某個節點宕機了,咱們就客觀的認爲這個節點宕機了。
當Sentinel集羣客觀的認爲master宕機,就會從全部的Sentinel節點中,選出一個Sentinel節點,來最終執行master的故障轉移。
那這個故障轉移具體要執行些什麼操做呢?咱們經過一個圖來看一下。
通知調用的客戶端master發生了變化
通知其他的原slave節點,去複製Sentinel選舉出來的新的master節點
若是此時原來的master又從新恢復了,Sentinel也會讓其去複製新的master節點。成爲一個新的slave節點。
硬核教程旨在用最快速的方法,讓你在本地體驗Redis主從架構和Sentinel集羣的搭建,並體驗整個故障轉移的過程。
首先須要準備一個目錄,而後分別創建兩個子目錄。以下。
$ tree . . ├── redis │ └── docker-compose.yml └── sentinel ├── docker-compose.yml ├── sentinel1.conf ├── sentinel2.conf └── sentinel3.conf 2 directories, 5 files
redis目錄下的docker-compose.yml
內容以下。
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節點去複製container_name爲redis-master的節點,這樣就組成了一個簡單的3個節點的主從架構
而後用命令行進入當前目錄,直接敲命令docker-compose up
便可,剩下的事情交給docker-compose去作就好,它會把咱們所須要的節點所有啓動起來。
此時咱們還須要拿到剛剛咱們啓動的master節點的IP,簡要步驟以下:
經過docker ps
找到對應的master節點的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
,拿到對應容器的IP,在NetworkSettings -> Networks -> IPAddress字段。
而後把這個值給記錄下來,此處個人值爲172.28.0.3
。
sentinel目錄下的docker-compose.yml
內容以下。
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 的模式啓動,本質上就是一個運行在特殊模式的 redis 服務器。
和 redis-server 的區別在於,他們分別載入了不一樣的命令表,sentinel 中沒法執行各類redis中特有的 set get操做。
創建三份如出一轍的文件,分別命名爲sentinel1.conf、sentinel2.conf和sentinel3.conf。其內容以下:
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
表示讓它去監聽名爲mymaster
的master節點,注意此處的IP必定要是你本身master節點的IP,而後最後面的2
就是咱們以前提到的quorum
。
而後命令行進入名爲sentinel的目錄下,敲docker-compose up
便可。至此,Sentinel集羣便啓動了起來。
而後咱們須要手動模擬master掛掉,來驗證咱們搭建的Sentinel集羣是否能夠正常的執行故障轉移。
命令行進入名爲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
得得得,你幹什麼就甩一堆日誌文件上來?湊字數?你這樣鬼能看懂?
的確,光從日誌文件一行一行的看,就算是我本身過兩週再來看,也是一臉懵逼。日誌文件完整了描述了整個Sentinel集羣從開始執行故障轉移到最終執行完成的全部細節,可是在這裏直接放出來不方便你們的理解。
因此爲了讓你們可以更加直觀的瞭解這個過程,我簡單的把過程抽象了成了一張圖,你們看圖結合日誌,應該可以更容易理解。
裏面關鍵的步驟步驟的相關解釋我也一併放入了圖片中。
最終的結果就是,master已經從咱們最開始的172.28.0.3
切換到了172.28.0.2
,後者則是原來的slave節點之一。此時咱們也能夠鏈接到172.28.0.2
這個容器裏去,經過命令來看一下其如今的狀況。
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
能夠看到,如今的172.28.0.2
這個節點的角色已經變成了master,與其相鏈接的slave節點只有1個,由於如今的原master尚未啓動起來,總共存活的只有2個實例。
接下來咱們模擬原master從新啓動,來看一下會發什麼什麼。
仍是經過命令行進入到名爲redis的本地目錄,經過docker-compose unpause master
來模擬原master故障恢復以後的上線。一樣咱們鏈接到原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
這個節點)的一個slave。
而後咱們也能夠經過再看一下新master節點的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,一樣與咱們開篇和圖中所講的原理相符合。
好了,以上就是本篇博客的所有內容
歡迎微信關注「SH的全棧筆記」,查看更多相關的文章
往期文章