大家好,我是曾续缘。本教程分享如何使用Docker搭建一个Redis主从集群,并配置哨兵模式以实现高可用性。通过本教程,我们将学习到如何创建Redis配置文件、设置主从关系、配置哨兵以及验证集群的工作状态。
准备工作
在开始之前,请确保已经安装了Docker和Docker Compose。
创建一个目录用于存放Redis容器的配置文件。
创建1个redis配置文件redis.conf
,内容如下:
查看代码
# 保护模式,设置为no可以关闭保护模式,允许外部网络访问
protected-mode no
# Redis监听的端口号
port 6379
# TCP监听的最大容纳数量
tcp-backlog 511
# Redis密码,强烈建议设置一个复杂的密码
requirepass redisroot
# 客户端闲置多少秒后断开连接,0表示不断开
timeout 0
# TCP保活策略,每隔多少秒发送一次ACK包,确认连接是否有效
tcp-keepalive 300
# 是否以守护进程方式运行,no表示不以后台进程方式运行
daemonize no
# 是否通过upstart或systemd管理,no表示不通过这些系统管理工具
supervised no
# 存储Redis进程号的文件路径
pidfile /var/run/redis_6379.pid
# 日志级别,notice表示普通级别
loglevel notice
# 日志文件路径,空字符串表示打印到标准输出
logfile ""
# 数据库数量,默认有16个
databases 30
# 是否显示启动LOGO
always-show-logo yes
# RDB持久化规则,例如在900秒内至少1个变更,300秒内至少10个变更,60秒内至少10000个变更时保存数据到磁盘
save 900 1
save 300 10
save 60 10000
# 在RDB持久化出错时停止写入操作
stop-writes-on-bgsave-error yes
# 是否对RDB文件进行压缩
rdbcompression yes
# 是否对RDB文件进行校验
rdbchecksum yes
# RDB文件名
dbfilename dump.rdb
# 数据存放目录
dir ./
# 当从库与主库失去连接时,是否继续响应客户端请求
replica-serve-stale-data yes
# 从库是否只读
replica-read-only yes
# 主从复制是否使用无磁盘同步
repl-diskless-sync no
# 主从复制是否禁用TCP_NODELAY
repl-disable-tcp-nodelay no
# 从库优先级,数字越小优先级越高
replica-priority 100
# 各种lazy选项,控制Redis释放内存的速度和方式
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
replica-lazy-flush no
# 是否开启AOF持久化
appendonly yes
# AOF文件名
appendfilename "appendonly.aof"
# 在AOF重写期间是否禁止fsync
no-appendfsync-on-rewrite no
# 自动触发AOF重写的百分比
auto-aof-rewrite-percentage 100
# 自动触发AOF重写的最小文件大小
auto-aof-rewrite-min-size 64mb
# 当AOF文件损坏时是否仍能加载
aof-load-truncated yes
# 是否使用RDB前导来减少AOF文件大小
aof-use-rdb-preamble yes
# Lua脚本的最大执行时间
lua-time-limit 5000
# 慢查询日志的最大长度
slowlog-max-len 128
# Keyspace事件通知,空字符串表示不通知
notify-keyspace-events ""
# Hash类型相关配置,ziplist的条目数和大小限制
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
# List类型相关配置,ziplist的大小限制
list-max-ziplist-size -2
# List压缩深度
list-compress-depth 0
# Set类型相关配置,intset的条目数限制
set-max-intset-entries 512
# Zset类型相关配置,ziplist的条目数和大小限制
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
# HyperLogLog的sparse模式的最大字节数
hll-sparse-max-bytes 3000
# Stream类型节点的最大字节数和条目数限制
stream-node-max-bytes 4096
stream-node-max-entries 100
# 是否激活重置哈希
activerehashing yes
# 服务器周期性操作频率,hz
hz 10
# 是否根据实际负载动态调整周期性操作的频率
dynamic-hz yes
# AOF重写时是否使用增量fsync
aof-rewrite-incremental-fsync yes
# RDB保存时是否使用增量fsync
rdb-save-incremental-fsync yes
然后复制两份,得到redis1.conf
和redis2.conf
。
cp redis.conf redis1.conf
cp redis.conf redis2.conf
接下来,我们将为从节点配置特定的参数。
编辑redis1.conf
和redis2.conf
,添加以下内容以指定它们作为从节点,并连接到主节点。
replicaof redis 6379
masterauth redisroot
一旦所有的Redis实例启动完成,从节点将开始从主节点同步数据。
主从复制原理
- 复制原理:Redis的主从复制是基于Master将数据快照和写命令传播给一个或多个Slave来实现的。当Slave启动并连接Master时,它会发送SYNC命令请求同步数据。Master则执行BGSAVE生成RDB文件并以缓冲区记录这期间的写命令,之后将这些数据传输给Slave。Slave载入这些数据后,Master再将缓存的写命令发送给Slave执行,以保证数据的一致性。
- 数据同步过程:在初次同步完成后,如果Master和Slave之间的连接没有断开,那么Master将使用同步之后的写命令持续更新Slave,保持数据的实时一致性。这种机制确保了数据的完整性和准确性,即使在高并发的情况下也能保证。
编写Docker Compose文件
现在,编写一个docker-compose.yaml
文件,用于创建3个Redis容器,分别绑定这3个不同的配置文件。
查看代码
services:
redis:
image: redis:6.2.7
container_name: redis
ports:
- "6379:6379"
volumes:
- /data/redis/conf/redis.conf:/etc/redis/redis.conf
command: redis-server /etc/redis/redis.conf
networks:
- redis-network
redis1:
image: redis:6.2.7
container_name: redis1
ports:
- "6378:6379"
volumes:
- /data/redis/conf/redis1.conf:/etc/redis/redis.conf
command: redis-server /etc/redis/redis.conf
networks:
- redis-network
redis2:
image: redis:6.2.7
container_name: redis2
ports:
- "6377:6379"
volumes:
- /data/redis/conf/redis2.conf:/etc/redis/redis.conf
command: redis-server /etc/redis/redis.conf
networks:
- redis-network
networks:
redis-network:
driver: bridge
启动和验证Redis集群
使用以下命令启动Docker Compose配置的容器:
docker compose up -d
容器启动后,通过以下命令进入Redis主节点容器,并获取关于Redis实例复制功能的信息:
docker exec -it redis redis-cli -a redisroot
info replication
可以看到当前 Redis 实例作为主库(master)运行,并成功与两个从库(slave)建立了连接。两个从库的 IP 地址分别为 172.19.0.2 和 172.19.0.4,均运行在默认的 6379 端口上,并且都处于在线状态。
接下来,尝试在主节点上进行写操作,并在从节点上进行读操作,以验证主从复制功能是否正常工作。
![]() | ![]() | ![]() |
---|
可以看到,只有在redis
这个节点上可以执行set
命令(写操作),其它两个节点只能执行get
命令(读操作)。也就是说读写操作已经分离了。
配置哨兵模式
在Redis主从架构中,哨兵(Sentinel)机制是用于监控Redis节点(特别是Master节点),在节点发生故障时自动进行故障转移,选举新的Master节点,并通知其他的Slave重新与新的Master同步。
要启用哨兵模式,需要额外配置哨兵的配置文件(sentinel.conf),并在其中指定需要监控的主服务器信息及端口,设置监控行为的参数,如故障判定的时限和自动选举新Master的投票数等。启动哨兵实例后,它们会自动发现并互相协作,共同维护整个集群的状态。
首先,创建哨兵的配置文件sentinel.conf
,内容如下:
port 26379 # 哨兵实例监听的端口号
sentinel monitor redisMaster redis 6379 2 # 监控指定Redis Master实例
sentinel auth-pass redisMaster redisroot # 设置访问控制
sentinel down-after-milliseconds redisMaster 5000 # 故障判定及响应时间设定
sentinel failover-timeout redisMaster 50000
port 26379
- 这行配置指定了哨兵实例监听的端口号,这里是26379,这是哨兵服务器的默认端口。
sentinel monitor redisMaster redis 6379 2
- 这行配置指示哨兵监控一个名为
redisMaster
的主节点。redis
是主节点的名字,可以是IP地址或可解析的主机名。6379
是主节点监听的端口号。2
表示至少需要两个哨兵认为主节点不可达,才会进行故障转移。
sentinel auth-pass redisMaster redisroot
- 这行配置提供了连接到主节点的密码,
redisMaster
是主节点的名称,redisroot
是密码。- 这是在主节点设置了密码的情况下需要的配置。
sentinel down-after-milliseconds redisMaster 5000
- 这行配置设置了哨兵认为主节点下线的超时时间,这里是5000毫秒(5秒)。
- 如果主节点在指定时间内没有回复哨兵的PING命令,哨兵会认为主节点已经下线。
sentinel failover-timeout redisMaster 50000
- 这行配置设置了故障转移的超时时间,这里是50000毫秒(50秒)。
- 在进行故障转移时,如果在这个时间内没有完成故障转移,则认为故障转移失败。
有些版本指定容器名
redis
会报错,那就填127.0.0.1
。上面一行改为
sentinel monitor redisMaster 127.0.0.1 6379 2
。启动后,查看redis的ip地址后再修改重启。
docker network inspect redis-network
复制两份哨兵配置文件,以创建3个哨兵实例:
cp sentinel.conf sentinel1.conf
cp sentinel.conf sentinel2.conf
使用下面命令关闭和删除compose文件对应的容器网络。注意需要在compose文件目录下执行。
docker compose down
然后,更新docker-compose.yaml
文件以包括哨兵服务:
查看代码
services:
redis:
image: redis:6.2.7
container_name: redis
ports:
- "6379:6379"
volumes:
- /data/redis/conf/redis.conf:/etc/redis/redis.conf
command: redis-server /etc/redis/redis.conf
networks:
- redis-network
redis1:
image: redis:6.2.7
container_name: redis1
ports:
- "6378:6379"
volumes:
- /data/redis/conf/redis1.conf:/etc/redis/redis.conf
command: redis-server /etc/redis/redis.conf
networks:
- redis-network
redis2:
image: redis:6.2.7
container_name: redis2
ports:
- "6377:6379"
volumes:
- /data/redis/conf/redis2.conf:/etc/redis/redis.conf
command: redis-server /etc/redis/redis.conf
networks:
- redis-network
sentinel:
image: redis:6.2.7
container_name: sentinel
ports:
- "26379:26379"
volumes:
- /data/redis/conf/sentinel.conf:/etc/redis/sentinel.conf
networks:
- redis-network
command: redis-sentinel /etc/redis/sentinel.conf
sentinel1:
image: redis:6.2.7
container_name: sentinel1
ports:
- "26378:26379"
volumes:
- /data/redis/conf/sentinel1.conf:/etc/redis/sentinel.conf
networks:
- redis-network
command: redis-sentinel /etc/redis/sentinel.conf
sentinel2:
image: redis:6.2.7
container_name: sentinel2
ports:
- "26377:26379"
volumes:
- /data/redis/conf/sentinel2.conf:/etc/redis/sentinel.conf
networks:
- redis-network
command: redis-sentinel /etc/redis/sentinel.conf
networks:
redis-network:
name: redis-network
driver: bridge
重新启动Docker Compose配置的容器:
docker compose up -d
容器启动后,通过以下命令进入哨兵主节点容器,并获取关于哨兵的信息:
进入哨兵主节点容器,查看哨兵状态。
docker exec -it sentinel redis-cli -p 26379
info sentinel
可以看到1主2从3哨兵。
验证哨兵模式
为了验证哨兵模式的工作,我们可以关闭主节点Redis容器,然后观察哨兵是否自动将一个从节点提升为新主节点。
现在关闭主节点
docker stop redis
然后稍等片刻,哨兵应该会检测到主节点失效,并开始故障转移过程。
再次进入哨兵节点查看状态。
docker exec -it sentinel redis-cli -p 26379
info sentinel
会看到主节点的IP地址已经更改,这表明哨兵已经选择了一个新的主节点。
查看两个redis节点情况,发现redis2成为master节点。
info replication
重新启动之前的主节点Redis容器,它作为从节点重新加入了集群。
docker start redis
参考资料:
https://www.cnblogs.com/lvrui/p/15292747.html