1.概述

在Docker中搭建Redis集群模式非常方便,下面是一个示例,演示一下如何使用Docker Compose搭建一个Redis集群环境。首先,确保我们本地环境已经安装了Docker和Docker Compose。

示例代码地址

2.搭建集群模式

2.1.创建文件夹

1
2
3
4
5
6
7
8
mkdir -p redis-cluster/.data
mkdir -p redis-cluster/scripts
mkdir -p redis-cluster/conf/redis-cluster-node1
mkdir -p redis-cluster/conf/redis-cluster-node2
mkdir -p redis-cluster/conf/redis-cluster-node3
mkdir -p redis-cluster/conf/redis-cluster-node4
mkdir -p redis-cluster/conf/redis-cluster-node5
mkdir -p redis-cluster/conf/redis-cluster-node6

2.2.创建配置文件

给出的样例仅仅用于windows wsl docker本地测试,不具有正式环境部署参考价值

2.2.1.redis-cluster-node1/redis.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
bind 0.0.0.0
# loglevel debug
logfile "/data/redis-cluster-node1.log"
save 3600 1
save 300 100
save 60 10000
stop-writes-on-bgsave-error no
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
rdb-del-sync-files no
dir /data/
requirepass 123456
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble yes
masterauth 123456
# 这里不开启的话,slave不一定能同步成功。windows wsl docker必须这样设置
repl-diskless-load on-empty-db

port 6379
# 启动集群模式
cluster-enabled yes
# 配置文件名称(redis-cluster-node1.conf ~ redis-cluster-node6.conf)
cluster-config-file redis-cluster-node1.conf
# 节点超时时间
cluster-node-timeout 5000
# 当前节点ip
cluster-announce-ip 172.202.0.2
# 当前节点端口
cluster-announce-port 6379
# 集群之间通信的端口号
cluster-announce-bus-port 16379

2.2.2.redis-cluster-node2/redis.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
bind 0.0.0.0
# loglevel debug
logfile "/data/redis-cluster-node2.log"
save 3600 1
save 300 100
save 60 10000
stop-writes-on-bgsave-error no
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
rdb-del-sync-files no
dir /data/
requirepass 123456
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble yes
masterauth 123456
# 这里不开启的话,slave不一定能同步成功。windows wsl docker必须这样设置
repl-diskless-load on-empty-db

port 6380
# 启动集群模式
cluster-enabled yes
# 配置文件名称(redis-cluster-node1.conf ~ redis-cluster-node6.conf)
cluster-config-file redis-cluster-node2.conf
# 节点超时时间
cluster-node-timeout 5000
# 当前节点ip
cluster-announce-ip 172.202.0.3
# 当前节点端口
cluster-announce-port 6380
# 集群之间通信的端口号
cluster-announce-bus-port 16380

2.2.3.redis-cluster-node3/redis.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
bind 0.0.0.0
# loglevel debug
logfile "/data/redis-cluster-node3.log"
save 3600 1
save 300 100
save 60 10000
stop-writes-on-bgsave-error no
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
rdb-del-sync-files no
dir /data/
requirepass 123456
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble yes
masterauth 123456
# 这里不开启的话,slave不一定能同步成功。windows wsl docker必须这样设置
repl-diskless-load on-empty-db

port 6381
# 启动集群模式
cluster-enabled yes
# 配置文件名称(redis-cluster-node1.conf ~ redis-cluster-node6.conf)
cluster-config-file redis-cluster-node3.conf
# 节点超时时间
cluster-node-timeout 5000
# 当前节点ip
cluster-announce-ip 172.202.0.4
# 当前节点端口
cluster-announce-port 6381
# 集群之间通信的端口号
cluster-announce-bus-port 16381

2.2.4.redis-cluster-node4/redis.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
bind 0.0.0.0
# loglevel debug
logfile "/data/redis-cluster-node6.log"
save 3600 1
save 300 100
save 60 10000
stop-writes-on-bgsave-error no
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
rdb-del-sync-files no
dir /data/
requirepass 123456
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble yes
masterauth 123456
# 这里不开启的话,slave不一定能同步成功。windows wsl docker必须这样设置
repl-diskless-load on-empty-db

port 6382
# 启动集群模式
cluster-enabled yes
# 配置文件名称(redis-cluster-node1.conf ~ redis-cluster-node6.conf)
cluster-config-file redis-cluster-node6.conf
# 节点超时时间
cluster-node-timeout 5000
# 当前节点ip
cluster-announce-ip 172.202.0.5
# 当前节点端口
cluster-announce-port 6382
# 集群之间通信的端口号
cluster-announce-bus-port 16382

2.2.5.redis-cluster-node5/redis.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
bind 0.0.0.0
# loglevel debug
logfile "/data/redis-cluster-node5.log"
save 3600 1
save 300 100
save 60 10000
stop-writes-on-bgsave-error no
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
rdb-del-sync-files no
dir /data/
requirepass 123456
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble yes
masterauth 123456
# 这里不开启的话,slave不一定能同步成功。windows wsl docker必须这样设置
repl-diskless-load on-empty-db

port 6383
# 启动集群模式
cluster-enabled yes
# 配置文件名称(redis-cluster-node1.conf ~ redis-cluster-node6.conf)
cluster-config-file redis-cluster-node5.conf
# 节点超时时间
cluster-node-timeout 5000
# 当前节点ip
cluster-announce-ip 172.202.0.6
# 当前节点端口
cluster-announce-port 6383
# 集群之间通信的端口号
cluster-announce-bus-port 16383

2.2.6.redis-cluster-node6/redis.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
bind 0.0.0.0
# loglevel debug
logfile "/data/redis-cluster-node6.log"
save 3600 1
save 300 100
save 60 10000
stop-writes-on-bgsave-error no
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
rdb-del-sync-files no
dir /data/
requirepass 123456
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble yes
masterauth 123456
# 这里不开启的话,slave不一定能同步成功。windows wsl docker必须这样设置
repl-diskless-load on-empty-db

port 6384
# 启动集群模式
cluster-enabled yes
# 配置文件名称(redis-cluster-node1.conf ~ redis-cluster-node6.conf)
cluster-config-file redis-cluster-node6.conf
# 节点超时时间
cluster-node-timeout 5000
# 当前节点ip
cluster-announce-ip 172.202.0.7
# 当前节点端口
cluster-announce-port 6384
# 集群之间通信的端口号
cluster-announce-bus-port 16384

2.2.7.scripts/init-redis-cluster.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#!/bin/bash

# 设置密码
REDIS_PASSWORD="123456"

# 节点列表
NODES=(
"172.202.0.2:6379"
"172.202.0.3:6380"
"172.202.0.4:6381"
"172.202.0.5:6382"
"172.202.0.6:6383"
"172.202.0.7:6384"
)

echo "等待Redis节点启动..."

# 等待所有节点就绪
for node in "${NODES[@]}"; do
IFS=':' read -r ip port <<< "$node"
until redis-cli -h "$ip" -p "$port" -a "$REDIS_PASSWORD" ping | grep -q "PONG"; do
echo "等待节点 $node 就绪..."
sleep 2
done
echo "节点 $node 已就绪"
done

echo "所有节点已就绪,开始创建集群..."

# 尝试创建集群
if redis-cli --cluster create \
"${NODES[0]}" \
"${NODES[1]}" \
"${NODES[2]}" \
"${NODES[3]}" \
"${NODES[4]}" \
"${NODES[5]}" \
--cluster-replicas 1 \
--cluster-yes \
-a "$REDIS_PASSWORD"; then
echo "Redis集群创建成功!"
exit 0
else
echo "Redis集群创建失败,检查是否已存在集群..."

# 检查集群状态
if redis-cli -h "${NODES[0]%:*}" -p "${NODES[0]#*:}" -a "$REDIS_PASSWORD" cluster info | grep -q 'cluster_state:ok'; then
echo "集群已存在,初始化完成"
exit 0
else
echo "集群未正确创建,请检查节点状态"
exit 1
fi
fi

2.3.创建docker-compose.yml文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
services:
redis-cluster-node1:
image: redis:7.4.5
container_name: redis-cluster-node1
restart: always
ports:
- 6379:6379
environment:
TZ: "Asia/Shanghai"
volumes:
- ./conf/redis-cluster-node1:/usr/local/etc/redis
- ./.data/redis-cluster-node1/:/data:Z
command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
networks:
redis-cluster-network:
ipv4_address: 172.202.0.2

redis-cluster-node2:
image: redis:7.4.5
container_name: redis-cluster-node2
restart: always
ports:
- 6380:6380
environment:
TZ: "Asia/Shanghai"
volumes:
- ./conf/redis-cluster-node2:/usr/local/etc/redis
- ./.data/redis-cluster-node2/:/data:Z
command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
networks:
redis-cluster-network:
ipv4_address: 172.202.0.3

redis-cluster-node3:
image: redis:7.4.5
container_name: redis-cluster-node3
restart: always
ports:
- 6381:6381
environment:
TZ: "Asia/Shanghai"
volumes:
- ./conf/redis-cluster-node3:/usr/local/etc/redis
- ./.data/redis-cluster-node3/:/data:Z
command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
networks:
redis-cluster-network:
ipv4_address: 172.202.0.4

redis-cluster-node4:
image: redis:7.4.5
container_name: redis-cluster-node4
restart: always
ports:
- 6382:6382
environment:
TZ: "Asia/Shanghai"
volumes:
- ./conf/redis-cluster-node4:/usr/local/etc/redis
- ./.data/redis-cluster-node4/:/data:Z
command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
networks:
redis-cluster-network:
ipv4_address: 172.202.0.5

redis-cluster-node5:
image: redis:7.4.5
container_name: redis-cluster-node5
restart: always
ports:
- 6383:6383
environment:
TZ: "Asia/Shanghai"
volumes:
- ./conf/redis-cluster-node5:/usr/local/etc/redis
- ./.data/redis-cluster-node5/:/data:Z
command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
networks:
redis-cluster-network:
ipv4_address: 172.202.0.6

redis-cluster-node6:
image: redis:7.4.5
container_name: redis-cluster-node6
restart: always
ports:
- 6384:6384
environment:
TZ: "Asia/Shanghai"
volumes:
- ./conf/redis-cluster-node6:/usr/local/etc/redis
- ./.data/redis-cluster-node6/:/data:Z
command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
networks:
redis-cluster-network:
ipv4_address: 172.202.0.7

redis-cluster-init: # redis-cli服务,作用是在上面六个redis节点启动成功之后,执行集群创建的命令
image: redis:7.4.5
container_name: redis-cluster-init
depends_on: # 设置依赖顺序,在上面六个节点启动成功之后启动
- redis-cluster-node1
- redis-cluster-node2
- redis-cluster-node3
- redis-cluster-node4
- redis-cluster-node5
- redis-cluster-node6
volumes:
- ./scripts/init-redis-cluster.sh:/init-redis-cluster.sh
command: >
bash -c "
chmod +x /init-redis-cluster.sh && /init-redis-cluster.sh
"
networks:
- redis-cluster-network
restart: "no" # 因为该服务只是用来执行Redis集群初始化的命令,所以服务关闭之后不需要重启

networks:
redis-cluster-network:
driver: bridge
ipam:
config:
- subnet: 172.202.0.0/24

2.4.启动

  1. 启动容器
1
docker compose up -d

  1. 查看容器状态
1
docker ps

4.2.简单测试

  1. 查看redis-cluster-init启动日志
1
docker logs -f redis-cluster-init

  1. 连接redis-cluster-node1
1
docker exec -it redis-cluster-node1 redis-cli -p 6379 -a 123456 -c
  1. 查看集群状态
1
cluster info

  1. 查看节点信息
1
cluster nodes

  1. 查看哈希槽分配信息
1
cluster slots