
简介这是一份面向Linux系统运维工程师与Docker初学者的Redis高可用集群自动化部署工具包专为CentOS 7.x环境设计解决传统Redis集群手动搭建步骤繁琐、配置易错、环境依赖复杂等痛点。资源共6个文件包含3个核心Shell脚本含自动构建、卸载及参数化部署功能、1个预拉取的Redis Docker镜像tar包、1份定制化redis.conf配置模板和1份详尽的README说明文档整体压缩包仅22.46MB轻量实用。已有1055人学习下载实测在标准CentOS 7.x服务器上一键执行即可完成6节点Redis Cluster部署涵盖网络配置、容器编排、主从分片及健康检查全流程。用户可直接复用脚本快速搭建生产级测试环境亦可基于源码理解Docker化Redis集群的启动逻辑、端口映射策略与配置注入机制是深入掌握容器化中间件部署实践的优质参考范例。1. 为什么 CentOS 7.x 上用 Shell 脚本一键部署 Redis 集群比docker-compose up更稳、更可控你有没有遇到过在 CentOS 7.x 服务器上跑docker-compose -f redis-cluster.yml up -d结果集群起不来——节点互相 ping 不通、CLUSTER NODES返回空、redis-cli --cluster create卡在 handshake不是镜像问题不是端口冲突而是 Docker 网络模式在 CentOS 7.x 的 kernel firewalld selinux 组合下对host.docker.internal解析失效、容器间--link已弃用、bridge 网络 DNS 分辨率不稳定——尤其当docker0网桥被手动修改过或与宿主机网段重叠时。这时候硬编码 IP 显式暴露端口 宿主机网络命名空间复用的 Shell 脚本方案反而成了生产环境最可靠的兜底手段。它不依赖 Docker Desktop根本不用装、不依赖docker-compose版本兼容性、不依赖--network host下的权限妥协而是用docker run原生命令逐个拉起 6 个 Redis 实例3 主 3 从通过--add-host强制注入静态解析、用--nethost复用宿主机网络栈规避 bridge 层转发延迟并在启动后用redis-cli --cluster create手动触发拓扑构建。适合运维同学批量交付、测试同学快速复现、以及那些被virtualization support not detected docker desktop failed to start because v错误劝退后回归原生 Docker CLI 的真实场景。2. 从零写一个可复用的 Redis 集群部署脚本核心逻辑拆解与最小可行命令2.1 为什么必须绕开 docker-composeCentOS 7.x 的三个硬约束在 CentOS 7.x内核 3.10.x上docker-compose的默认行为存在三处隐性风险DNS 解析不可靠docker-compose创建的自定义 bridge 网络中容器默认使用127.0.0.11作为 DNS但该地址在 CentOS 7.x 的systemd-resolved未启用时可能无响应导致redis-cli --cluster create连接其他节点超时端口映射与集群通信冲突Redis 集群要求节点间既走客户端端口6379也走集群总线端口63791000016379。docker-compose默认只映射 6379若未显式声明16379端口节点握手失败--network host模式被 compose 限制docker-compose不支持为单个服务启用host网络network_mode: host会禁用ports和links而 Redis 集群在宿主机网络下能彻底规避 NAT 和 iptables 规则干扰。因此我们放弃docker-compose.yml改用纯docker run命令链——每个 Redis 实例独立启动IP 固定为127.0.0.1因--nethost端口显式绑定集群总线端口强制暴露。2.2 脚本骨架6 个实例的端口规划与启动顺序Redis 集群最小规模是 3 主 3 从避免脑裂我们按如下端口分配全部绑定到127.0.0.1避免外网暴露角色实例编号客户端端口集群总线端口数据目录主节点1637116371/data/redis-node1主节点2637216372/data/redis-node2主节点3637316373/data/redis-node3从节点4637416374/data/redis-node4从节点5637516375/data/redis-node5从节点6637616376/data/redis-node6注意端口避开系统保留端口1024和常用服务如 6379 被默认 Redis 占用且集群总线端口 客户端端口 10000是 Redis 官方硬编码规则不可更改。脚本启动顺序必须严格先全部启动 6 个实例不配置集群关系再统一执行redis-cli --cluster create。因为 Redis 集群初始化要求所有节点处于no cluster状态且可互相访问。2.3 启动单个 Redis 实例的最小 docker run 命令以下命令启动一个监听127.0.0.1:6371的 Redis 主节点数据落盘到/data/redis-node1并暴露集群总线端口16371docker run -d \ --name redis-node1 \ --nethost \ --restartalways \ -v /data/redis-node1:/data \ -e REDIS_PORT6371 \ -e CLUSTER_PORT16371 \ -e REDIS_CONF/usr/local/etc/redis/redis.conf \ -d redis:7.2-alpine \ redis-server /usr/local/etc/redis/redis.conf \ --port 6371 \ --cluster-enabled yes \ --cluster-config-file nodes-6371.conf \ --cluster-node-timeout 5000 \ --appendonly yes \ --appendfilename appendonly.aof \ --pidfile /var/run/redis_6371.pid \ --logfile /var/log/redis_6371.log \ --dir /data \ --bind 127.0.0.1 \ --protected-mode no \ --daemonize no关键参数说明--nethost复用宿主机网络命名空间所有容器直接使用127.0.0.1无需 DNS 解析-v /data/redis-node1:/data将宿主机目录挂载为容器内/dataAOF 和 RDB 文件持久化于此--port 6371客户端连接端口--cluster-enabled yes启用集群模式必须--cluster-config-file nodes-6371.conf每个节点独立配置文件避免多实例覆盖同一文件--bind 127.0.0.1仅监听本地回环禁止外部访问安全基线--protected-mode no--nethost下必须关闭保护模式否则拒绝非127.0.0.1连接而集群握手时 Redis 内部用getaddrinfo解析自身 hostname默认返回::1或127.0.0.1但 protected-mode 会拦截--daemonize noDocker 容器要求主进程前台运行否则容器立即退出。该命令可直接在终端执行验证。成功后docker ps | grep redis-node1应显示状态Up且netstat -tlnp | grep :6371可见监听。3. 完整 Shell 脚本实现6 个节点启动 集群初始化 健康检查闭环3.1 脚本结构设计变量驱动、幂等启动、失败熔断我们采用「函数式模块」组织脚本核心函数包括init_dirs创建 6 个数据目录设置chown 999:999Redis 官方镜像默认用户 UID999start_node封装docker run命令接受端口、目录、节点名参数wait_for_nodes轮询redis-cli -p PORT ping直到全部 6 个端口返回PONGcreate_cluster调用redis-cli --cluster create传入全部 6 个127.0.0.1:PORT地址check_cluster_status执行redis-cli -p 6371 cluster info验证cluster_state:ok且cluster_known_nodes:6。脚本开头强制校验环境Docker 是否已安装且运行systemctl is-active docker /dev/null || { echo Docker 未运行; exit 1; }CentOS 版本是否为 7.xgrep -q CentOS Linux release 7\. /etc/redhat-release || { echo 仅支持 CentOS 7.x; exit 1; }firewalld是否禁用避免端口拦截systemctl is-active firewalld /dev/null { echo 请先 systemctl stop firewalld systemctl disable firewalld; exit 1; }提示firewalld是 CentOS 7.x 默认防火墙若未关闭16371-16376端口会被拦截导致集群握手超时。这是线上最常被忽略的坑。3.2 核心启动函数用 for 循环生成 6 个实例含注释版#!/bin/bash # redis-cluster-deploy.sh —— CentOS 7.x 专用 Redis 集群一键部署脚本 # 配置区 REDIS_IMAGEredis:7.2-alpine NODE_PORTS(6371 6372 6373 6374 6375 6376) DATA_ROOT/data # 配置区 init_dirs() { echo 【步骤1】创建数据目录... for port in ${NODE_PORTS[]}; do dir${DATA_ROOT}/redis-node${port} mkdir -p $dir chown 999:999 $dir # Redis 容器内 UID999必须匹配 done } start_node() { local port$1 local node_nameredis-node${port} local data_dir${DATA_ROOT}/redis-node${port} local cluster_port$((port 10000)) echo 【步骤2】启动 ${node_name} (端口 ${port}/${cluster_port})... # 检查是否已存在同名容器 if docker ps -a | grep -q $node_name; then echo 容器 $node_name 已存在跳过启动 return fi docker run -d \ --name $node_name \ --nethost \ --restartalways \ -v $data_dir:/data \ -d $REDIS_IMAGE \ redis-server /usr/local/etc/redis/redis.conf \ --port $port \ --cluster-enabled yes \ --cluster-config-file nodes-${port}.conf \ --cluster-node-timeout 5000 \ --appendonly yes \ --appendfilename appendonly.aof \ --pidfile /var/run/redis_${port}.pid \ --logfile /var/log/redis_${port}.log \ --dir /data \ --bind 127.0.0.1 \ --protected-mode no \ --daemonize no } wait_for_nodes() { echo 【步骤3】等待所有节点就绪ping 检测... local timeout60 local elapsed0 while [ $elapsed -lt $timeout ]; do local ready_count0 for port in ${NODE_PORTS[]}; do if redis-cli -p $port ping /dev/null 21; then ((ready_count)) fi done if [ $ready_count -eq ${#NODE_PORTS[]} ]; then echo 全部 ${#NODE_PORTS[]} 个节点已响应 PONG return 0 fi sleep 2 ((elapsed 2)) done echo 超时${timeout} 秒内未全部就绪检查日志docker logs redis-node6371 exit 1 } create_cluster() { echo 【步骤4】执行集群初始化... # 构建节点地址列表127.0.0.1:6371 127.0.0.1:6372 ... local nodes for port in ${NODE_PORTS[]}; do nodes$nodes 127.0.0.1:${port} done # 使用 --cluster-replicas 1 表示每个主节点配 1 个从节点3 主 3 从 if ! redis-cli --cluster create $nodes --cluster-replicas 1 /tmp/cluster-create.log 21; then echo 集群创建失败日志 cat /tmp/cluster-create.log exit 1 fi echo 集群创建成功 } check_cluster_status() { echo 【步骤5】验证集群状态... # 任选一个主节点检查 local master_port${NODE_PORTS[0]} local info$(redis-cli -p $master_port cluster info 2/dev/null) if echo $info | grep -q cluster_state:ok \ echo $info | grep -q cluster_known_nodes:6; then echo ✅ 集群健康6 个节点已识别状态 OK echo 当前主节点分布 redis-cli -p $master_port cluster nodes | grep master | head -3 | awk {print $2,$3} else echo ❌ 集群状态异常请检查 echo $info exit 1 fi }逻辑说明init_dirs中chown 999:999是关键Redis Alpine 镜像以 UID999 用户运行若宿主机目录属主为 root容器内无法写入 AOF 文件启动后立即 crashstart_node函数内if docker ps -a | grep -q $node_name实现幂等重复执行脚本不会重启已有容器避免数据丢失wait_for_nodes使用redis-cli -p PORT ping而非docker ps因为容器 Up 不代表 Redis 进程已 ready加载配置、AOF 重放需时间create_cluster中$nodes字符串拼接必须无空格首尾否则redis-cli --cluster create解析失败这是grep在 shell 脚本中常见用法的典型陷阱空格导致参数截断。3.3 主流程串联函数并加入错误捕获main() { set -e # 任何命令失败立即退出 trap echo ❌ 脚本执行中断错误行号: $LINENO; exit 1 ERR echo Redis 集群部署脚本启动CentOS 7.x init_dirs for port in ${NODE_PORTS[]}; do start_node $port done wait_for_nodes create_cluster check_cluster_status echo ✅ 部署完成集群地址127.0.0.1:6371主节点 echo 测试命令redis-cli -p 6371 cluster nodes } main $set -e与trap的作用set -e保证任意子命令失败如docker run权限不足、redis-cli ping超时立即终止不继续执行后续步骤trap捕获ERR信号输出具体失败行号方便定位——这是 Shell 脚本调试的后悔药没有它你只能靠echo二分法排查。4. 避坑指南CentOS 7.x 上 Redis 集群部署的 5 个血泪经验4.1 现象redis-cli --cluster create报错Node 127.0.0.1:6371 is not empty. Either the node already knows other nodes...原因宿主机/data/redis-node6371/nodes-6371.conf文件残留旧集群元数据如上次部署未清理Redis 启动时自动加载该文件认为节点已加入集群。解决在init_dirs函数中增加清理逻辑for port in ${NODE_PORTS[]}; do dir${DATA_ROOT}/redis-node${port} rm -f $dir/nodes-${port}.conf $dir/appendonly.aof $dir/dump.rdb mkdir -p $dir chown 999:999 $dir done4.2 现象docker run启动后容器立即退出docker logs redis-node6371显示Could not create server TCP listening socket 127.0.0.1:6371: bind: Cannot assign requested address原因宿主机127.0.0.1:6371端口已被占用如旧 Redis 进程未 kill或--bind 127.0.0.1在--nethost下与 IPv6 冲突CentOS 7.x 默认启用 IPv6。解决执行lsof -i :6371查杀占用进程在docker run命令中显式添加--ipv6false参数虽--nethost下无效但部分内核版本需此开关更稳妥做法改用--bind 127.0.0.1 --bind ::1双栈绑定Redis 7.0 支持。4.3 现象集群创建成功但redis-cli -p 6371 cluster nodes显示部分节点fail?状态且ping不通原因firewalld或iptables拦截了16371-16376集群总线端口非客户端端口导致节点间心跳包丢弃。解决systemctl stop firewalld systemctl disable firewalld # 若必须启用防火墙则开放端口 firewall-cmd --permanent --add-port6371-6376/tcp firewall-cmd --permanent --add-port16371-16376/tcp firewall-cmd --reload4.4 现象redis-cli --cluster create卡住不动日志显示Waiting for the cluster to join原因--protected-mode no缺失。--nethost下 Redis 默认仍启用保护模式拒绝来自::1IPv6 localhost的连接而集群握手时内部使用getaddrinfo解析 hostname可能返回::1。解决确保docker run命令中包含--protected-mode no且该参数在redis-server启动参数末尾位置敏感放在--bind之后。4.5 现象脚本执行到create_cluster时报错redis-cli: command not found原因宿主机未安装redis-cliDocker 容器内有但集群创建命令需在宿主机执行。解决脚本开头增加依赖检查if ! command -v redis-cli /dev/null; then echo redis-cli 未安装正在安装... yum install -y redis fi注意CentOS 7.x 自带redis包版本较低3.2但redis-cli --cluster功能从 3.0 起已存在足够使用。若需高版本 CLI可curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg echo deb [arch$(dpkg --print-architecture) signed-by/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main | sudo tee /etc/apt/sources.list.d/redis.list sudo apt-get update sudo apt-get install -y redis-cli—— 但这是 Ubuntu 语法CentOS 7.x 必须用yum install redis。5. 验证与压测确认集群真可用不止是“看起来正常”5.1 用redis-cli手动验证读写分离与故障转移集群部署完成后不能只信cluster info必须实测# 1. 连接任意节点自动重定向到正确 slot redis-cli -p 6371 set hello world # 输出OK # 2. 读取验证 key 路由正确 redis-cli -p 6371 get hello # 输出world # 3. 查看 key 所在槽位和节点 redis-cli -p 6371 cluster keyslot hello # 输出866槽位号 redis-cli -p 6371 cluster nodes | grep 866- # 输出应包含主节点地址如 127.0.0.1:637116371 master - 0 171xxxxxxx 0 connected 0-5460 # 4. 模拟主节点宕机kill 容器 docker kill redis-node6371 sleep 10 # 等待从节点提升为主 # 5. 检查新主节点原从节点 6374 应升级 redis-cli -p 6374 cluster nodes | grep master | grep -E (6374|6371) # 应看到 6374 为 master6371 为 fail关键点redis-cli -p 6371 set hello world成功不代表写入成功——如果 6371 是从节点该命令会重定向到主节点执行。真正验证需cluster keyslot定位槽位再cluster nodes确认该槽位当前 master 地址。5.2 用redis-benchmark压测集群吞吐对比单节点单节点 Redis6379与 3 主 Redis 集群6371-6373的吞吐差异是检验部署质量的终极标尺# 对单节点压测基准 redis-benchmark -h 127.0.0.1 -p 6379 -n 100000 -c 50 -t set,get # 对集群压测需指定 -c 与 -n且 key 带 {} 确保路由到同一槽 redis-benchmark -h 127.0.0.1 -p 6371 -n 100000 -c 50 -t set,get \ --key-pattern user:{id} \ --csv cluster-bench.csv解读结果单节点SETQPS 约 8~10w取决于 CPU3 主集群SETQPS 应达 24~30w线性扩展若仅 12w说明客户端未正确打散 key如全用user:1导致所有请求落到同一主节点--key-pattern user:{id}中{id}触发哈希标签hash tag确保相同{id}的 key 落在同一槽不同{id}打散到不同主节点。我的习惯是每次部署完必跑redis-benchmark并用top -p $(pgrep redis-server)观察各节点 CPU 是否均衡。如果redis-node6371CPU 90%其余节点 10%一定是 key 设计没加 hash tag或者客户端 SDK 未开启集群模式如 Jedis 需JedisCluster非Jedis。5.3 生产级检查清单5 项必须确认的配置检查项命令合格标准不合格后果AOF 持久化启用redis-cli -p 6371 config get appendonlyappendonly,yes宕机丢失全部内存数据集群总线端口监听ss -tlnp | grep :16371LISTEN状态PID 为 redis-server节点间无法握手集群分裂数据目录权限ls -ld /data/redis-node6371drwxr-xr-x 999 999容器内 Redis 无法写入 AOF反复 crashprotected-mode 关闭redis-cli -p 6371 config get protected-modeprotected-mode,no集群节点间连接被拒绝firewalld 状态systemctl is-active firewalldinactive16371-16376端口被拦截心跳超时把这 5 行命令存为check-production.sh每次上线前执行——这是我踩过三次数据丢失事故后养成的肌肉记忆。希望帮到你。本文还有配套的精品资源点击获取