參考鏈接:
https://cloud.tencent.com/developer/article/1474195
https://juejin.im/post/5d26b03de51d454fa33b1960
環境:
1、CentOS Linux release 7.6.1810 (Core)
2、三台主機:192.168.3.103、192.168.3.80、192.168.3.81
3、安裝好的docker:Docker version 19.03.4, build 9013bf583a
4、redis為最新版本(latest)
框架與思路:


啟動搭建容器主從
從docker官方公共倉庫拉取redis鏡像,然后修改redis服務的配置文件,最后啟動容器,啟動redis服務器。在多台機器上運行redis服務器,並建立主從關系。
redis的主從是實現redis集群和redis哨兵高可用的基礎,redis的主從結構使從可以復制主上的數據,如果從與主之間網絡斷開,從會自動重連到主上。
獲取最新redis鏡像
#docker pull redis
查看鏡像:
#docker image ls
注:三台機器都做上述操作
獲取並修改redis配置文件
redis官方提供了一個配置文件樣例,通過wget工具下載下來。我用的root用戶,就直接下載到/root目錄里了
注:無wget命令,需提前下載
#yum -y install wget
#wget http://download.redis.io/redis-stable/redis.conf
打開下載下來的文件后,可以看到配置有很多。我只是搭建服務進行試驗所以只修改必要的幾項。如果要運用到線上,那必須將所有配置都按需求進行修改。
其中redis服務器的master和slave角色使用的配置文件還會有些不同,下面分別進行說明。
對於master而言,配置文件修改以下幾項
# 注釋這一行,表示Redis可以接受任意ip的連接
# bind 127.0.0.1
# 關閉保護模式
protected-mode no
# 讓redis服務后台運行
daemonize yes
# 設定密碼(可選,如果這里開啟了密碼要求,slave的配置里就要加這個密碼. 只是練習配置,就不使用密碼認證了)
# requirepass masterpassword
# 配置日志路徑,為了便於排查問題,指定redis的日志文件目錄
logfile "/var/log/redis/redis.log"
對於slave而言,配置文件修改以下幾項:
# 注釋這一行,表示Redis可以接受任意ip的連接
# bind 127.0.0.1
# 關閉保護模式
protected-mode no
# 讓redis服務后台運行
daemonize yes
# 設定密碼(可選,如果這里開啟了密碼要求,slave的配置里就要加這個密碼)
requirepass masterpassword
# 設定主庫的密碼,用於認證,如果主庫開啟了requirepass選項這里就必須填相應的密碼
masterauth <master-password>
# 設定master的IP和端口號,redis配置文件中的默認端口號是6379
# 低版本的redis這里會是slaveof,意思是一樣的,因為slave是比較敏感的詞匯,所以在redis后面的版本中不在使用slave的概念,取而代之的是replica
# 將192.168.3.103作為主,其余兩台機器做從。ip和端口號按照機器和配置做相應修改。
replicaof 192.168.3.103 6379
# 配置日志路徑,為了便於排查問題,指定redis的日志文件目錄
logfile "/var/log/redis/redis.log"
啟動redis對應的容器
三台機器上分別將容器別名指定為
192.168.3.103 ------>redis_master
192.168.3.80 -------->redis_slave1
192.168.3.81 -------->redis_slave2
要注意master的配置文件和slave不同。不過首先要啟動主服務器,也就是r redis_master容器。
啟動redis_master
# docker run --name redis_master -v /redis/redis.conf:/usr/local/etc/redis/redis.conf -d -p 6379:6379 redis
# 通過ps命令查看容器的狀態,可以看到redis_master已經啟動
啟動redis_slave1
#docker run --name redis_slave1 -v /redis/redis.conf:/usr/local/etc/redis/redis.conf -d -p 6379:6379 redis
# 通過ps命令查看容器的狀態,可以看到redis_slave1已經啟動
啟動redis_slave2
# docker run --name redis_slave2 -v /redis/redis.conf:/usr/local/etc/redis/redis.conf -d -p 6379:6379 redis
# 通過ps命令查看容器的狀態,可以看到redis_slave2已經啟動
上面已經啟動了容器,接下來進入容器里啟動redis服務器
# 以交互模式進入容器redis_master
#docker exec -it redis_master
# 創建日志文件目錄
#mkdir -p /var/log/redis/
#touch /var/log/redis/redis.log
# 啟動redis服務器,如果沒有任何輸出,就說明成功了
#redis-server /usr/local/etc/redis/redis.conf
# 在容器里啟動一個redis客戶端
#redis-cli
# 執行info命令,查看服務器狀態
127.0.0.1:6379> info
...
# 如果是主,這里的role的值會是master,如果是從,這里的role的值會是slave
role:slave
# 對於slave,還要查看master_link_status這個屬性值。slave上這個屬性值為up就說明主從復制是OK的,否者就有問題。如果從機狀態不為up,首先排查主機的端口是否被限,然后查看redis日志排查原因
master_link_status:up
...
#最后退出容器
#exit
注:
另外兩台機器操作同上
設置redis主從關系
分別進入redis_slave1/ redis_slave2(兩者操作相同)
[root@localhost ~]# docker exec -it redis_slave1 bash
root@aa5bad0f8fea:/data# redis-cli
127.0.0.1:6379> SLAVEOF 192.168.3.103 6379
OK
查看確認:
在redis_master中輸入info查看
docker exec -it redis_master bash
redis-cli
info
在redis_slave1中輸入info查看
docker exec -it redis_slave1 bash
redis-cli
info
在redis_slave2中輸入info查看
docker exec -it redis_slave2 bash
redis-cli
info
驗證主從復制
主從搭建成功后,可以通過在master上寫入一個key-value值,查看是否會同步到slave上,來驗證主從同步是否能成功。
# 以交互模式進入容器redis_master中
#docker exec -it redis_master bash
運行一個redis-cli,向test_key寫入一個值
redis-cli
set test_key hello-world
OK
在任意slave機器上進入容器,也運行一個redis-cli,查詢這個key的值。如果能查詢到這個值,且與主機上的值相同,說明主從同步成功。經測試,主動同步成功。
添加哨兵
主從結構搭建成功了,系統的可用性變高了,但是如果主發生故障,需要人工手動切換從機為主機。這種切換工作不僅浪費人力資源,更大的影響是主從切換期間這段時間redis是無法對外提供服務的。因此,哨兵系統被開發出來了,哨兵可以在主發生故障后,自動進行故障轉移,從從機里選出一台升級為主機,並持續監聽着原來的主機,當原來的主機恢復后,會將其作為新主的從機。
哨兵先監聽主,通過對主發送info命令,獲取到從的信息,然后也會監聽到從。另外哨兵都會像主訂閱__sentinel__:hello頻道,當有新的哨兵加入時,會向這個頻道發送一條信息,這條信息包含了該哨兵的IP和端口等信息,那么其他已經訂閱了該頻道的哨兵就會收到這條信息,就知道有一個新的哨兵加入。這些哨兵會與新加入和哨兵建立連接,選主是需要通過這個連接來進行投票。這個關系可以用下面這個圖來描述
獲取並修改sentinel配置文件
通過wget命令獲取sentinel的配置文件
wget http://download.redis.io/redis-stable/sentinel.conf
修改配置文件以下幾項(三台機器的sentinel.conf的配置文件相同)
# 讓sentinel服務后台運行
daemonize yes
# 修改日志文件的路徑
logfile "/var/log/redis/sentinel.log"
# 修改監控的主redis服務器
# 最后一個2表示,兩台機器判定主被動下線后,就進行failover(故障轉移)
sentinel monitor mymaster 192.168.3.103 6379 2
啟動容器
與啟動redis容器類似,啟動一個別名為sentinel的容器
sentinel_master
docker run -it --name sentinel_master -p 26379:26379 -v /root/sentinel.conf:/usr/local/etc/redis/sentinel.conf -d redis
sentinel_slave1
docker run -it --name sentinel_slave1 -p 26379:26379 -v /root/sentinel.conf:/usr/local/etc/redis/sentinel.conf -d redis
sentinel_slave2
docker run -it --name sentinel_slave1 -p 26379:26379 -v /root/sentinel.conf:/usr/local/etc/redis/sentinel.conf -d redis
運行哨兵
# 進入容器
#docker exec -it sentinel_master bash
# 創建日志目錄和文件
# mkdir -p /var/log/redis
#touch /var/log/redis/sentinel.log
#啟動哨兵
redis-sentinel /usr/local/etc/redis/sentinel.conf
注:
在另外兩台機器上按照同樣的方法在一個容器中運行sentinel,sentinel都使用相同的配置文件。
驗證failover(故障轉移)
為了驗證哨兵機制下的自動主從切換,我們將主上的redis進程kill掉(或docker stop redis_master)。
稍等幾秒鍾后,就有另外一台從升級為主機,實驗時是第三台機器,也就是redis_slave2升級為了主,用info命令查詢可以看到redis_slave2服務器的角色變成的master。說明自動主從切換成功。
然后重新啟動之前被kill掉的master服務器,啟動后用info命令查看,可以發現其變成了redis_slave2的從服務器。
可以查看/var/log/redis/sentinel.log日志
總結
redis通過主從復制來實現高可用,但是發生故障時需要人工進行主從切換,效率低下。哨兵機制實現了redis主從的自動切換,提高了redis集群的可用性,提高了redis集群的故障轉移效率。
