文章目录
- 前言
- 技术积累
- 1、Redis 主从复制机制
- 2、Docker Compose 编排
- 3、 Redis 配置文件定制
- 4、 验证主从状态
- 5、 自动化部署与维护
- 环境准备
- 实战演示
- 创建redis目录及配置
- 1、创建redis目录
- 2、创建redis配置文件
- 启动redis集群服务
- 1、创建docker-compose编排文件
- 2、编排docker-compose
- 验证Redis集群主从复制
- Redis集群数据持久化验证
- 总结
前言
随着互联网应用的快速发展,高并发访问和数据缓存的需求日益增长。Redis 作为一款高性能的内存数据库,广泛应用于缓存、消息队列、分布式锁等场景。为了提升 Redis 的可用性和读写性能,通常采用主从复制架构来实现读写分离。本次实战通过 Docker Compose 快速搭建一个 Redis 主从复制集群,模拟生产环境中 Redis 高可用架构的基础部署方式。通过该实践,可以更好地理解 Redis 主从复制机制、Docker 容器编排以及服务间通信原理。
技术积累
1、Redis 主从复制机制
- Redis 主从复制是异步复制,默认情况下从节点连接到主节点后会进行一次全量同步(RDB dump),之后进行增量同步(AOF 或 repl-backlog)。
- 从节点可处理读请求,减轻主节点压力,适用于读多写少的场景。
- 支持链式复制,即从节点也可以作为其他从节点的主节点。
- 普通主从集群没有自动故障转移,这个是最大的缺点
2、Docker Compose 编排
- 使用 docker-compose.yml 文件定义多个容器服务,实现 Redis 主从节点的快速部署。
- 通过自定义网络(networks)确保容器间可通过服务名互相访问。
- 可挂载本地目录作为配置文件或持久化存储,便于调试和数据保留。
3、 Redis 配置文件定制
- 在从节点配置中添加 replicaof 指令,指定其主节点地址。
- 可设置只读模式(slave-read-only yes)、连接超时时间、密码认证等安全策略。
4、 验证主从状态
- 进入 Redis 容器执行 redis-cli info replication 查看主从状态信息。
- 主节点显示连接的从节点数量,从节点显示其所属主节点的信息。
5、 自动化部署与维护
- 利用 Docker 的健康检查功能(healthcheck)监控 Redis 状态。
- 通过 shell 脚本或 CI/CD 工具实现一键部署与扩容。
环境准备
- 安装 docker
- 安装 docker compose
实战演示
本地演示使用windows11 docker desktop 环境,有条件的可以使用Linux自动安装docker环境。
创建redis目录及配置
1、创建redis目录
主从集群目录结构如下所示:
- master-slave
- redis-master
- data
- conf
- redis.conf
- redis-slave1
- data
- conf
- redis.conf
- redis-slave2
- data
- conf
- redis.conf
- docker-compose.yaml
- redis-master
2、创建redis配置文件
- master 主节点: redis.conf
# 主节点配置
# 绑定的主机地址
bind 0.0.0.0
# 允许外网访问
protected-mode no
# 启用守护进程后,Redis会把pid写到一个pidfile中,在/var/run/redis.pid
daemonize no
# 当Redis以守护进程方式运行时,Redis默认会把pid写入/var/run/redis.pid文件,可以通过pidfile指定
pidfile /var/run/redis.pid
# 指定Redis监听端口,默认端口为6379
# 如果指定0端口,表示Redis不监听TCP连接
port 6379
# 当客户端闲置多长时间后关闭连接,如果指定为0,表示关闭该功能
timeout 0
# 指定日志记录级别,Redis总共支持四个级别:debug、verbose、notice、warning,默认为verbose
# debug (很多信息, 对开发/测试比较有用)
# verbose (many rarely useful info, but not a mess like the debug level)
# notice (moderately verbose, what you want in production probably)
# warning (only very important / critical messages are logged)
loglevel verbose
# 日志记录方式,默认为标准输出,如果配置为redis为守护进程方式运行,而这里又配置为标准输出,则日志将会发送给/dev/null
logfile redis.log################################ SNAPSHOTTING #################################
# RDB存储配置
# 指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合
# Save the DB on disk:
#
# save <seconds> <changes>
#
# Will save the DB if both the given number of seconds and the given
# number of write operations against the DB occurred.
#
# 满足以下条件将会同步数据:
# 900秒(15分钟)内有1个更改
# 300秒(5分钟)内有10个更改
# 60秒内有10000个更改
# Note: 可以把所有“save”行注释掉,这样就取消同步操作了
save 900 1
save 300 10
save 60 10000
# 指定存储至本地数据库时是否压缩数据,默认为yes,Redis采用LZF压缩,如果为了节省CPU时间,可以关闭该选项,但会导致数据库文件变的巨大
rdbcompression yes
# 指定本地数据库文件名,默认值为dump.rdb
dbfilename dump.rdb
# 指定本地数据库存放目录,文件名由上一个dbfilename配置项指定
dir /data################################# REPLICATION ################################################################### SECURITY ###################################
# 设置密码
requirepass 123456789############################## APPEND ONLY MODE ###############################
# 开启aof配置
appendonly yes
# 指定更新日志条件,共有3个可选值:
# no:表示等操作系统进行数据缓存同步到磁盘(快)
# always:表示每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全)
# everysec:表示每秒同步一次(折衷,默认值)
appendfsync everysec
# 指定更新日志文件名,默认为appendonly.aof
appendfilename "appendonly.aof"
- slave1 从节点1 : redis.conf
# 从节点配置
# 绑定的主机地址
bind 0.0.0.0
# 允许外网访问
protected-mode no
# 启用守护进程后,Redis会把pid写到一个pidfile中,在/var/run/redis.pid
daemonize no
# 当Redis以守护进程方式运行时,Redis默认会把pid写入/var/run/redis.pid文件,可以通过pidfile指定
pidfile /var/run/redis.pid
# 指定Redis监听端口,默认端口为6379
# 如果指定0端口,表示Redis不监听TCP连接
port 6379
# 当客户端闲置多长时间后关闭连接,如果指定为0,表示关闭该功能
timeout 0
# 指定日志记录级别,Redis总共支持四个级别:debug、verbose、notice、warning,默认为verbose
# debug (很多信息, 对开发/测试比较有用)
# verbose (many rarely useful info, but not a mess like the debug level)
# notice (moderately verbose, what you want in production probably)
# warning (only very important / critical messages are logged)
loglevel verbose
# 日志记录方式,默认为标准输出,如果配置为redis为守护进程方式运行,而这里又配置为标准输出,则日志将会发送给/dev/null
logfile redis.log################################ SNAPSHOTTING #################################
# RDB存储配置
# 指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合
# Save the DB on disk:
#
# save <seconds> <changes>
#
# Will save the DB if both the given number of seconds and the given
# number of write operations against the DB occurred.
#
# 满足以下条件将会同步数据:
# 900秒(15分钟)内有1个更改
# 300秒(5分钟)内有10个更改
# 60秒内有10000个更改
# Note: 可以把所有“save”行注释掉,这样就取消同步操作了
save 900 1
save 300 10
save 60 10000
# 指定存储至本地数据库时是否压缩数据,默认为yes,Redis采用LZF压缩,如果为了节省CPU时间,可以关闭该选项,但会导致数据库文件变的巨大
rdbcompression yes
# 指定本地数据库文件名,默认值为dump.rdb
dbfilename dump.rdb
# 指定本地数据库存放目录,文件名由上一个dbfilename配置项指定
dir /data################################# REPLICATION #################################
# 设置当本机为slav服务时,设置master服务的ip地址及端口,在Redis启动时,它会自动从master进行数据同步
replicaof redis-master 6379
# 开启只读模式
replica-read-only yes
# 当master服务设置了密码保护时,slav服务连接master的密码
masterauth 123456789repl-diskless-load on-empty-db################################## SECURITY ###################################
# 设置密码
requirepass 123456789############################## APPEND ONLY MODE ###############################
# 开启aof配置
appendonly yes
# 指定更新日志条件,共有3个可选值:
# no:表示等操作系统进行数据缓存同步到磁盘(快)
# always:表示每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全)
# everysec:表示每秒同步一次(折衷,默认值)
appendfsync everysec
# 指定更新日志文件名,默认为appendonly.aof
appendfilename "appendonly.aof"
- slave2 从节点2: redis.conf和 slave1 从节点1 配置一致,复制一份即可。
启动redis集群服务
1、创建docker-compose编排文件
- 创建 docker-compose.yaml
version: '3.8'services:redis-master:image: redis:6-alpinecontainer_name: redis-masterenvironment:- "TZ=Asia/Shanghai"ports:- "6377:6379"volumes:- ./redis-master/conf/redis.conf:/usr/local/etc/redis/redis.conf- ./redis-master/data:/datacommand: redis-server /usr/local/etc/redis/redis.confnetworks:- redis-master-slaveredis-slave1:image: redis:6-alpinecontainer_name: redis-slave1environment:- "TZ=Asia/Shanghai"ports:- "6380:6379"volumes:- ./redis-slave1/conf/redis.conf:/usr/local/etc/redis/redis.conf- ./redis-slave1/data:/datacommand: redis-server /usr/local/etc/redis/redis.confdepends_on:- redis-masternetworks:- redis-master-slaveredis-slave2:image: redis:6-alpinecontainer_name: redis-slave2environment:- "TZ=Asia/Shanghai"ports:- "6381:6379"volumes:- ./redis-slave2/conf/redis.conf:/usr/local/etc/redis/redis.conf- ./redis-slave2/data:/datacommand: redis-server /usr/local/etc/redis/redis.confdepends_on:- redis-masternetworks:- redis-master-slavenetworks:redis-master-slave:driver: bridge
2、编排docker-compose
- 运行 docker-compose.yaml
docker-compose -f docker-compose.yaml up -d
- 查看redis集群容器
docker ps -a
验证Redis集群主从复制
- 检查主节点信息
docker exec -it redis-master redis-cli -h 127.0.0.1 -p 6379 -a 123456789 info replication
执行上述命令,得到以下输出:role表示角色,connected_slaves表示副本数
# Replication
role:master
connected_slaves:2
slave0:ip=172.20.0.3,port=6379,state=online,offset=603741,lag=0
slave1:ip=172.20.0.4,port=6379,state=online,offset=603741,lag=0
master_failover_state:no-failover
master_replid:149762551ed827fe20934a1917ba22acffdd96f2
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:603741
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:603741
- 检查从节点1信息
docker exec -it redis-slave1 redis-cli -h 127.0.0.1 -p 6379 -a 123456789 info replication
执行上述命令,得到以下输出:role表示角色,master_link_status表示是否连接成功,up表示成功,down表示失败
# Replication
role:slave
master_host:redis-master
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_read_repl_offset:603811
slave_repl_offset:603811
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:149762551ed827fe20934a1917ba22acffdd96f2
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:603811
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:603811
- 检查从节点2信息
docker exec -it redis-slave2 redis-cli -h 127.0.0.1 -p 6379 -a 123456789 info replication
执行上述命令,得到以下输出:role表示角色,master_link_status表示是否连接成功,up表示成功,down表示失败
# Replication
role:slave
master_host:redis-master
master_port:6379
master_link_status:up
master_last_io_seconds_ago:8
master_sync_in_progress:0
slave_read_repl_offset:603853
slave_repl_offset:603853
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:149762551ed827fe20934a1917ba22acffdd96f2
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:603853
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:603853
Redis集群数据持久化验证
- 写入数据到主节点
docker exec -it redis-master redis-cli -h 127.0.0.1 -p 6379 -a 123456789 SET name "test_senfel_data"
- 主节点读取数据查看是否设置成功
docker exec -it redis-master redis-cli -h 127.0.0.1 -p 6379 -a 123456789 GET name
- 从节点1读取数据,查看是否同步
docker exec -it redis-slave1 redis-cli -h 127.0.0.1 -p 6379 -a 123456789 GET name
- 从节点2读取数据,查看是否同步
docker exec -it redis-slave2 redis-cli -h 127.0.0.1 -p 6379 -a 123456789 GET name
PS C:\Users\user> docker exec -it redis-master redis-cli -h 127.0.0.1 -p 6379 -a 123456789 SET name "test_senfel_data"
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
OK
PS C:\Users\user> docker exec -it redis-master redis-cli -h 127.0.0.1 -p 6379 -a 123456789 GET name
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
"test_senfel_data"
PS C:\Users\user> docker exec -it redis-slave1 redis-cli -h 127.0.0.1 -p 6379 -a 123456789 GET name
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
"test_senfel_data"
PS C:\Users\user> docker exec -it redis-slave2 redis-cli -h 127.0.0.1 -p 6379 -a 123456789 GET name
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
"test_senfel_data"
总结
本次实战成功利用 Docker Compose 搭建了一个 Redis 主从复制环境,可以掌握Redis 主从复制的基本原理与配置方法,Docker Compose 多服务容器编排的能力,以及Redis 服务的容器化部署与管理。但是普通主从复制虽然可以提升读性能和数据冗余功能,却不能实现高可用的,因为它并没有实现自动故障转移。故下一期我们将继续实战可自动故障转移的哨兵模式,敬请鉴赏。