前言
本小節我們學習使用Docker部署Redis集群(標準的一主兩從).
案例
目錄結構
- [root@iZ2ze8sm5upgi8z1dcazqeZ redis]# pwd
- /workspace/redis
- [root@iZ2ze8sm5upgi8z1dcazqeZ redis]# tree
- .
- ├── data
- │ ├── appendonly.aof
- │ ├── docker-compose.yml
- │ └── dump.rdb
- └── sentinel
- ├── config
- └── data
- 4 directories, 3 files
- [root@iZ2ze8sm5upgi8z1dcazqeZ redis]#
拉取redis鏡像
docker pull redis
- [root@iZ2ze8sm5upgi8z1dcazqeZ redis]# docker images
- REPOSITORY TAG IMAGE ID CREATED SIZE
- redis latest 01a52b3b5cd1 4 hours ago 98.2MB
編寫docker-compose.yml文件實現redis一主二從
<code>version: '3.7'/<code>
<code>services:/<code>
<code> master:/<code>
<code> image: redis/<code>
<code> container_name: redis-master/<code>
<code> restart: always/<code>
<code> command: redis-server --port 6379 --requirepass Dustyone --appendonly yes/<code>
<code> ports:/<code>
<code> - 6379:6379/<code>
<code> volumes:/<code>
<code> - /workspace/redis/data:/data/<code>
<code> slave1:/<code>
<code> image: redis/<code>
<code> container_name: redis-slave-1/<code>
<code> restart: always/<code>
<code> command: redis-server --slaveof 182.92.0.228 6379 --port 6380 --requirepass Dustyone --masterauth Dustyone --appendonly yes/<code>
<code> ports:/<code>
<code> - 6380:6380/<code>
<code> volumes:/<code>
<code> - /workspace/redis/data:/data/<code>
<code> slave2:/<code>
<code> image: redis/<code>
<code> container_name: redis-slave-2/<code>
<code> restart: always/<code>
<code> command: redis-server --slaveof 182.92.0.228 6379 --port 6381 --requirepass Dustyone --masterauth Dustyone --appendonly yes/<code>
<code> ports:/<code>
<code> - 6381:6381/<code>
<code> volumes:/<code>
<code> - /workspace/redis/data:/data/<code>
version docker文件的版本
image 指定容器鏡像就是之前拉取的redis鏡像
container_name 給這個鏡像起一個別名
restart always:表名開機自啟動
command 相當於執行一些命令 (–requirepass 指定redis密碼 --appendonly yes 這個命令是用於開啟redis數據持久化)
ports 端口映射,將容器的端口映射到對應宿主機的端口
volumes 數據卷的映射.因為一旦容器停止了那麼裡面的數據也沒有.所以我們需要把這個數據文件放在外面,然後映射到容器中
啟動redis,使用如下命令 -d 掛在後臺
- docker-compose up -d
查看redis是否啟動成功,使用如下命令,看到紅框中的三個並且狀態是 UP 則表明啟動redis成功
<code>[root@iZ2ze8sm5upgi8z1dcazqeZ redis]# docker ps -a/<code>
<code>CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES/<code>
<code>a43bcfd77e5a redis "docker-entrypoint.s…" 14 minutes ago Up 14 minutes 6379/tcp, 0.0.0.0:6380->6380/tcp redis-slave-1/<code>
<code>19b10ac59405 redis "docker-entrypoint.s…" 14 minutes ago Up 14 minutes 6379/tcp, 0.0.0.0:6381->6381/tcp redis-slave-2/<code>
<code>9acdc4bd4086 redis "docker-entrypoint.s…" 14 minutes ago Up 14 minutes 0.0.0.0:6379->6379/tcp redis-master/<code>
驗證redis是否實現了一主二從的功能
進入主redis容器中,使用如下命令
- docker exec -it redis-master bash
鏈接Redis Client並對主Redis操作
<code>[root@iZ2ze8sm5upgi8z1dcazqeZ redis]# docker exec -it redis-master bash/<code>
<code>root@9acdc4bd4086:/data# redis-cli/<code>
<code>127.0.0.1:6379> auth Dustyone/<code>
<code>OK/<code>
<code>127.0.0.1:6379> set sales Dustyone/<code>
<code>OK/<code>
<code>127.0.0.1:6379> get sales/<code>
<code>"Dustyone"/<code>
<code>127.0.0.1:6379>/<code>
進入任意從Redis並驗證數據是否同步
ctrl+c退出redis,輸入exit如下命令退出容器。
<code>[root@iZ2ze8sm5upgi8z1dcazqeZ redis]# docker exec -it redis-slave-1 bash/<code>
<code>root@a43bcfd77e5a:/data# redis-cli -p 6380/<code>
<code>127.0.0.1:6380> auth Dustyone/<code>
<code>OK/<code>
<code>127.0.0.1:6380> keys */<code>
<code>1) "broker"/<code>
<code>2) "sales"/<code>
<code>127.0.0.1:6380> get slave/<code>
<code>(nil)/<code>
<code>127.0.0.1:6380> get sales/<code>
<code>"Dustyone"/<code>
<code>127.0.0.1:6380> set sales Aron/<code>
<code>(error) READONLY You can't write against a read only replica./<code>
<code>127.0.0.1:6380> /<code>
如上命令中我們嘗試了在從Redis上做set操作,結果提示從Redis只有讀的操作。
如此我們便驗證完畢了。
小結
如果使用失敗了,可以使用如下命令查看日誌,觀察是什麼原因造成的
docker logs -f 容器Id
停止redis,使用如下命令
<code>docker-compose down/<code>
<code>docker stop 容器Id/<code>
<code>docker rm 容器Id/<code>
停止並移除所有容器可以使用如下命令
<code>docker stop $(docker ps -a -q)/<code>
<code>docker rm $(docker ps -a -q)/<code>
啟動redis
<code>docker-compose up -d/<code>
比如我們的主從部署在182.92.0.228的6379/6380/6381上,該ECS實例的安全組規則必須開放6379-6381
- 本小節案例中是將Redis集群部署在同一服務器上的,如若需要將主從Redis部署在不同服務器上,按照本案例提供的思路,將各個配置項中的IP地址替換成相應的IP地址即可。
本小節我們學習一下使用Dokcer部署Redis集群之後為確保Redis HA性能實現Sentinel模式。
如何使用Docker部署Redis集群。
案例
參照前文,假設你已經成功部署了Redis集群。
目錄參考
- [root@iZ2ze8sm5upgi8z1dcazqeZ redis]# tree
- .
- ├── data
- │ ├── appendonly.aof
- │ ├── docker-compose.yml
- │ └── dump.rdb
- └── sentinel
- ├── config
- │ ├── docker-compose.yml
- │ ├── sentinel1.conf
- │ ├── sentinel2.conf
- │ ├── sentinel3.conf
- │ └── sentinel.conf
- └── data
- 4 directories, 8 files
- [root@iZ2ze8sm5upgi8z1dcazqeZ redis]#
在中workspace/redis/sentinel/config編寫sentinel.conf文件
port 26379
<code>dir /workspace/redis/sentinel/config/<code>
<code># 自定義集群名,其中 182.92.0.228 為 redis-master 的 ip,6379 為 redis-master 的端口,2 為最小投票數(因為有 3 臺 Sentinel 所以可以設置成 2)/<code>
<code>sentinel monitor redis-master 182.92.0.228 6379 2/<code>
<code>sentinel down-after-milliseconds redis-master 30000/<code>
<code>sentinel parallel-syncs redis-master 1/<code>
<code>sentinel auth-pass redis-master Dustyone/<code>
<code>sentinel failover-timeout redis-master 180000/<code>
<code>sentinel deny-scripts-reconfig yes/<code>
將sentinel.conf複製三份,複製文件與sentinel.conf同路徑
- cp sentinel.conf sentinel1.conf
- cp sentinel.conf sentinel2.conf
- cp sentinel.conf sentinel3.conf
編寫docker-composr.yml
<code>version: '3.7'/<code>
<code>services:/<code>
<code> sentinel1:/<code>
<code> image: redis/<code>
<code> container_name: redis-sentinel-1/<code>
<code> command: redis-sentinel /workspace/redis/sentinel/config/sentinel.conf/<code>
<code> restart: always/<code>
<code> ports:/<code>
<code> - 26379:26379/<code>
<code> volumes:/<code>
<code> - /workspace/redis/sentinel/config/sentinel1.conf:/workspace/redis/sentinel/config/sentinel.conf/<code>
<code> sentinel2:/<code>
<code> image: redis/<code>
<code> container_name: redis-sentinel-2/<code>
<code> command: redis-sentinel /workspace/redis/sentinel/config/sentinel.conf/<code>
<code> restart: always/<code>
<code> ports:/<code>
<code> - 26380:26380/<code>
<code> volumes:/<code>
<code> - /workspace/redis/sentinel/config/sentinel2.conf:/workspace/redis/sentinel/config/sentinel.conf/<code>
<code> sentinel3:/<code>
<code> image: redis/<code>
<code> container_name: redis-sentinel-3/<code>
<code> command: redis-sentinel /workspace/redis/sentinel/config/sentinel.conf/<code>
<code> restart: always/<code>
<code> ports:/<code>
<code> - 26381:26381/<code>
<code> volumes:/<code>
<code> - /workspace/redis/sentinel/config/sentinel3.conf:/workspace/redis/sentinel/config/sentinel.conf/<code>
在/workspace/redis/sentinel/config啟動docker-compose.yml
- docker-compose up -d
查看redis-sentinel是否啟動成功
- [root@iZ2ze8sm5upgi8z1dcazqeZ config]# docker ps -a
- CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
- 72eb47246eec redis "docker-entrypoint.s…" 6 minutes ago Up 6 minutes 6379/tcp, 0.0.0.0:26380->26380/tcp redis-sentinel-2
- c68c5d3c1ecf redis "docker-entrypoint.s…" 6 minutes ago Up 6 minutes 6379/tcp, 0.0.0.0:26381->26381/tcp redis-sentinel-3
- a5df697f45bd redis "docker-entrypoint.s…" 6 minutes ago Up 6 minutes 6379/tcp, 0.0.0.0:26379->26379/tcp redis-sentinel-1
- a43bcfd77e5a redis "docker-entrypoint.s…" 2 hours ago Up 2 hours 6379/tcp, 0.0.0.0:6380->6380/tcp redis-slave-1
- 19b10ac59405 redis "docker-entrypoint.s…" 2 hours ago Up 2 hours 6379/tcp, 0.0.0.0:6381->6381/tcp redis-slave-2
- 9acdc4bd4086 redis "docker-entrypoint.s…" 2 hours ago Up 16 minutes 0.0.0.0:6379->6379/tcp redis-master
進入redis-sentinel容器中,查看主redis連接狀態
[root@iZ2ze8sm5upgi8z1dcazqeZ config]# docker exec -it redis-sentinel-1 bash
root@a5df697f45bd:/data# redis-cli -p 26379
127.0.0.1:26379> sentinel master redis-master
1) "name"
2) "redis-master"
3) "ip"
4) "182.92.0.228"
5) "port"
6) "6380"
7) "runid"
8) "4ab8f3fb673651053d3750dd8a72d98f1bc872c1"
9) "flags"
10) "master"
11) "link-pending-commands"
12) "0"
13) "link-refcount"
14) "1"
15) "last-ping-sent"
16) "0"
17) "last-ok-ping-reply"
18) "858"
19) "last-ping-reply"
20) "858"
21) "down-after-milliseconds"
22) "30000"
23) "info-refresh"
24) "8224"
25) "role-reported"
26) "master"
27) "role-reported-time"
28) "520683"
29) "config-epoch"
30) "1"
31) "num-slaves"
32) "2"
33) "num-other-sentinels"
34) "2"
35) "quorum"
36) "2"
37) "failover-timeout"
38) "180000"
39) "parallel-syncs"
40) "1"
127.0.0.1:26379>
查看從redis信息是否正常
127.0.0.1:26379> sentinel slaves redis-master
1) 1) "name"
2) "182.92.0.228:6381"
3) "ip"
4) "182.92.0.228"
5) "port"
6) "6381"
7) "runid"
8) "54c6883557cc0cbb28e521997bb1b25ddd2908d9"
9) "flags"
10) "slave"
11) "link-pending-commands"
12) "0"
13) "link-refcount"
14) "1"
15) "last-ping-sent"
16) "0"
17) "last-ok-ping-reply"
18) "789"
19) "last-ping-reply"
20) "789"
21) "down-after-milliseconds"
22) "30000"
23) "info-refresh"
24) "1724"
25) "role-reported"
26) "slave"
27) "role-reported-time"
28) "644775"
29) "master-link-down-time"
30) "0"
31) "master-link-status"
32) "ok"
33) "master-host"
34) "182.92.0.228"
35) "master-port"
36) "6380"
37) "slave-priority"
38) "100"
39) "slave-repl-offset"
40) "432646"
2) 1) "name"
2) "182.92.0.228:6379"
3) "ip"
4) "182.92.0.228"
5) "port"
6) "6379"
7) "runid"
8) "e286d7fa7661b9c9cf4c984ee36ddb69a21ccc5b"
9) "flags"
10) "slave"
11) "link-pending-commands"
12) "0"
13) "link-refcount"
14) "1"
15) "last-ping-sent"
16) "0"
17) "last-ok-ping-reply"
18) "623"
19) "last-ping-reply"
20) "623"
21) "down-after-milliseconds"
22) "30000"
23) "info-refresh"
24) "623"
25) "role-reported"
26) "slave"
27) "role-reported-time"
28) "644775"
29) "master-link-down-time"
30) "1569469175000"
31) "master-link-status"
32) "err"
33) "master-host"
34) "182.92.0.228"
35) "master-port"
36) "6380"
37) "slave-priority"
38) "100"
39) "slave-repl-offset"
40) "1"
127.0.0.1:26379>
測試主redis掛了之後,哨兵能否正常選舉redis
停掉主redis
docker stop redis-master
查看redis-sentinel日誌,看其將那個redis選舉為主
<code>[root@iZ2ze8sm5upgi8z1dcazqeZ config]# docker logs redis-sentinel-2/<code>
<code>1:X 26 Sep 2019 03:28:51.588 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo/<code>
<code>1:X 26 Sep 2019 03:28:51.588 # Redis version=5.0.6, bits=64, commit=00000000, modified=0, pid=1, just started/<code>
<code>1:X 26 Sep 2019 03:28:51.588 # Configuration loaded/<code>
<code>1:X 26 Sep 2019 03:28:51.590 * Running mode=sentinel, port=26379./<code>
<code>1:X 26 Sep 2019 03:28:51.590 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128./<code>
<code>1:X 26 Sep 2019 03:28:51.590 # Sentinel ID is 02dd0257960310b300feef92f56d484f55df4b44/<code>
<code>1:X 26 Sep 2019 03:28:51.590 # +monitor master redis-master 182.92.0.228 6380 quorum 2/<code>
<code>1:X 26 Sep 2019 03:28:53.707 * +sentinel-address-switch master redis-master 182.92.0.228 6380 ip 172.26.0.4 port 26379 for e41d3841f9c208262b8564d1678050b8e8fb2e06/<code>
<code>1:X 26 Sep 2019 03:28:53.738 * +sentinel-address-switch master redis-master 182.92.0.228 6380 ip 172.26.0.3 port 26379 for 8be5d0ebdebe9b14139ac7db9b4d9d97f613e3e2/<code>
<code>1:X 26 Sep 2019 03:43:50.239 # +sdown slave 182.92.0.228:6379 182.92.0.228 6379 @ redis-master 182.92.0.228 6380/<code>
<code>[root@iZ2ze8sm5upgi8z1dcazqeZ config]# /<code>
如上可知,6380上的Redis被選舉為主Redis了。
測試端口號為6380的redis是否具備寫功能,如下則表明成功
<code>[root@iZ2ze8sm5upgi8z1dcazqeZ config]# docker exec -it redis-slave-1 bash/<code>
<code>root@a43bcfd77e5a:/data# redis-cli -p 6380/<code>
<code>127.0.0.1:6380> auth Dustyone/<code>
<code>OK/<code>
<code>127.0.0.1:6380> keys */<code>
<code>1) "reob"/<code>
<code>2) "broker"/<code>
<code>3) "sales"/<code>
<code>127.0.0.1:6380> set buyers Duyb/<code>
<code>OK/<code>
<code>127.0.0.1:6380> keys */<code>
<code>1) "reob"/<code>
<code>2) "broker"/<code>
<code>3) "buyers"/<code>
<code>4) "sales"/<code>
<code>127.0.0.1:6380> get buyers/<code>
<code>"Duyb"/<code>
<code>127.0.0.1:6380> /<code>
如上便檢驗成功了
小節
本案例實現為單機版集群,如若主從不在同一服務器上,請設置合理的主從之間的心跳檢測時間
場景:本案例中將6379的Redis設置成主Redis,當主Redis掛了之後在重新加入集群時,不再是Master角色了。
開發的安全組
閱讀更多 java程序員工程師 的文章