简介:这份资源面向需要在 CentOS 7.x 环境下快速搭建 Redis 集群的运维人员与后端开发者,提供基于 Docker 的一键部署方案,解决手动配置多节点集群步骤繁琐、易出错的问题。压缩包共 6 个文件,约 22.46MB,以 shell 脚本为主,辅以 Redis 配置文件、离线镜像包和说明文档,脚本负责自动化构建与部署,配置文件用于集群参数设定,镜像包便于无外网环境直接导入,文档则给出参数传递与执行说明。已有 1055 人学习下载,说明该方案在实际环境中具备一定参考价值。读者按说明将参数传入安装脚本即可自动完成部署,同时可从脚本中了解容器编排、节点配置与卸载清理的完整思路,适合作为学习 Docker 化 Redis 集群部署的实操参考。
1. 用一份 shell 脚本把 Redis 集群塞进 Docker:CentOS 7 上的落地起点
一台 CentOS 7 的测试机,装完 Docker 之后想跑个 Redis 集群验证业务代码,结果redis-cli --cluster create敲到第三遍还是卡在Waiting for the cluster to join,这种场景做过的人应该都不陌生。这份资源就是冲着这个痛点来的:一个 shell 脚本,在 CentOS 7.x 上通过 Docker 一键拉起 Redis 集群,把节点目录创建、配置文件生成、容器启动、集群握手这几步串成一条命令。它解决的不是「Redis 集群原理是什么」,而是「我不想每次搭环境都重来一遍手工流程」。适合两类人:一是需要在本地或测试环境快速复现集群行为、验证分片和故障转移逻辑的后端开发者;二是刚接触 Docker 网络与 Redis Cluster 端口模型、想找一个能跑通的起点来拆解的运维新手。脚本本身不复杂,但里面关于端口映射、容器网络和集群总线端口的处理,恰恰是手工搭建时最容易翻车的地方。
2. 脚本拆开看:Redis Cluster 的端口模型与 Docker 网络怎么对齐
2.1 为什么 Redis Cluster 在 Docker 里容易「看起来起来了但连不上」
Redis Cluster 不是单端口服务。每个节点要同时暴露两个端口:客户端端口(默认 6379 起)和集群总线端口(客户端端口 + 10000,即 16379 起)。总线端口用于节点之间的 gossip 通信、故障检测和槽位迁移协商。手工在宿主机上跑没问题,因为两个端口天然可达;一旦套上 Docker,如果只-p 6379:6379,容器内部节点之间能聊,但集群创建时redis-cli从宿主机发起握手,节点回报给集群的地址是容器内网 IP,宿主机上的客户端根本路由不过去,于是卡在 join 阶段。这是第一个必须理解的点:集群模式下,节点对外宣告的地址和端口必须是从发起方视角可达的。
常见做法有两种。第一种是--network host,容器直接共享宿主机网络栈,端口模型和裸机一致,脚本最简单,但端口冲突风险高,一台机器只能跑一套。第二种是自定义 bridge 网络加固定 IP,每个容器分配一个网段内的静态地址,端口全量映射,集群创建时用宿主机 IP 加映射端口。这份脚本走的是第二种思路,因为它要在一台机器上起六个节点(三主三从),host 网络下端口会打架。理解了这个选型,后面看脚本里的--net和--ip参数就不会觉得是玄学。
2.2 节点目录与配置文件的生成逻辑
脚本启动前会为每个节点准备独立目录,通常形如/data/redis-cluster/7001/conf和/data/redis-cluster/7001/data。配置文件和持久化数据分开挂载,是为了重建容器时不丢 RDB/AOF,同时改配置不用进容器。核心配置项不多,但每一项都有讲究:
| 配置项 | 建议值 | 作用与注意点 |
|---|---|---|
| port | 7001 起递增 | 容器内客户端端口,与宿主机映射保持一致便于排查 |
| cluster-enabled | yes | 不开这个,后面所有集群命令都无从谈起 |
| cluster-config-file | nodes.conf | 节点自维护的集群状态文件,必须可写且不能手工改 |
| cluster-node-timeout | 15000 | 故障判定超时,测试环境别设太小,否则网络抖动就触发主从切换 |
| appendonly | yes | 集群模式下建议开 AOF,重启恢复更可控 |
| protected-mode | no | 容器网络内需要,宿主机侧靠防火墙兜底 |
脚本用循环批量生成这些文件,节点编号和端口做偏移。这里有个细节:cluster-config-file指向的文件在容器首次启动时不存在是正常的,Redis 会自己创建;但如果挂载目录权限不对,容器内 redis 用户写不进去,节点会反复重启,日志里只报一句Can't open the cluster config file,很容易被忽略。
2.3 一键启动脚本的关键片段与参数说明
下面这段是脚本里启动单个节点的核心逻辑,抽出来看比读整份脚本更清楚:
# 遍历节点端口,逐个启动容器 for port in 7001 7002 7003 7004 7005 7006; do node_dir="/data/redis-cluster/${port}" # 容器内固定 IP,末位与端口做映射,便于记忆和排查 ip="172.20.0.$((port - 7000 + 10))" docker run -d \ --name "redis-${port}" \ --net redis-cluster-net \ --ip "${ip}" \ -p "${port}:${port}" \ -p "$((port + 10000)):$((port + 10000))" \ -v "${node_dir}/conf/redis.conf:/usr/local/etc/redis/redis.conf" \ -v "${node_dir}/data:/data" \ redis:6.2 \ redis-server /usr/local/etc/redis/redis.conf done逐项说清楚。--net redis-cluster-net要求脚本提前docker network create --subnet=172.20.0.0/16建好网络,否则--ip直接报错。--ip用端口号做偏移,是为了让容器地址和端口一一对应,出问题时docker inspect一眼能对上号。两个-p缺一不可,第二个是总线端口,漏了就是前面说的 join 卡死。-v挂载配置文件而不是用-e传参,是因为集群配置项多,写进文件更直观,也方便后续调参。镜像版本这里用 6.2,实际脚本里通常写成变量,方便统一升级;注意 Redis 7 之后部分集群命令行为有变化,脚本如果按 6.x 写的,别随手换 latest。
启动完成后,脚本会等待几秒让节点就绪,再执行集群创建:
# 用第一个节点作为入口发起集群创建,--cluster-replicas 1 表示一主一从 docker exec -it redis-7001 redis-cli --cluster create \ 172.20.0.11:7001 172.20.0.12:7002 172.20.0.13:7003 \ 172.20.0.14:7004 172.20.0.15:7005 172.20.0.16:7006 \ --cluster-replicas 1这里用的是容器内网 IP 而不是宿主机 IP,因为docker exec进去的redis-cli处在同一网络里,节点之间互相宣告内网地址即可。--cluster-replicas 1决定主从比例,六个节点就是三主三从,前三个默认成为主节点。如果节点数不是 6 的倍数,这个参数要相应调整,否则会报槽位分配不均。执行后会出现一段交互确认,脚本里通常用--cluster-yes跳过,但第一次手动跑建议保留确认,看清楚槽位分配再继续。
3. 从零复现:CentOS 7 上的执行顺序与验证手段
3.1 前置检查与依赖确认
在 CentOS 7.x 上跑之前,先把几件事确认掉,能省掉后面一半的排查时间。Docker 版本建议 20.10 以上,docker network create --subnet的静态 IP 分配在更老的版本上行为不稳定。检查命令:
# 确认 docker 服务与版本 docker version --format '{{.Server.Version}}' # 确认内核支持 bridge 网络与端口转发 sysctl net.ipv4.ip_forward # 确认 firewalld 状态,测试环境可先关闭或放行端口段 systemctl status firewalldip_forward必须是 1,否则容器跨网段通信直接断。firewalld 在 CentOS 7 上默认开启,Docker 会自己插 iptables 规则,但集群总线端口段如果被拦,表现就是节点间时通时不通,故障转移测试永远不触发。测试环境图省事可以systemctl stop firewalld,生产环境则要显式放行 7001-7006 和 17001-17006 两段。另外确认/data所在分区有足够空间,六个节点各开 AOF,写入量大的话增长比想象中快。
3.2 执行脚本与观察启动过程
脚本一般以bash deploy-redis-cluster.sh方式执行,内部按「建网络 → 建目录 → 生成配置 → 起容器 → 等就绪 → 建集群」的顺序走。执行过程中重点看两个输出:一是docker ps里六个容器是否都是 Up 状态,有反复 Restarting 的就是配置或权限问题;二是集群创建命令的槽位分配表,正常应该看到 0-5460、5461-10922、10923-16383 三段均匀落在三个主节点上。如果某段槽位显示[OK]但节点状态是fail,多半是总线端口没通。
启动后不要急着写业务代码,先做连通性验证:
# 查看集群整体状态,重点看 cluster_state 是否为 ok docker exec -it redis-7001 redis-cli -p 7001 cluster info # 查看节点列表,确认三主三从角色和槽位 docker exec -it redis-7001 redis-cli -p 7001 cluster nodes # 从宿主机侧验证映射端口可达 redis-cli -h 127.0.0.1 -p 7001 -c set foo bar redis-cli -h 127.0.0.1 -p 7001 -c get foo-c参数不能省,集群模式下客户端要跟随MOVED重定向,不加就只能命中恰好持有该 key 槽位的节点,换一个 key 就报错,新手常误以为集群坏了。cluster info里cluster_known_nodes应该是 6,cluster_size是 3,这两个数字对不上说明握手没完成。
3.3 故障转移与扩缩容的验证方法
集群搭起来只是第一步,真正要验证的是它能不能按预期工作。最直接的测试是手动下线一个主节点,看从节点是否在cluster-node-timeout之后接管:
# 停掉一个主节点容器,模拟故障 docker stop redis-7001 # 等待超时时间后查看集群状态,原从节点应升为主 sleep 20 docker exec -it redis-7002 redis-cli -p 7002 cluster nodes观察输出里原 7001 的槽位是否转移到了它的从节点,以及该从节点的角色标记是否从slave变成master。这一步能跑通,说明总线端口、超时配置、主从复制链路都是对的。扩缩容则涉及redis-cli --cluster add-node和reshard,脚本通常不覆盖这部分,因为槽位迁移是有状态操作,不适合一键化。需要扩节点时,先按同样方式起新容器,再用add-node加入,最后reshard手动分配槽位,每一步都要看cluster nodes确认状态收敛再继续。
4. 避坑清单:这套脚本在 CentOS 7 上最容易翻车的五处
4.1 集群创建卡在 Waiting for the cluster to join
现象是--cluster create执行后长时间停在等待握手,最终超时退出。原因几乎总是总线端口没映射或没放行,节点之间无法完成 gossip 交换。解决方式是检查docker ps的端口映射是否包含+10000那一段,以及 firewalld/iptables 是否放行了该段;用docker exec进容器telnet另一个节点的总线端口,能通再重试创建。重试前记得清掉各节点 data 目录下的nodes.conf,否则残留状态会干扰新一轮握手。
4.2 容器反复重启,日志只有一行配置读取失败
现象是docker ps显示 Restarting,docker logs里报配置文件打不开或权限不足。原因是挂载的宿主机目录属主与容器内 redis 用户 UID 不匹配,CentOS 7 上默认 UID 与官方镜像里的 redis 用户经常对不上。解决办法是启动前对数据目录执行chown -R 999:999(官方镜像 redis 用户常见 UID),或者干脆在docker run里加--user指定。这个问题隐蔽在于容器不报「权限」二字,只报文件打不开,容易往配置内容上找。
4.3 宿主机客户端连上就报 MOVED,以为集群没建好
现象是用宿主机redis-cli连映射端口,set一个 key 返回MOVED重定向,换 key 又正常。这不是故障,是集群的正常行为,客户端没开集群模式。解决方式是加-c参数,或者业务侧用支持集群的客户端(如 Jedis 的JedisCluster、lettuce 的集群连接)。判断集群是否健康看cluster info的cluster_state,不要用单条命令的返回结果下结论。
4.4 主从切换测试永远不触发
现象是手动停掉主节点后,等了很久从节点也没升主。原因通常是cluster-node-timeout设得过大,或者节点间网络存在单向不通(总线端口只通了一半)。排查时先确认cluster nodes里各节点看到的彼此状态是否都是connected,再看超时配置是否与测试预期匹配。测试环境把超时设成 5000 到 15000 之间比较合适,设成 60000 就得等一分钟,容易误判为不工作。
4.5 重建环境后旧容器名冲突
现象是第二次执行脚本时docker run报 name already in use。原因是脚本没有做幂等处理,上一次的容器还在。解决方式是在脚本开头加清理逻辑,先docker rm -f掉同名容器再启动,或者用docker ps -a --filter name=redis-批量清理。更稳妥的做法是脚本里判断容器是否存在,存在则跳过或重建,而不是无脑run。这一点在反复调试配置时尤其重要,血泪经验是每次改完配置忘了清容器,跑起来还是旧参数,排查半天以为是配置没生效。
5. 把脚本改造成可复用模板:参数外置与幂等设计
原始脚本能跑通,但直接拿去别的机器上复用,往往会因为路径、端口段、镜像版本写死而需要手改多处。我一般会做两件事把它变成模板。第一件是把可变项抽到脚本头部集中定义,用变量贯穿全文:
# 集中配置区,换环境只改这一段 BASE_DIR="/data/redis-cluster" BASE_PORT=7001 NODE_COUNT=6 NET_NAME="redis-cluster-net" SUBNET="172.20.0.0/16" IMAGE="redis:6.2" TIMEOUT=15000 # 派生变量,避免散落魔法数字 BUS_PORT_OFFSET=10000 IP_PREFIX="172.20.0."这样换一台机器,改BASE_DIR和SUBNET即可,端口段和节点数联动计算,不会出现改了端口忘了改 IP 偏移的情况。第二件是加幂等保护:启动前检查网络是否存在,存在则复用;检查容器是否同名,存在则先停再删;检查数据目录是否已有nodes.conf,有则提示是否清理。幂等设计的意义不在于脚本多优雅,而在于调试阶段你能放心地反复执行,而不用每次手工收拾残局。
验证改造是否成功,有个简单办法:连续执行两次脚本,第二次应该能正常走完且集群状态不变,而不是报错退出或起出重复容器。再进一步,可以加一个--clean参数,传入时执行完整清理(停容器、删网络、清数据目录),不传时走增量启动。这套思路不限于 Redis,任何「多容器加集群握手」的部署脚本都能套用。从那以后我每次写这类一键脚本,都会先把可变参数和清理逻辑写在前头,再写启动流程,因为翻车最多的从来不是启动命令本身,而是第二次、第三次执行时的状态残留。希望帮到你。
本文还有配套的精品资源,点击获取