Redis哨兵集群原理講解和Docker-compose安裝Redis哨兵集群
今日目標(biāo)
- 掌握Docker-compose安裝Redis哨兵集群
單節(jié)點(diǎn)Redis的并發(fā)能力是有上限的,要進(jìn)一步提高Redis的并發(fā)能力,就需要搭建主從集群,實(shí)現(xiàn)讀寫(xiě)分離
- 主節(jié)點(diǎn): 可以對(duì)Redis實(shí)現(xiàn)讀寫(xiě)操作
- 從節(jié)點(diǎn): 只可以對(duì)Redis實(shí)現(xiàn)讀操作
但是,當(dāng)master節(jié)點(diǎn)宕機(jī)后,我們就不能寫(xiě)數(shù)據(jù)到Redis,所以需要搭建一個(gè)三節(jié)點(diǎn)形成的Sentinel集群,來(lái)監(jiān)管之前的Redis主從集群
1.Redis哨兵
Redis提供了哨兵(Sentinel)機(jī)制來(lái)實(shí)現(xiàn)主從集群的自動(dòng)故障恢復(fù)。
哨兵的結(jié)構(gòu)如圖:
圖片
共包含6個(gè)節(jié)點(diǎn),一個(gè)主兩個(gè)從和三個(gè)哨兵。這里我們會(huì)在同一臺(tái)虛擬機(jī)中開(kāi)啟6個(gè)redis實(shí)例,模擬主從集群,信息如下:
IP | PORT | 角色 |
192.168.150.102 | 6380 | master |
192.168.150.102 | 6381 | slave |
192.168.150.102 | 6382 | slave |
192.168.150.102 | 26379 | sentinel |
192.168.150.102 | 26380 | sentinel |
192.168.150.102 | 26381 | sentinel |
哨兵的作用如下:
- 監(jiān)控:Sentinel 會(huì)不斷檢查您的master和slave是否按預(yù)期工作
- 自動(dòng)故障恢復(fù):如果master故障Sentinel會(huì)將一個(gè)slave提升為master。當(dāng)故障實(shí)例恢復(fù)后也以新的master為主
- 通知:Sentinel充當(dāng)Redis客戶(hù)端的服務(wù)發(fā)現(xiàn)來(lái)源,當(dāng)集群發(fā)生故障轉(zhuǎn)移時(shí)會(huì)將最新信息推送給Redis的客戶(hù)端
2. 準(zhǔn)備實(shí)例和配置
要在同一臺(tái)虛擬機(jī)開(kāi)啟6個(gè)實(shí)例,必須準(zhǔn)備6份不同的配置文件和目錄,配置文件所在目錄也就是工作目錄。 確保下面的配置已經(jīng)更改(位置也別錯(cuò))
# master
mkdir -p /redis-master-slave-sentinel/redis/master/config /redis-master-slave-sentinel/redis/master/data
cd /redis-master-slave-sentinel/redis/master/config
curl -O -L http://download.redis.io/releases/redis-6.0.20.tar.gz
tar -zxvf redis-6.0.20.tar.gz
cp /redis-master-slave-sentinel/redis/master/config/redis-6.0.20/redis.conf /redis-master-slave-sentinel/redis/master/config/redis.conf
sed -i 's/bind 127.0.0.1/bind 0.0.0.0/' /redis-master-slave-sentinel/redis/master/config/redis.conf
# slave-1
mkdir -p /redis-master-slave-sentinel/redis/slave-1/config /redis-master-slave-sentinel/redis/slave-1/data
cd /redis-master-slave-sentinel/redis/slave-1/config/
cp /redis-master-slave-sentinel/redis/master/config/redis-6.0.20/redis.conf /redis-master-slave-sentinel/redis/slave-1/config/redis.conf
sed -i 's/bind 127.0.0.1/bind 0.0.0.0/' /redis-master-slave-sentinel/redis/slave-1/config/redis.conf
# slave-2
mkdir -p /redis-master-slave-sentinel/redis/slave-2/config /redis-master-slave-sentinel/redis/slave-2/data
cd /redis-master-slave-sentinel/redis/slave-2/config/
cp /redis-master-slave-sentinel/redis/master/config/redis-6.0.20/redis.conf /redis-master-slave-sentinel/redis/slave-2/config/redis.conf
sed -i 's/bind 127.0.0.1/bind 0.0.0.0/' /redis-master-slave-sentinel/redis/slave-2/config/redis.conf
#redis-sentinel-1
mkdir -p /redis-master-slave-sentinel/sentinel/redis-sentinel-1 /redis-master-slave-sentinel/sentinel/redis-sentinel-1/s1
cd /redis-master-slave-sentinel/sentinel/redis-sentinel-1
cat >> /redis-master-slave-sentinel/sentinel/redis-sentinel-1/sentinel.conf <<EOF
# 配置可參考 http://download.redis.io/redis-stable/sentinel.conf
# 配置說(shuō)明 https://redis.io/topics/sentinel
port 26379
dir /tmp
sentinel monitor mymaster 192.168.150.102 6380 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel auth-pass mymaster 123456
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes
EOF
#redis-sentinel-2
mkdir -p /redis-master-slave-sentinel/sentinel/redis-sentinel-2 /redis-master-slave-sentinel/sentinel/redis-sentinel-2/s2
cd /redis-master-slave-sentinel/sentinel/redis-sentinel-2
cat >> /redis-master-slave-sentinel/sentinel/redis-sentinel-2/sentinel.conf <<EOF
# 配置可參考 http://download.redis.io/redis-stable/sentinel.conf
# 配置說(shuō)明 https://redis.io/topics/sentinel
port 26379
dir /tmp
sentinel monitor mymaster 192.168.150.102 6380 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel auth-pass mymaster 123456
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes
EOF
#redis-sentinel-3
mkdir -p /redis-master-slave-sentinel/sentinel/redis-sentinel-3 /redis-master-slave-sentinel/sentinel/redis-sentinel-3/s3
cd /redis-master-slave-sentinel/sentinel/redis-sentinel-3
cat >> /redis-master-slave-sentinel/sentinel/redis-sentinel-3/sentinel.conf <<EOF
# 配置可參考 http://download.redis.io/redis-stable/sentinel.conf
# 配置說(shuō)明 https://redis.io/topics/sentinel
port 26379
dir /tmp
sentinel monitor mymaster 192.168.150.102 6380 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel auth-pass mymaster 123456
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes
EOF
sentinel.conf說(shuō)明
port 26379
dir /tmp
sentinel monitor mymaster 192.168.150.102 6380 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel auth-pass mymaster 123456
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes
sentinel.conf解讀
- port 26379:是當(dāng)前sentinel實(shí)例的端口
- sentinel monitor mymaster 192.168.150.102 6380 2:指定主節(jié)點(diǎn)信息 ○ mymaster:主節(jié)點(diǎn)名稱(chēng),自定義,任意寫(xiě) ○ 192.168.150.102 6380:主節(jié)點(diǎn)的ip和端口 ○ 2:選舉master時(shí)的quorum值
- sentinel auth-pass mymaster 123456 :訪問(wèn)主節(jié)點(diǎn)時(shí)的密碼
如果您覺(jué)得本文不錯(cuò),歡迎關(guān)注,點(diǎn)贊,收藏支持,您的關(guān)注是我堅(jiān)持的動(dòng)力!
3. docker-compose-redis-master-slave-sentinel.yml文件的編寫(xiě)
創(chuàng)建名稱(chēng)為docker-compose-redis-master-slave-sentinel.yml用于安裝Redis哨兵集群docker-compose文件
version: '3'
# 網(wǎng)橋redis -> 方便相互通訊
networks:
redis:
services:
# ============================ ↓↓↓↓↓↓ redis ↓↓↓↓↓↓ ============================
# 主
redis-master:
image: redis:6.0.20 # 鏡像'redis:6.0.20'
container_name: redis-master # 容器名為'redis-master'
restart: unless-stopped # 指定容器退出后的重啟策略為始終重啟,但是不考慮在Docker守護(hù)進(jìn)程啟動(dòng)時(shí)就已經(jīng)停止了的容器
command: redis-server /etc/redis/redis.conf --port 6380 --requirepass 123456 --masterauth 123456 --appendonly no # 啟動(dòng)redis服務(wù)并添加密碼為:123456, 當(dāng)主redis下線重啟后變成從redis時(shí)認(rèn)證主redis密碼:123456, 默認(rèn)不開(kāi)啟redis-aof方式持久化配置
environment: # 設(shè)置環(huán)境變量,相當(dāng)于docker run命令中的-e
TZ: Asia/Shanghai
LANG: en_US.UTF-8
volumes: # 數(shù)據(jù)卷掛載路徑設(shè)置,將本機(jī)目錄映射到容器目錄
- "/redis-master-slave-sentinel/redis/master/data:/data"
- "/redis-master-slave-sentinel/redis/master/config/redis.conf:/etc/redis/redis.conf" # `redis.conf`文件內(nèi)容`http://download.redis.io/redis-stable/redis.conf`
ports: # 映射端口
- "6380:6380"
# 從1
redis-slave-1:
image: redis:6.0.20 # 鏡像'redis:6.0.20'
container_name: redis-slave-1 # 容器名為'redis-slave-1'
restart: unless-stopped # 指定容器退出后的重啟策略為始終重啟,但是不考慮在Docker守護(hù)進(jìn)程啟動(dòng)時(shí)就已經(jīng)停止了的容器
command: redis-server /etc/redis/redis.conf --port 6381 --requirepass 123456 --appendonly no --slaveof 192.168.150.102 6380 --masterauth 123456 # 啟動(dòng)redis服務(wù)并添加密碼為:123456,默認(rèn)不開(kāi)啟redis-aof方式持久化配置,連接并認(rèn)證master節(jié)點(diǎn)
environment: # 設(shè)置環(huán)境變量,相當(dāng)于docker run命令中的-e
TZ: Asia/Shanghai
LANG: en_US.UTF-8
volumes: # 數(shù)據(jù)卷掛載路徑設(shè)置,將本機(jī)目錄映射到容器目錄
- "/redis-master-slave-sentinel/redis/slave-1/data:/data"
- "/redis-master-slave-sentinel/redis/slave-1/config/redis.conf:/etc/redis/redis.conf" # `redis.conf`文件內(nèi)容`http://download.redis.io/redis-stable/redis.conf`
ports: # 映射端口
- "6381:6381"
depends_on:
- redis-master
links:
- redis-master
# 從2
redis-slave-2:
image: redis:6.0.20 # 鏡像'redis:6.0.20'
container_name: redis-slave-2 # 容器名為'redis-slave-2'
restart: unless-stopped # 指定容器退出后的重啟策略為始終重啟,但是不考慮在Docker守護(hù)進(jìn)程啟動(dòng)時(shí)就已經(jīng)停止了的容器
command: redis-server /etc/redis/redis.conf --port 6382 --requirepass 123456 --appendonly no --slaveof 192.168.150.102 6380 --masterauth 123456 # 啟動(dòng)redis服務(wù)并添加密碼為:123456,默認(rèn)不開(kāi)啟redis-aof方式持久化配置,連接并認(rèn)證master節(jié)點(diǎn)
environment: # 設(shè)置環(huán)境變量,相當(dāng)于docker run命令中的-e
TZ: Asia/Shanghai
LANG: en_US.UTF-8
volumes: # 數(shù)據(jù)卷掛載路徑設(shè)置,將本機(jī)目錄映射到容器目錄
- "/redis-master-slave-sentinel/redis/slave-2/data:/data"
- "/redis-master-slave-sentinel/redis/slave-2/config/redis.conf:/etc/redis/redis.conf" # `redis.conf`文件內(nèi)容`http://download.redis.io/redis-stable/redis.conf`
ports: # 映射端口
- "6382:6382"
depends_on:
- redis-master
links:
- redis-master
# ============================ ↓↓↓↓↓↓ sentinel ↓↓↓↓↓↓ ============================
redis-sentinel-1:
image: redis:6.0.20 # 鏡像'redis:6.0.20'
container_name: redis-sentinel-1 # 容器名為'redis-sentinel-1'
restart: unless-stopped # 指定容器退出后的重啟策略為始終重啟,但是不考慮在Docker守護(hù)進(jìn)程啟動(dòng)時(shí)就已經(jīng)停止了的容器
command: redis-sentinel /etc/redis/sentinel.conf
environment: # 設(shè)置環(huán)境變量,相當(dāng)于docker run命令中的-e
TZ: Asia/Shanghai
LANG: en_US.UTF-8
ports:
- "26379:26379"
volumes:
- "/redis-master-slave-sentinel/sentinel/redis-sentinel-1/sentinel.conf:/etc/redis/sentinel.conf" # `sentinel.conf`文件內(nèi)容`http://download.redis.io/redis-stable/sentinel.conf`
depends_on:
- redis-master
- redis-slave-1
- redis-slave-2
links:
- redis-master
- redis-slave-1
- redis-slave-2
redis-sentinel-2:
image: redis:6.0.20 # 鏡像'redis:6.0.20'
container_name: redis-sentinel-2 # 容器名為'redis-sentinel-2'
restart: unless-stopped # 指定容器退出后的重啟策略為始終重啟,但是不考慮在Docker守護(hù)進(jìn)程啟動(dòng)時(shí)就已經(jīng)停止了的容器
command: redis-sentinel /etc/redis/sentinel.conf
environment: # 設(shè)置環(huán)境變量,相當(dāng)于docker run命令中的-e
TZ: Asia/Shanghai
LANG: en_US.UTF-8
ports:
- "26380:26379"
volumes:
- "/redis-master-slave-sentinel/sentinel/redis-sentinel-2/sentinel.conf:/etc/redis/sentinel.conf" # `sentinel.conf`文件內(nèi)容`http://download.redis.io/redis-stable/sentinel.conf`
depends_on:
- redis-master
- redis-slave-1
- redis-slave-2
- redis-sentinel-1
links:
- redis-master
- redis-slave-1
- redis-slave-2
redis-sentinel-3:
image: redis:6.0.20 # 鏡像'redis:6.0.20'
container_name: redis-sentinel-3 # 容器名為'redis-sentinel-3'
restart: unless-stopped # 指定容器退出后的重啟策略為始終重啟,但是不考慮在Docker守護(hù)進(jìn)程啟動(dòng)時(shí)就已經(jīng)停止了的容器
command: redis-sentinel /etc/redis/sentinel.conf
environment: # 設(shè)置環(huán)境變量,相當(dāng)于docker run命令中的-e
TZ: Asia/Shanghai
LANG: en_US.UTF-8
ports:
- "26381:26379"
volumes:
- "/redis-master-slave-sentinel/sentinel/redis-sentinel-3/sentinel.conf:/etc/redis/sentinel.conf" # `sentinel.conf`文件內(nèi)容`http://download.redis.io/redis-stable/sentinel.conf`
depends_on:
- redis-master
- redis-slave-1
- redis-slave-2
- redis-sentinel-1
- redis-sentinel-2
links:
- redis-master
- redis-slave-1
- redis-slave-2
3.1. 運(yùn)行 -- 哨兵模式(sentinel監(jiān)視r(shí)edis主從服務(wù)
運(yùn)行 -- 哨兵模式(sentinel監(jiān)視r(shí)edis主從服務(wù),當(dāng)某個(gè)master服務(wù)下線時(shí),自動(dòng)將該master下的某個(gè)從服務(wù)升級(jí)為master服務(wù)替代已下線的master服務(wù)繼續(xù)處理請(qǐng)求 -- 即主節(jié)點(diǎn)切換)
docker-compose -f docker-compose-redis-master-slave-sentinel.yml -p redis up -d
圖片
3.2 測(cè)試
- 1.哨兵模式查看
# 連接redis-sentinel-1
docker exec -it redis-sentinel-1 redis-cli -p 26379
- 2.查看redis主信息
sentinel master mymaster
圖片
- 查看redis從信息
sentinel slaves mymaster
圖片
- 4.查看 哨兵redis-sentinel-1日志
docker logs -f redis-sentinel-1
圖片
- 進(jìn)入redis-slave-1容器
docker exec -it redis-master redis-cli -h 192.168.150.102 -p 6381 -a 123456
圖片
- 關(guān)閉redis-master主節(jié)點(diǎn)
docker stop redis-master
發(fā)現(xiàn)主節(jié)點(diǎn)從master節(jié)點(diǎn),轉(zhuǎn)換為slave-2節(jié)點(diǎn)
圖片
- 進(jìn)入redis-slave-2容器
docker exec -it redis-master redis-cli -h 192.168.150.102 -p 6382 -a 123456
- 7.查看集群狀態(tài)
info replication
發(fā)現(xiàn)現(xiàn)在從節(jié)點(diǎn)只剩一個(gè)
圖片
- 8.重啟master節(jié)點(diǎn)
docker start redis-master
圖片
- 9.再次查看集群狀態(tài)
info replication
發(fā)現(xiàn)master節(jié)點(diǎn)添加回來(lái)了,但是變成了從節(jié)點(diǎn)
圖片
3.3. 卸載哨兵集群
docker-compose -f docker-compose-redis-master-slave-sentinel.yml -p redis down
3.4. 集群故障恢復(fù)原理
哨兵master自己從當(dāng)前集群中的slave節(jié)點(diǎn)中選出一個(gè)新的master,原則是
- 1-首先會(huì)判斷slave節(jié)點(diǎn)與master節(jié)點(diǎn)斷開(kāi)時(shí)間長(zhǎng)短,如果超過(guò)指定值(down-after-milliseconds * 10)則會(huì)排除該slave節(jié)點(diǎn)
- 2-然后判斷slave節(jié)點(diǎn)的slave-priority值,越小優(yōu)先級(jí)越高,如果是0則永不參與選舉
- 3-如果slave-prority一樣,則判斷slave節(jié)點(diǎn)的offset值,越大說(shuō)明數(shù)據(jù)越新,優(yōu)先級(jí)越高
- 4-最后是判斷slave節(jié)點(diǎn)的運(yùn)行id大小,越小優(yōu)先級(jí)越高。
3.5. 哨兵集群監(jiān)控原理
Sentinel基于心跳機(jī)制監(jiān)測(cè)服務(wù)狀態(tài),每隔1秒向集群的每個(gè)實(shí)例發(fā)送ping命令:
- 主觀下線:如果某sentinel節(jié)點(diǎn)發(fā)現(xiàn)某實(shí)例未在規(guī)定時(shí)間響應(yīng),則認(rèn)為該實(shí)例主觀下線。
- 客觀下線:若超過(guò)指定數(shù)量(quorum)的sentinel都認(rèn)為該實(shí)例主觀下線,則該實(shí)例客觀下線。quorum值最好超過(guò)Sentinel實(shí)例數(shù)量的一半。
圖片
總結(jié)
Sentinel的三個(gè)作用是什么
- 監(jiān)控
- 故障轉(zhuǎn)移
- 通知
Sentinel如何判斷一個(gè)redis實(shí)例是否健康
- 每隔1秒發(fā)送一次ping命令,如果超過(guò)一定時(shí)間沒(méi)有相向則認(rèn)為是主觀下線
- 如果大多數(shù)sentinel都認(rèn)為實(shí)例主觀下線,則判定服務(wù)下線