用Docker Compose快速搭建Redis Cluster集群(附完整配置与解析)
有的时候我们为了验证redis的一些特性,需要搭建一个实验环境,如果向运维申请不太好协调,本教程使用特别简单的一种方式,快速搭建一个redis集群,本环境最新版本使用redis8。
一、为什么选择Docker Compose搭建Redis Cluster?
在传统部署方式中,搭建Redis Cluster需要手动配置每个节点、执行集群初始化命令,步骤繁琐且易出错;而Docker Compose通过配置即代码的方式,将所有节点的部署逻辑整合到一个docker-compose.yml文件中,只需一条命令即可完成集群创建,优势显著:
二、完整Docker Compose配置解析
先上完整的docker-compose.yml配置(即文中提供的版本),再逐段拆解关键参数,帮大家理解每一行配置的作用:
version: '3' # Compose文件版本,兼容Docker 1.13.0+
services:
# 第一个Redis节点(主节点)
redis-node-0:
image: bitnamilegacy/redis-cluster:5.0 # 基于Bitnami的Redis集群镜像(稳定版5.0)
ports:
- "6380:6379" # 宿主机端口6380映射到容器内Redis默认端口6379
volumes:
- redis-cluster_data-0:/bitnami/redis/data # 数据卷挂载,持久化Redis数据
environment:
- REDIS_PASSWORD=test@redis # Redis集群密码(所有节点必须一致)
- REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 # 集群所有节点名称(用于发现节点)
- REDIS_ALLOW_REMOTE_CONNECTIONS=yes # 允许远程连接(非本地容器可访问)
- REDIS_CLUSTER_DYNAMIC_IPS=no # 禁用动态IP(避免容器重启后IP变化导致集群故障)
- REDIS_CLUSTER_ANNOUNCE_IP=172.24.32.232 # 宣告IP(必须是宿主机可被访问的IP)
- REDIS_CLUSTER_ANNOUNCE_PORT=6380 # 关键:宣告宿主机映射端口(而非容器内6379)
# 第二个Redis节点(主节点)
redis-node-1:
image: bitnamilegacy/redis-cluster:5.0
ports:
- "6381:6379"
volumes:
- redis-cluster_data-1:/bitnami/redis/data
environment:
- REDIS_PASSWORD=test@redis
- REDIS_NODES=redis-node-0 redis-node-1 redis-node-2
- REDIS_ALLOW_REMOTE_CONNECTIONS=yes
- REDIS_CLUSTER_DYNAMIC_IPS=no
- REDIS_CLUSTER_ANNOUNCE_IP=172.24.32.232
- REDIS_CLUSTER_ANNOUNCE_PORT=6381 # 对应宿主机映射端口6381
# 第三个Redis节点(主节点+集群初始化节点)
redis-node-2:
image: bitnamilegacy/redis-cluster:5.0
ports:
- "6382:6379"
depends_on: # 依赖关系:确保node0和node1启动后再启动node2
- redis-node-0
- redis-node-1
volumes:
- redis-cluster_data-2:/bitnami/redis/data
environment:
- REDIS_PASSWORD=test@redis
- REDISCLI_AUTH=test@redis # redis-cli工具的认证密码(用于执行集群创建命令)
- REDIS_NODES=redis-node-0 redis-node-1 redis-node-2
- REDIS_CLUSTER_REPLICAS=0 # 副本数:0表示所有节点都是主节点(无从节点,简化版集群)
- REDIS_CLUSTER_CREATOR=yes # 标记为“集群创建者”:此节点会自动执行集群初始化命令
- REDIS_ALLOW_REMOTE_CONNECTIONS=yes
- REDIS_CLUSTER_DYNAMIC_IPS=no
- REDIS_CLUSTER_ANNOUNCE_IP=172.24.32.232
- REDIS_CLUSTER_ANNOUNCE_PORT=6382
# 数据卷定义:用于持久化每个节点的数据(容器删除后数据不丢失)
volumes:
redis-cluster_data-0:
redis-cluster_data-1:
redis-cluster_data-2:
# 自定义网络:避免与宿主机或其他容器网络冲突
networks:
default:
driver: bridge # 桥接模式(默认网络模式,适合单机部署)
ipam:
driver: default
config:
- subnet: 172.28.0.0/16 # 独立子网:172.28.0.0网段,避免与其他服务IP冲突
redis-host.conf
# Redis Cluster配置文件(适用于Docker环境下的集群节点)
# 核心功能:定义Redis服务端口、网络策略、持久化方式及集群通信规则
################################## 网络与访问控制 ##################################
# 绑定地址:允许所有IPv4(0.0.0.0)和IPv6(::)地址访问
# 集群环境必须配置,确保节点间跨容器通信
bind 0.0.0.0 ::
# 保护模式:开启(yes)
# 作用:仅允许通过密码认证或指定IP的客户端访问,防止未授权访问
protected-mode yes
# 服务端口:6379(Redis默认端口)
# 与Docker Compose中的端口映射对应(如宿主机6380:容器内6379)
port 6379
# TCP连接队列大小:511
# 高并发场景可调整为1024,避免连接被拒绝
tcp-backlog 511
# 客户端超时时间:0(永不超时)
# 集群节点间保持长连接,禁用超时防止通信中断
timeout 0
# TCP保活机制:300秒(5分钟)
# 定期发送心跳包检测连接有效性,避免"假死"节点
tcp-keepalive 300
################################## 进程与日志配置 ##################################
# 守护进程模式:禁用(no)
# 容器环境必须设为no,否则Redis会以后台进程运行导致容器退出
daemonize no
# 外部进程监控:禁用(no)
# 容器内由Docker管理进程生命周期,无需外部监控
supervised no
# PID文件路径:容器内存储进程ID的位置
# 用于容器内部管理Redis进程
pidfile /opt/bitnami/redis/tmp/redis.pid
# 日志级别:notice
# 日志详细程度:debug > verbose > notice > warning
# 生产环境推荐notice(平衡详细度与性能)
loglevel notice
# 日志输出路径:空字符串(输出到标准输出)
# 容器环境下便于通过docker logs命令查看日志
logfile ""
################################## 数据库基础配置 ##################################
# 数据库数量:16个
# 注意:Redis Cluster仅使用db0,其他数据库无效
databases 16
# 启动时显示Logo:启用(yes)
# 仅影响启动日志输出,无功能影响,生产环境可设为no
always-show-logo yes
################################## RDB持久化配置 ##################################
# RDB快照触发条件(满足任一条件即执行)
save 900 1 # 900秒(15分钟)内有1次写入操作
save 300 10 # 300秒(5分钟)内有10次写入操作
save 60 10000 # 60秒(1分钟)内有10000次写入操作
# 快照生成失败时是否停止写入:是(yes)
# 生产环境建议开启,防止数据丢失却未察觉
stop-writes-on-bgsave-error yes
# RDB文件压缩:启用(yes)
# 压缩快照文件大小,代价是轻微CPU消耗,推荐开启
rdbcompression yes
# RDB文件校验:启用(yes)
# 加载快照时校验完整性,防止损坏的RDB导致节点启动失败
rdbchecksum yes
# RDB文件名:dump.rdb
# 快照文件名称,存储在dir指定的目录
dbfilename dump.rdb
# 数据存储目录:/bitnami/redis/data
# 需与Docker Compose的volumes挂载路径一致,确保数据持久化
dir /bitnami/redis/data
################################## 主从复制配置 ##################################
# 从节点服务过期数据:是(yes)
# 主节点故障时,从节点继续提供旧数据,避免服务中断
replica-serve-stale-data yes
# 从节点只读:是(yes)
# 防止从节点被误写入,保证主从数据一致性
replica-read-only yes
# 无盘复制:禁用(no)
# 关闭时使用磁盘传输数据,适合中小数据量;大数据量可设为yes减少IO
repl-diskless-sync no
# 无盘复制延迟:5秒
# 等待从节点准备就绪后再发送数据,避免网络拥塞
repl-diskless-sync-delay 5
# 禁用TCP_NODELAY:否(no)
# 关闭Nagle算法,减少数据传输延迟,加速主从同步
repl-disable-tcp-nodelay no
# 从节点优先级:100
# 数值越小优先级越高,故障转移时优先选择高优先级节点
replica-priority 100
################################## 安全配置 ##################################
# 访问密码:test@redis
# 集群所有节点必须使用相同密码,否则节点间无法通信
requirepass test@redis
################################## 惰性删除配置 ##################################
# 内存淘汰时惰性删除:否(no)
# 内存不足时立即删除过期键,适合数据一致性要求高的场景
lazyfree-lazy-eviction no
# 键过期时惰性删除:否(no)
# 键过期后立即删除,不延迟处理
lazyfree-lazy-expire no
# 服务器删除操作惰性执行:否(no)
# DEL命令立即执行,不交给后台线程
lazyfree-lazy-server-del no
# 从节点惰性清空数据:否(no)
# 从节点同步主节点数据时,立即清空旧数据
replica-lazy-flush no
################################## AOF持久化配置 ##################################
# 开启AOF持久化:是(yes)
# 生产环境建议开启,与RDB配合实现双保险
appendonly yes
# AOF文件名:appendonly.aof
# AOF日志文件名称,存储在dir指定目录
appendfilename "appendonly.aof"
# AOF刷盘策略:everysec(每秒一次)
# 策略对比:
# - always:每次写入都刷盘(最安全,性能最差)
# - everysec:每秒刷盘(平衡安全与性能,推荐)
# - no:由操作系统决定(性能最好,风险最高)
appendfsync everysec
# AOF重写时是否暂停刷盘:否(no)
# 重写期间继续刷盘,避免数据丢失
no-appendfsync-on-rewrite no
# AOF自动重写触发条件:
auto-aof-rewrite-percentage 100 # 文件大小比上次重写后增长100%(翻倍)
auto-aof-rewrite-min-size 64mb # 文件最小达到64MB才可能触发重写
# 加载AOF时允许截断:是(yes)
# AOF文件损坏时,忽略损坏部分继续加载,避免节点启动失败
aof-load-truncated yes
# AOF混合持久化:是(yes)
# AOF文件头部存储RDB快照,尾部存储增量命令,兼顾加载速度与数据完整性
aof-use-rdb-preamble yes
################################## Lua脚本配置 ##################################
# Lua脚本执行超时时间:5000毫秒(5秒)
# 防止长时间运行的脚本阻塞Redis主线程
lua-time-limit 5000
################################## 集群核心配置 ##################################
# 开启集群模式:是(yes)
# 此参数是区分集群节点与单机节点的关键
cluster-enabled yes
# 集群配置文件:/bitnami/redis/data/nodes.conf
# 自动生成和维护,存储集群槽位分配、节点信息等,请勿手动修改
cluster-config-file /bitnami/redis/data/nodes.conf
# 集群宣告IP:172.24.32.232
# 节点向集群其他节点宣告的IP地址,必须是宿主机可访问的IP
# 与Docker Compose中的REDIS_CLUSTER_ANNOUNCE_IP保持一致
cluster-announce-ip 172.24.32.232
################################## 性能与监控配置 ##################################
# 慢查询阈值:10000微秒(10毫秒)
# 执行时间超过此值的命令会被记录到慢查询日志
slowlog-log-slower-than 10000
# 慢查询日志最大长度:128条
# 日志满后自动删除最旧的记录
slowlog-max-len 128
# 延迟监控阈值:0(关闭)
# 设为>0的值(毫秒)时开启,记录超过该阈值的延迟事件
latency-monitor-threshold 0
# 键空间事件通知:关闭(空字符串)
# 不发送任何事件通知,减少性能消耗;需使用时可配置(如"KEA")
notify-keyspace-events ""
################################## 数据结构优化配置 ##################################
# Hash结构压缩阈值
hash-max-ziplist-entries 512 # 元素数量≤512时使用紧凑存储
hash-max-ziplist-value 64 # 元素值≤64字节时使用紧凑存储
# List结构压缩配置
list-max-ziplist-size -2 # -2表示按字节限制(≤8KB时使用紧凑存储)
list-compress-depth 0 # 0表示不压缩列表两端的节点
# Set结构编码优化
set-max-intset-entries 512 # 元素≤512且全为整数时使用紧凑存储
# ZSet结构压缩阈值
zset-max-ziplist-entries 128 # 元素数量≤128时使用紧凑存储
zset-max-ziplist-value 64 # 元素值≤64字节时使用紧凑存储
# HyperLogLog存储优化
hll-sparse-max-bytes 3000 # ≤3000字节时使用稀疏存储
# Stream节点大小限制
stream-node-max-bytes 4096 # 单个节点最大4096字节
stream-node-max-entries 100 # 单个节点最多100个条目
# 主动重哈希:启用(yes)
# 定期优化Hash表,避免哈希冲突导致性能下降
activerehashing yes
################################## 客户端限制配置 ##################################
# 客户端输出缓冲区限制(防止单个客户端占用过多内存)
client-output-buffer-limit normal 0 0 0 # 普通客户端:无限制
client-output-buffer-limit replica 256mb 64mb 60 # 从节点客户端:256MB后限流,64MB持续60秒则断开
client-output-buffer-limit pubsub 32mb 8mb 60 # 订阅客户端:32MB后限流,8MB持续60秒则断开
################################## 系统优化配置 ##################################
# 主线程执行频率:10Hz(每秒10次)
# 高并发场景可提高至20-50,提升响应速度(会增加CPU消耗)
hz 10
# 动态调整主线程频率:启用(yes)
# 根据负载自动调整hz值,平衡性能与CPU消耗
dynamic-hz yes
# AOF重写增量刷盘:启用(yes)
# 重写AOF时每写32KB数据刷盘一次,避免磁盘IO峰值
aof-rewrite-incremental-fsync yes
# RDB快照增量刷盘:启用(yes)
# 生成RDB时每写32KB数据刷盘一次,优化磁盘IO
rdb-save-incremental-fsync yes
三、关键配置详解(避坑重点!)
在实战中,很多人搭建Redis Cluster后会遇到“节点无法通信”“远程无法连接”等问题,核心原因是对以下几个关键配置理解不到位,这里单独拎出来重点说明:
1. REDIS_CLUSTER_ANNOUNCE_IP与REDIS_CLUSTER_ANNOUNCE_PORT
这是最容易踩坑的配置,也是集群能正常工作的核心:
背景:Redis Cluster节点之间需要互相通信,默认情况下,容器会使用自己的内部IP(如172.17.0.x)和内部端口(6379)向其他节点“宣告”自己的地址;但如果宿主机外的服务要访问集群,或宿主机有端口映射,内部地址会导致“节点可达性问题”。
解决方案:
REDIS_CLUSTER_ANNOUNCE_IP:填写宿主机的IP地址(如配置中的172.24.32.232,需确保其他节点/服务能访问该IP);REDIS_CLUSTER_ANNOUNCE_PORT:填写宿主机的映射端口(如node0的6380,而非容器内的6379),确保外部流量能通过宿主机端口转发到容器。
2. REDIS_CLUSTER_CREATOR=yes与depends_on
集群初始化需要一个“发起者”节点,负责执行redis-cli --cluster create命令:
REDIS_CLUSTER_CREATOR=yes:标记redis-node-2为“创建者”,该节点启动后会自动执行集群初始化,无需手动操作;depends_on: [redis-node-0, redis-node-1]:确保另外两个节点先启动,避免初始化时节点未就绪导致失败。
3. 自定义网络(networks)
默认情况下,Docker Compose会创建一个默认网络,但可能与宿主机其他服务的子网冲突(如172.17.0.0是Docker默认桥接网段):
配置中指定
subnet: 172.28.0.0/16,为Redis集群分配独立网段,彻底避免IP冲突问题;网络驱动使用
bridge,适合单机部署;如果是多机部署,可改用overlay网络。
4. 数据卷(volumes)
每个节点对应一个独立的数据卷(redis-cluster_data-0/1/2):
作用:持久化Redis数据,即使容器被删除,数据仍保存在宿主机的
/var/lib/docker/volumes/目录下;优势:节点重启、重建时,数据不会丢失,保证集群数据一致性。
四、集群部署与验证步骤
理解配置后,实际部署只需3步,非常简单:
步骤1:准备配置文件
在宿主机创建一个目录(如redis-cluster),并在该目录下创建docker-compose.yml文件,将上文的完整配置复制进去。
步骤2:启动Redis Cluster集群
在redis-cluster目录下执行以下命令,启动集群(-d表示后台运行):
docker-compose up -d
启动后可通过以下命令查看容器状态,确保3个节点都处于Up状态:
docker-compose ps
步骤3:验证集群可用性
验证1:进入容器查看集群信息
选择任意一个节点(如redis-node-0),进入容器内部:
docker-compose exec redis-node-0 bash
在容器内执行redis-cli命令(需输入密码),查看集群状态:
redis-cli -a test@redis cluster info
如果输出类似以下内容,说明集群正常(cluster_state:ok表示集群状态健康):
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
...
验证2:测试数据读写
在redis-cli中执行数据写入与读取,验证分片功能(Redis Cluster会将数据按槽位分配到不同节点):
# 写入数据(key为"test_key")
set test_key "hello_redis_cluster"
# 读取数据
get test_key
# 查看该key所在的节点
cluster keyslot test_key
如果能正常写入并读取,且cluster keyslot能返回对应的槽位(如15495),说明集群分片功能正常。
验证3:远程访问测试
在另一台能访问宿主机(172.24.32.232)的机器上,使用redis-cli远程连接集群(需指定任意一个节点的宿主机IP和端口):
redis-cli -h 172.24.32.232 -p 6380 -a test@redis
连接成功后执行cluster nodes,能看到所有3个节点的信息,说明远程访问正常。
五、常见问题与解决方案
在部署过程中,可能会遇到以下问题,这里提供针对性解决方案:
问题1:集群启动后cluster_state:fail
原因:节点之间无法通信,大概率是
REDIS_CLUSTER_ANNOUNCE_IP或REDIS_CLUSTER_ANNOUNCE_PORT配置错误;解决方案:
确认
REDIS_CLUSTER_ANNOUNCE_IP是宿主机的正确IP(可通过ifconfig或ip addr查看);确认
REDIS_CLUSTER_ANNOUNCE_PORT与ports中的宿主机端口一致(如node0的6380);重启集群:
docker-compose down && docker-compose up -d。
问题2:远程无法连接集群
原因:
宿主机防火墙未开放6380/6381/6382端口;
REDIS_ALLOW_REMOTE_CONNECTIONS未设置为yes;
解决方案:
开放端口(以CentOS为例):
firewall-cmd --zone=public --add-port=6380-6382/tcp --permanent firewall-cmd --reload确认
environment中REDIS_ALLOW_REMOTE_CONNECTIONS=yes。
问题3:容器启动后立即退出
原因:数据卷权限不足,或之前的集群数据残留导致冲突;
解决方案:
删除旧数据卷:
docker volume rm redis-cluster_redis-cluster_data-0 redis-cluster_redis-cluster_data-1 redis-cluster_redis-cluster_data-2;重启集群:
docker-compose up -d。
六、扩展建议
本文搭建的是3主0从的简化版集群,适合测试或小规模应用;如果用于生产环境,建议优化以下几点:
增加从节点:将
REDIS_CLUSTER_REPLICAS设置为1或2,为每个主节点配置从节点,实现故障自动切换(如3主3从);启用密码复杂度:将
REDIS_PASSWORD改为更复杂的密码(包含大小写、数字、特殊字符),避免暴力破解;挂载自定义配置文件:如果需要修改Redis的核心配置(如
maxmemory、appendonly),可通过volumes挂载自定义的redis.conf文件;监控集群状态:使用Redis官方的
redis-cli cluster info,或第三方工具(如Prometheus + Grafana)监控集群健康度、内存使用率等指标。
评论区