redis集群配置
以下通过docker启动多实例配置Redis 集群案例,让你学会如何在生产环境中如何部署redis集群,以及其它注意点。
一、docker启动多实例配置Redis 集群
1. 架构设计
三主三从
2. 环境准备
- 工具依赖:安装 Docker 和 Docker Compose。
- 目录规划:在本地创建配置目录(如
redis-cluster
),并在其中创建子目录nodes
(用于存储集群节点数据)和conf
(用于存储 Redis 配置文件)。
cd ~
创建目录
for i in {1..6}; domkdir -p data/redis-cluster/nodes$i/conf data/redis-cluster/nodes$i/data
done
3. 编写 Redis 配置文件(conf/redis.conf
)
port ${PORT} # 端口号,通过环境变量动态替换
cluster-enabled yes # 开启集群模式
cluster-config-file nodes.conf # 集群配置文件(自动生成)
cluster-node-timeout 5000 # 节点超时时间,超时后会被认为不可用。
appendonly yes # 启用AOF持久化,保证数据安全性。
dir /data # 数据存储目录
结合命令行工具快速生成各节点配置:
vi configure.sh
for i in {1..6}; doport=$((7000 + i))cat > data/redis-cluster/nodes${i}/conf/redis.conf <<EOF
port ${port}
cluster-enabled yes
cluster-config-file /data/nodes.conf
appendonly yes
dir /data
EOF
done
4. 编写 Docker Compose 编排文件(docker-compose.yml
)
注意事项:
- 确保各服务器之间的网络互通(需开放 Redis 端口和集群总线端口 port+10000,如 7001 对应 17001)。
version: '3'
services:redis1:image: redis:7.0-alpine # 使用轻量级 Alpine 镜像container_name: redis1ports:- "7001:7001" # 映射宿主机端口 7001 到容器端口(与配置文件中的 ${PORT} 对应)- "17001:17001" # 新增:集群总线端口(7001+10000)environment:- PORT=7001volumes:- /Users/lantai/data/redis-cluster/nodes1/conf/redis.conf:/usr/local/redis.conf- /Users/lantai/data/redis-cluster/nodes1/data:/datacommand: ["redis-server", "/usr/local/redis.conf"]redis2:image: redis:7.0-alpinecontainer_name: redis2ports:- "7002:7002"- "17002:17002"environment:- PORT=7002volumes:- /Users/lantai/data/redis-cluster/nodes2/conf/redis.conf:/usr/local/redis.conf- /Users/lantai/data/redis-cluster/nodes2/data:/datacommand: ["redis-server", "/usr/local/redis.conf"]redis3:image: redis:7.0-alpinecontainer_name: redis3ports:- "7003:7003"- "17003:17003"environment:- PORT=7003volumes:- /Users/lantai/data/redis-cluster/nodes3/conf/redis.conf:/usr/local/redis.conf- /Users/lantai/data/redis-cluster/nodes3/data:/datacommand: ["redis-server", "/usr/local/redis.conf"]redis4:image: redis:7.0-alpinecontainer_name: redis4ports:- "7004:7004"- "17004:17004"environment:- PORT=7004volumes:- /Users/lantai/data/redis-cluster/nodes4/conf/redis.conf:/usr/local/redis.conf- /Users/lantai/data/redis-cluster/nodes4/data:/datacommand: ["redis-server", "/usr/local/redis.conf"]redis5:image: redis:7.0-alpinecontainer_name: redis5ports:- "7005:7005"- "17005:17005"environment:- PORT=7005volumes:- /Users/lantai/data/redis-cluster/nodes5/conf/redis.conf:/usr/local/redis.conf- /Users/lantai/data/redis-cluster/nodes5/data:/datacommand: ["redis-server", "/usr/local/redis.conf"]redis6:image: redis:7.0-alpinecontainer_name: redis6ports:- "7006:7006"- "17006:17006"environment:- PORT=7006volumes:- /Users/lantai/data/redis-cluster/nodes6/conf/redis.conf:/usr/local/redis.conf- /Users/lantai/data/redis-cluster/nodes6/data:/datacommand: ["redis-server", "/usr/local/redis.conf"]
分配指定ip模式
- 使用固定 IP 或域名,避免容器重启后 IP 变动导致集群断裂。
自定义一个集群专属网桥
docker network create \--driver bridge \--subnet 172.18.0.0/16 \--gateway 172.18.0.1 \redis_netdocker network inspect redis_net
services:redis1:image: redis:7.0-alpinecontainer_name: redis1# 网络配置networks:redis_net:ipv4_address: 172.18.0.2 ports:- "7001:7001"- "17001:17001" environment:- PORT=7001volumes:- /Users/lantai/data/redis-cluster/nodes1/conf/redis.conf:/usr/local/redis.conf- /Users/lantai/data/redis-cluster/nodes1/data:/datacommand: ["redis-server", "/usr/local/redis.conf"]redis2:image: redis:7.0-alpinecontainer_name: redis2# 网络配置networks:redis_net:ipv4_address: 172.18.0.3ports:- "7002:7002"- "17002:17002"environment:- PORT=7002volumes:- /Users/lantai/data/redis-cluster/nodes2/conf/redis.conf:/usr/local/redis.conf- /Users/lantai/data/redis-cluster/nodes2/data:/datacommand: ["redis-server", "/usr/local/redis.conf"]redis3:image: redis:7.0-alpinecontainer_name: redis3# 网络配置networks:redis_net:ipv4_address: 172.18.0.4ports:- "7003:7003"- "17003:17003"environment:- PORT=7003volumes:- /Users/lantai/data/redis-cluster/nodes3/conf/redis.conf:/usr/local/redis.conf- /Users/lantai/data/redis-cluster/nodes3/data:/datacommand: ["redis-server", "/usr/local/redis.conf"]redis4:image: redis:7.0-alpinecontainer_name: redis4# 网络配置networks:redis_net:ipv4_address: 172.18.0.5ports:- "7004:7004"- "17004:17004"environment:- PORT=7004volumes:- /Users/lantai/data/redis-cluster/nodes4/conf/redis.conf:/usr/local/redis.conf- /Users/lantai/data/redis-cluster/nodes4/data:/datacommand: ["redis-server", "/usr/local/redis.conf"]redis5:image: redis:7.0-alpinecontainer_name: redis5# 网络配置networks:redis_net:ipv4_address: 172.18.0.6ports:- "7005:7005"- "17005:17005"environment:- PORT=7005volumes:- /Users/lantai/data/redis-cluster/nodes5/conf/redis.conf:/usr/local/redis.conf- /Users/lantai/data/redis-cluster/nodes5/data:/datacommand: ["redis-server", "/usr/local/redis.conf"]redis6:image: redis:7.0-alpinecontainer_name: redis6# 网络配置networks:redis_net:ipv4_address: 172.18.0.7ports:- "7006:7006"- "17006:17006"environment:- PORT=7006volumes:- /Users/lantai/data/redis-cluster/nodes6/conf/redis.conf:/usr/local/redis.conf- /Users/lantai/data/redis-cluster/nodes6/data:/datacommand: ["redis-server", "/usr/local/redis.conf"]
# 添加 networks 部分,声明 redis_net 为外部网络
networks:redis_net:external: true
5. 启动容器并初始化集群
启动所有 Redis 实例:
# docker-compose -p myproject up -d
docker-compose -p redis-cluster up -d
或者
docker compose -p redis-cluster up -d
直接运行 docker-compose up -d ,会依据当前docker-compose.yml所在目录的目录名称,生成项目名
使用 redis-cli
初始化集群
进入一个容器 中执行集群创建:
# 宿主机上安装redis(redis-cli工具), 想宿主机进行管理集群,测试了不行
# 初始化集群(3 主 3 从,主节点为 7001、7002、7003,从节点为 7004、7005、7006)
redis-cli --cluster create \-a "你的密码" \ # 指定连接所有节点的统一密码,如果有,这里配置文件里没设置172.18.0.2:7001 172.18.0.3:7002 172.18.0.4:7003 \172.18.0.5:7004 172.18.0.6:7005 172.18.0.7:7006 \--cluster-replicas 1
# 无密码
redis-cli --cluster create \172.18.0.2:7001 172.18.0.3:7002 172.18.0.4:7003 \172.18.0.5:7004 172.18.0.6:7005 172.18.0.7:7006 \--cluster-replicas 1
--cluster-replicas 1
:指定每个主节点对应 1 个从节点。
测试端口连通性
nc -vz 172.18.0.2 7001
nc -vz 172.18.0.2 17001
验证集群状态
redis容器中
/data # redis-cli -p 7001 cluster nodes
d50856317e509ab8add95baa06c2324bc97b5e8d 172.18.0.3:7002@17002 master - 0 1747807849000 2 connected 5461-10922
bef486e0773ee8efb8bb4b9425115af7ccce4a65 172.18.0.2:7001@17001 myself,master - 0 1747807848000 1 connected 0-5460
1fd3bb65f20b8091fa89c2959bcfc2deef7af1a6 172.18.0.6:7005@17005 slave bef486e0773ee8efb8bb4b9425115af7ccce4a65 0 1747807849411 1 connected
a3fe31a1b726f626b4703d3ebb77ccec0a9182af 172.18.0.4:7003@17003 master - 0 1747807847000 3 connected 10923-16383
e48ea426732610b3a8e058e4955fc8b16b50f717 172.18.0.5:7004@17004 slave a3fe31a1b726f626b4703d3ebb77ccec0a9182af 0 1747807847000 3 connected
c55ed02356d4ef3d5ddfed8e8da15b6fe33d0809 172.18.0.7:7006@17006 slave d50856317e509ab8add95baa06c2324bc97b5e8d 0 1747807847332 2 connected
/data # redis-cli -p 7001 cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:321
cluster_stats_messages_pong_sent:297
cluster_stats_messages_fail_sent:3
cluster_stats_messages_sent:621
cluster_stats_messages_ping_received:297
cluster_stats_messages_pong_received:317
cluster_stats_messages_fail_received:1
cluster_stats_messages_received:615
total_cluster_links_buffer_limit_exceeded:0
以下是对 Redis 集群状态输出的详细解析及说明:
核心状态指标
- 集群整体状态
cluster_state:ok
说明:集群处于健康状态,所有主节点和槽位(slot)正常工作,无故障节点或未分配的槽位。
注意:若显示cluster_state:fail
,表示集群不可用,需排查故障节点或槽位。
- 槽位(Slot)状态
cluster_slots_assigned:16384
说明:Redis 集群共有 16384 个槽位,当前全部已分配给主节点。cluster_slots_ok:16384
说明:所有槽位均处于正常状态(主节点可访问,从节点同步正常)。cluster_slots_pfail:0
说明:无槽位处于“疑似故障”(possible fail)状态(通常由节点间心跳超时触发)。cluster_slots_fail:0
说明:无槽位处于“已确认故障”(fail)状态(需通过投票机制确认)。
- 节点状态
cluster_known_nodes:6
说明:集群中已知的节点总数为 6 个(包括主节点和从节点)。cluster_size:3
说明:当前集群中的主节点数量为 3 个(每个主节点负责一部分槽位)。cluster_current_epoch:6
说明:集群的当前纪元(epoch),用于选举新主节点时的版本号管理,数值越大表示集群状态越新。cluster_my_epoch:1
说明:当前节点的纪元(该节点首次加入集群时的 epoch 值),用于区分不同节点的选举周期。
网络与通信指标
- 消息发送统计
cluster_stats_messages_ping_sent:321
说明:已发送的PING
消息数(用于节点间心跳检测)。cluster_stats_messages_pong_sent:297
说明:已发送的PONG
消息数(对PING
的响应,携带节点状态信息)。cluster_stats_messages_fail_sent:3
说明:已发送的FAIL
消息数(通知其他节点某主节点已故障)。cluster_stats_messages_sent:621
说明:总发送消息数(PING
+PONG
+FAIL
+其他类型)。
- 消息接收统计
cluster_stats_messages_ping_received:297
说明:已接收的PING
消息数。cluster_stats_messages_pong_received:317
说明:已接收的PONG
消息数。cluster_stats_messages_fail_received:1
说明:已接收的FAIL
消息数(表示有其他节点检测到故障)。cluster_stats_messages_received:615
说明:总接收消息数。
- 缓冲区状态
total_cluster_links_buffer_limit_exceeded:0
说明:节点间通信的缓冲区未超限(若大于 0,可能存在网络拥塞或节点负载过高)。
集群健康度评估
健康状态
当前输出显示集群处于 完全健康状态,关键指标特征:
- 所有槽位已分配且正常(
cluster_slots_assigned=ok=16384
,pfail=fail=0
)。 - 主节点数量与集群规模一致(
cluster_size=3
),节点总数包含从节点(如 3 主 + 3 从)。 - 节点间通信正常,消息收发均衡,无故障通知(
fail_sent/received
数值极低)。
潜在问题排查方向
若后续指标出现异常,可参考以下维度:
cluster_state:fail
- 检查
cluster_slots_fail
是否大于 0,定位故障主节点。 - 查看
cluster_known_nodes
是否减少,确认是否有节点下线。
- 检查
cluster_slots_pfail
** 升高**- 可能因节点间网络延迟或心跳超时(默认每秒发送
PING
,超时时间cluster-node-timeout
)。
- 可能因节点间网络延迟或心跳超时(默认每秒发送
- 消息发送/接收失衡(如
PING
发送远多于接收)- 可能存在部分节点无法响应,需检查节点日志或网络连通性。
总结
当前 Redis 集群运行正常,所有槽位分配完整,节点间通信良好,无故障或异常状态。可继续监控 cluster_state
、槽位状态及节点通信指标,确保集群持续稳定。
测试集群
在第一台机器上连接集群的7001端口的节点,在另外一台连接7005节点
连接方式为 redis-cli -h -c -p 加参数 -c 可连接到集群。
在7001节点执行命令 set hello world ,执行结果如下:
/data # hostname -i
172.18.0.2
/data # redis-cli -h 172.18.0.2 -c -p 7001
172.18.0.2:7001> set hello world
OK
172.18.0.2:7001> get hello
"world"
redis6从节点上查询数据
从节点上新增数据看看:
数据会自动分配到主节点上去。
管理工具下载地址:https://redisdesktop.com/download
docker-compose 常用维护命令:
# 停止容器
docker-compose stop
# 启动容器
docker-compose start
# 删除容器
docker-compose down
# 重新创建容器
docker-compose up -d
- 停止容器后再启动(docker-compose stop + docker-compose start),IP 地址通常不变(Docker 会保留已分配的 IP 给该容器,除非手动删除容器)。
- 删除容器后重新创建(docker-compose down + docker-compose up),IP 地址可能变化(取决于地址池是否有空闲 IP)。
二、关键配置与优化
1. Redis 配置优化
- 内存限制:通过
maxmemory
和maxmemory-policy
配置内存策略(如allkeys-lru
)。 - 持久化:生产环境建议同时开启 RDB 和 AOF(
appendonly yes
),并定期备份。 - 集群参数:
cluster-require-full-coverage no # 允许部分 slot 未分配(测试环境可选)
cluster-slave-validity-factor 10 # 从节点失效判定时间
2. 容器配置优化
- 资源限制:使用 Docker 限制 CPU 和内存(避免资源竞争):
resources:limits:memory: 2gcpus: "1"
- 数据持久化:将容器内的
/data
目录挂载到宿主机或云存储(如 AWS EBS、NFS),避免容器删除导致数据丢失。
三、集群管理与维护
1. 常用操作命令
- 添加节点(新节点作为从节点加入):
redis-cli --cluster add-node new-node-ip:port existing-master-ip:port
- 移除节点(需先迁移数据):
redis-cli --cluster del-node target-ip:port node-id
- 重新分片(调整 slot 分布):
redis-cli --cluster reshard master-ip:port
# 添加节点
redis-cli --cluster add-node new_host:new_port existing_host:existing_port# 删除节点
redis-cli --cluster del-node host:port node_id# 重新分片
redis-cli --cluster reshard host:port# 故障转移
redis-cli -c -p 7000 cluster failover# 查看集群信息
redis-cli -c -p 7000 cluster info
2. 监控与告警
- 工具推荐:
- Prometheus + Grafana:通过
redis_exporter
采集指标(如内存使用率、命中率、集群状态)。 - RedisInsight:官方可视化监控工具,支持集群管理。
- Prometheus + Grafana:通过
- 告警规则:
- 内存使用率超过 80% 时触发告警。
- 主从同步延迟超过 10 秒时触发告警。
- 集群中失效节点数超过
quorum
(仲裁值)时触发故障告警。
四、高可用性与容灾
1. 主从复制
- 集群默认通过
--cluster-replicas
参数自动分配从节点,确保主节点故障时自动 failover。
2. 跨机房部署
- 将集群节点分散到不同机房(如机房 A、B、C),云上分布在多可用区,避免单机房故障导致集群不可用。
- 结合负载均衡器(如 Nginx、HAProxy)对外提供服务,支持自动切换节点。
五、常见问题与解决方案
问题现象 | 可能原因 | 解决方案 |
---|---|---|
集群初始化失败 | 相应端口未开放或节点 IP 错误 | 检查防火墙规则,确保节点间可通信;使用正确的 IP 和端口重新初始化。 |
从节点未正常复制主节点数据 | 主从配置错误或网络延迟过高 | 检查 cluster nodes 输出,确认从节点是否正确指向主节点;优化网络环境。 |
写入数据时提示 “MOVED” 错误 | slot 未正确分配或集群状态不一致 | 使用 redis-cli cluster check 检查 slot 分布,重新分片或修复集群状态。 |
通过以上方案,可在容器环境中快速搭建高可用的 Redis 集群。
测试环境建议使用单机多实例模拟,生产环境需结合实际服务器资源和网络架构进行部署,并做好监控和备份。