1.概述

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

示例代码地址

2.搭建主从模式

2.1.创建文件夹

1
2
mkdir -p redis-sentinel-replication/redis/.data
mkdir -p redis-sentinel-replication/redis/conf

2.2.创建配置文件

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

2.2.1.redis-master.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
bind 0.0.0.0
loglevel debug
logfile "/data/redis-6379.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
# replica-announce-ip redis-master
# replica-announce-port 6379

# 这里不开启的话,slave不一定能同步成功。windows wsl docker必须这样设置
repl-diskless-load on-empty-db

2.2.2.redis-slave1.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
bind 0.0.0.0
loglevel debug
logfile "/data/redis-6380.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
replica-announce-ip 172.201.0.3
replica-announce-port 6379

slaveof 172.201.0.2 6379
slave-read-only yes
slave-serve-stale-data yes

# 这里不开启的话,slave不一定能同步成功。windows wsl docker必须这样设置
repl-diskless-load on-empty-db

2.2.3.redis-slave2.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
bind 0.0.0.0
loglevel debug
logfile "/data/redis-6381.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
replica-announce-ip 172.201.0.4
replica-announce-port 6379

slaveof 172.201.0.2 6379
slave-read-only yes
slave-serve-stale-data yes

# 这里不开启的话,slave不一定能同步成功。windows wsl docker必须这样设置
repl-diskless-load on-empty-db

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
services:
# redis-master
redis-master:
image: redis:7.4.5
container_name: redis-master
restart: always
ports:
- 6379:6379
environment:
TZ: "Asia/Shanghai"
volumes:
- ./redis/conf/redis-master.conf:/usr/local/etc/redis/redis.conf
- ./redis/.data/redis-master/:/data:Z
command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
networks:
redis-network:
ipv4_address: 172.201.0.2

# redis slave 1
redis-slave1:
image: redis:7.4.5
container_name: redis-slave1
restart: always
ports:
- 6380:6379
environment:
TZ: "Asia/Shanghai"
volumes:
- ./redis/conf/redis-slave1.conf:/usr/local/etc/redis/redis.conf
- ./redis/.data/redis-slave1/:/data:Z
command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
networks:
redis-network:
ipv4_address: 172.201.0.3

# redis slave 2
redis-slave2:
image: redis:7.4.5
container_name: redis-slave2
restart: always
ports:
- 6381:6379
environment:
TZ: "Asia/Shanghai"
volumes:
- ./redis/conf/redis-slave2.conf:/usr/local/etc/redis/redis.conf
- ./redis/.data/redis-slave2/:/data:Z
command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
networks:
redis-network:
ipv4_address: 172.201.0.4

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

上述docker-compose.yml文件定义了两个Redis服务,一个用于主节点(redis-master),另一个用于从节点(redis-slave)。

  • 主节点将监听默认端口6379
  • 从节点将监听端口6380

此外,我们创建了一个自定义网络(redis-network),以便主从节点可以相互通信。

2.3.启动

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

  1. 查看容器状态
1
docker ps

2.4.简单测试

  1. 检查主从复制是否正常工作。可以使用Another Redis Desktop Manager连接到主节点并执行一些写操作:

  1. 再检查两个从库数据是否已经复制

99.常见问题

  1. Failed trying to load the MASTER synchronization DB from disk: No such file or directory

redis官方配置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
# -----------------------------------------------------------------------------
#
# Replica can load the RDB it reads from the replication link directly from the
# socket, or store the RDB to a file and read that file after it was completely
# received from the master.
#
# In many cases the disk is slower than the network, and storing and loading
# the RDB file may increase replication time (and even increase the master's
# Copy on Write memory and replica buffers).
# However, parsing the RDB file directly from the socket may mean that we have
# to flush the contents of the current database before the full rdb was
# received. For this reason we have the following options:
#
# "disabled" - Don't use diskless load (store the rdb file to the disk first)
# "on-empty-db" - Use diskless load only when it is completely safe.
# "swapdb" - Keep current db contents in RAM while parsing the data directly
# from the socket. Replicas in this mode can keep serving current
# data set while replication is in progress, except for cases where
# they can't recognize master as having a data set from same
# replication history.
# Note that this requires sufficient memory, if you don't have it,
# you risk an OOM kill.
repl-diskless-load disabled

我们将上面的属性设置为on-empty-db即可

  1. WARNING: Sentinel was not able to save the new configuration on disk!!!: Device or resource busy

如果直接使用文件映射指定sentinel.conf到容器内,这么做有可能导致哨兵没有写入配置文件的权限。

解决方案:使用文件夹映射。