简介:面向 CentOS 7.x 环境下的运维与开发人员,提供一套基于 Docker 的 Redis 集群一键部署 Shell 脚本,解决手工搭建步骤繁琐、重复操作多的问题,尤其适合需要快速交付或频繁重建集群的场景,理解 Docker 与 Redis 基本概念即可上手。资源包共 6 个文件,包括 3 个 Shell 脚本、1 个 Redis 配置文件、1 个离线镜像 tar 包和 1 份说明文档,整体约 22.46MB,结构精简清晰;脚本覆盖自动部署、扩展构建与卸载,配置文件支持自定义端口、副本数等集群参数。已有 1055 人学习下载,脚本经作者实测可用,具备实战参考价值。按 README 提示将参数传给安装脚本,即可自动加载镜像并完成集群部署;同时配套的 tar 镜像和 conf 解决了离线环境镜像导入与自定义配置的常见需求,适合作为生产或测试环境中 Redis 集群快速交付的参考工具。
1. 为什么 Redis 集群在 CentOS7.x 上反而最难搞:先理清一键脚本要解决什么
我见过太多人在 CentOS7.x 上部署 Redis 集群时,光是安装 Docker、调网络就花了半天。单机 Redis 的瓶颈一旦出现,主从结构只能解决读多写少的场景,要扛住写压力和高可用,最终还是要落到 Redis Cluster 上,而用 Shell 脚本做一键部署,正是把 Docker 操作和集群初始化固定成一条流水线的最佳方式。很多人觉得集群部署就是把几个 redis-server 塞进容器里跑起来,结果第一步就被端口规划、防火墙、容器 IP 漂移这类环境问题绊住。用一套 Docker 加 Shell 脚本的方案,把环境检查、配置生成、容器启动、集群初始化和故障验证全部串起来,一条命令拉起三主三从,才是真正能落地的工程化做法。这篇文章适合 CentOS7.x 上从零起步的运维,也适合想要一套可复现集群部署流程的开发。
2. 环境核查与选型:CentOS7.x 的 Docker 版本、网络与目录规划
2.1 为什么 CentOS7.x 上要先查内核:Docker 不是装好就能用
CentOS7.x 默认内核 3.10.x,而 Docker 的 overlay2 存储驱动、namespaces 等特性在新版本里对内核要求越来越高。这不是玄学,是社区里大量真实反馈堆出来的结论。我见过 CentOS 7.4 上装 Docker 20.10 后,容器创建时报operation not supported,一查日志,是内核的 mount 参数不支持 overlay2 的metacopy,最后只能升级内核解决。所以在部署脚本里,环境检查的第一项就是内核版本。
脚本里最合理的环境检查顺序是这样:
#!/bin/bash KERNEL_VERSION=$(uname -r | awk -F. '{print $1}') KERNEL_MINOR=$(uname -r | awk -F. '{print $2}') # CentOS7.x 最低要求 3.10,生产建议 4.18+ if [ "$KERNEL_VERSION" -lt 3 ] || { [ "$KERNEL_VERSION" -eq 3 ] && [ "$KERNEL_MINOR" -lt 10 ]; }; then echo "内核版本过低:$(uname -r),Redis Cluster 部署需要至少 3.10 以上内核" exit 1 fi逻辑说明:uname -r在 CentOS7 上的输出类似3.10.0-1160.el7.x86_64,用 awk 按点拆出第一二段,再和数值比大小。脚本里只卡 3.10 下限,但如果你要跑 Docker 最新版,建议把阈值提到 4.18,升级内核用yum install kernel-lt或者加 elrepo-release 源,这是 CentOS7.x 的常规操作。
Docker 版本同样要检查。CentOS 自带的 docker 包是远古版本,千万别用,这套 docker 安装教程的第一步就是卸载它。常见做法是走 Docker CE 官方源:
# 检查 docker 是否存在 if ! command -v docker >/dev/null 2>&1; then echo "未安装 Docker,开始安装 Docker CE..." yum install -y yum-utils yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo yum install -y docker-ce docker-ce-cli containerd.io systemctl enable docker systemctl start docker fi # 检查版本,低于 19.03 就提示升级 DOCKER_VERSION=$(docker version --format '{{.Server.Version}}' 2>/dev/null) if [ -z "${DOCKER_VERSION}" ]; then echo "Docker 服务未启动或安装异常" exit 1 fi echo "当前 Docker 版本:${DOCKER_VERSION}"这里docker version --format是标准模板输出,能直接拿到 server 版本。19.03 是跨入稳定期的重要节点,早于它的版本在容器网络和资源限制上有一堆历史 bug,集群体系不如 20.10+ 清晰。CentOS7.x 上的 Docker 安装教程都大同小异,但真正的问题基本不在安装本身,而在安装完之后的存储驱动和网络。
装完后再看一眼存储驱动:如果docker info里 Storage Driver 不是 overlay2,而是 vfs 或者 device mapper,那容器性能会差很多。遇到这种情况,先看/etc/docker/daemon.json是否设置了"storage-driver": "overlay2",再看内核模块有没有加载。
2.2 网络和目录规划:端口、IP 和持久化目录定下来再动工
这一步是决定整个集群能不能跨主机连通的基础。Redis Cluster 的端口规划有一条铁律:每个节点监听两个端口,一个客户端端口,另一个是集群总线端口,默认是客户端端口加 10000。总线端口仅用于节点间通信、失败检测和配置传播,防火墙必须放行。
我一般用三台机器、每台两个节点,或者六台机器各一节点,看手头资源。测试环境用一台 CentOS7.x 虚拟机就能模拟:6379、6380、6381 三个客户端端口,16379、16380、16381 对应集群总线。目录规划如下:
/opt/redis-cluster/ ├── 6379/ │ ├── data/ # RDB/AOF 持久化文件 │ └── conf/ # redis.conf ├── 6380/ └── 6381/脚本的开头部分就是创建目录和检查磁盘:
BASE_DIR="/opt/redis-cluster" PORTS=(6379 6380 6381) for PORT in "${PORTS[@]}"; do mkdir -p "${BASE_DIR}/${PORT}/data" "${BASE_DIR}/${PORT}/conf" done DISK_FREE=$(df -P "${BASE_DIR}" | awk 'NR==2 {print $4}') if [ "${DISK_FREE}" -lt 5242880 ]; then echo "磁盘剩余空间不足 5GB,集群数据可能占满磁盘" exit 1 fi参数说明:df -P的第四列是空闲 KB,数值 5242880 对应 5GB。为什么至少 5GB?三个主节点的 RDB 快照加 AOF 重写,数据量在测试阶段不大,但谁知道你后面往里面灌了多少离线分析结果。提前检查这一步不亏,省得后面 AOF 重写把磁盘写满,整个集群进入 OOM 或者只读故障。
防火墙放行这一步,CentOS7.x 用 firewalld,脚本里这样处理:
for PORT in "${PORTS[@]}"; do firewall-cmd --permanent --add-port=${PORT}/tcp firewall-cmd --permanent --add-port=$((PORT+10000))/tcp done firewall-cmd --reload同时放行了 6379 和 16379 这类配对端口。如果你在云环境,别忽略安全组那一层——云安全组不放行,主机防火墙怎么开都没用。集群初始化时卡在Waiting for the cluster to join,十有八九和这两层端口策略有关。
2.3 镜像选择与预拉取:固定 tag,拒绝 latest 黑匣子
镜像选择看似小事,实则影响运维。Redis 镜像有两个大坑:
第一,不要用redis:latest。这个 tag 跟着官方滚动更新,你上周部署和今天部署拿到的可能是不同大版本,之后想复现问题、对比数据都很被动。而且 latest 底下的系统版本也在频繁更换,出问题的时候没法精确回滚。
第二,宿主机上别依赖系统自带的 Redis 客户端。CentOS7.x 的 yum 源里 redis 版本可能是 3.x 或 5.x,拿老版本 redis-cli 去操作 Redis 7.x 的集群,某些命令的行为对不上,徒增排错成本。最稳的方式就是把客户端调用也注入到容器里,用docker exec redis-6379 redis-cli ...这种方式。
脚本里预拉取镜像并缓存,判断如下:
REDIS_IMAGE="redis:7.2" if ! docker image inspect "${REDIS_IMAGE}" >/dev/null 2>&1; then echo "首次使用,拉取镜像 ${REDIS_IMAGE}..." timeout 180 docker pull "${REDIS_IMAGE}" if [ $? -ne 0 ]; then echo "镜像拉取失败,请检查网络或配置镜像加速器" exit 2 fi fidocker image inspect比docker images | grep更准确:grep 可能把redis:7.2-rc或者自定义 tag 误匹配进来,而 inspect 是按精确镜像名查。timeout 180防止网络异常时脚本永久挂起。CentOS7.x 上如果镜像拉取慢,配置/etc/docker/daemon.json的 registry-mirrors 是常见做法,这个后面会在避坑章节提。
3. 写集群部署 Shell 脚本:从 redis.conf 生成到三主三从初始化
这一章是整个标题的核心实操部分,按「生成配置 → 启动容器 → 初始化集群」三步走。整套脚本跑完,你得到的是一个 cluster_state 为 ok 的六节点集群。
3.1 生成 redis.conf:Cluster 模式必需的配置项逐个解释
Redis Cluster 模式对 redis.conf 有硬性要求。下面这几行缺一不可,否则 Redis 启动后根本进不了 cluster 状态:
HOST_IP=$(ip addr show eth0 | grep 'inet ' | awk '{print $2}' | cut -d/ -f1) PORT=6379 cat > /opt/redis-cluster/${PORT}/conf/redis.conf << REDIS_EOF port ${PORT} bind 0.0.0.0 cluster-enabled yes cluster-config-file nodes-${PORT}.conf cluster-node-timeout 5000 appendonly yes appendfsync everysec protected-mode no dir /data logfile "" REDIS_EOF逐项说明:
cluster-enabled yes:最核心的开关,不开这个,Redis 就只是单实例,不会参加槽位分配和故障转移。cluster-config-file nodes-${PORT}.conf:集群状态文件,Redis 启动时读取、运行时动态更新,记录节点 ID、主从关系和槽位分配。注意这个文件的路径受dir约束。cluster-node-timeout 5000:节点间判定失败的超时时间。默认 15000,测试环境我习惯调成 5000,让故障转移更快。生产环境建议维持 15000 或至少 10000,设置太短容易在网络抖动时误判。appendonly yes加appendfsync everysec:每秒刷一次 AOF,故障时最多丢一秒数据。对 Redis Cluster 来说,数据安全比性能波动重要。bind 0.0.0.0:容器网络里必须监听所有接口,否则其他节点的请求进不来。protected-mode no:设置了密码的前提下其实保留 yes 也安全,但没有密码的测试环境,protected-mode 会限制来自其他节点的访问,白白制造连接问题。
关于dir /data:容器内工作目录必须是挂载的持久化目录。如果不设,Redis 会把 RDB 和 nodes.conf 写到镜像层的默认目录,容器删除后数据全丢。用前面建的宿主机目录/opt/redis-cluster/${PORT}/data挂到容器/data,就不会写丢。
3.2 docker run 启动容器:为什么我在 CentOS7.x 上坚持用 host 网络
Redis 容器启动方式不是唯一的,但网络模式的选择直接决定你有没有坑。标准做法是-p 6379:6379做端口映射,但在 CentOS7.x 上我强烈建议直接用--network host。原因有三:
第一,容器 IP 漂移问题。默认 bridge 网络下,容器每次重启可能分到不同的内部 IP,Redis Cluster 的 nodes.conf 文件里记录的 IP 是旧的,重启后集群互连直接失败。第二,跨主机集群时,bridge 模式下必须额外配置cluster-announce-ip指向宿主机 IP,否则集群节点返回的地址是容器 IP,其他机器根本访问不到。第三,host 网络省掉 NAT 转发的性能损耗,容器内 Redis 可以直接使用宿主机端口,也省了端口映射的配置成本。
function start_redis_node() { local PORT=$1 local IMAGE=$2 local PASSWORD_CONDITION="" if [ -n "${REDIS_PASSWORD}" ]; then PASSWORD_CONDITION="--requirepass ${REDIS_PASSWORD} --masterauth ${REDIS_PASSWORD}" fi docker run -d \ --name redis-${PORT} \ --network host \ --restart always \ -v /opt/redis-cluster/${PORT}/data:/data \ -v /opt/redis-cluster/${PORT}/conf/redis.conf:/etc/redis/redis.conf:ro \ -e TZ=Asia/Shanghai \ "${IMAGE}" \ redis-server /etc/redis/redis.conf ${PASSWORD_CONDITION} }参数说明:
--name redis-${PORT}:容器名固定。后面执行 redis-cli 和 docker logs 的时候,不用去记随机 ID。--network host:容器直接用宿主机网络栈,不需要-p映射。--restart always:宿主机重启后,Docker 服务会自动拉起容器。这行绝对要加,不加的话,一次服务器重启就让你整个集群瘫痪。- 两个
-v挂载:data 目录可写、conf 文件只读。只读挂载可以防止容器内进程意外改写配置文件。 -e TZ=Asia/Shanghai:让容器日志时间与宿主机一致。CentOS7 上有人直接挂/etc/timezone,反而不如环境变量简单。
密码这里有一个容易踩的点:--requirepass只设置客户端连接密码,节点间互连还需要--masterauth。只配前者不配后者,集群创建时从节点连不上主节点,初始化必然报 NOAUTH。这个问题在第 5 章展开讲。
3.3 初始化集群:就绪探针、IP 传参和 --cluster-replicas
六个容器全部起来后,调用redis-cli --cluster create。这一步有三个细节,错过任何一个都会卡壳。
第一个细节是必须等容器真正就绪。docker run 返回成功只代表容器进程被接受,Redis 内部可能还在加载 AOF、绑定端口。立刻 create 会得到 Connection refused。常见做法是循环探测 ping:
for PORT in "${PORTS[@]}"; do while true; do RESULT=$(docker exec redis-${PORT} redis-cli -p ${PORT} ping 2>/dev/null) if [ "${RESULT}" == "PONG" ]; then echo "redis-${PORT} 已就绪" break fi echo "等待 redis-${PORT} 就绪..." sleep 2 done done第二个细节是把宿主机 IP 传给 create 参数。这个 IP 会被写进 nodes.conf,作为节点的对外地址。如果写成了 127.0.0.1 或者 localhost,集群可能在本机内是通的,但跨主机的时候直接全红。
第三个细节是--cluster-replicas 1:每个主节点配一个从节点。六个节点会最终形成三主三从。create 命令执行时会打印待分配的槽位信息,默认情况下需要手动输入 yes 确认,脚本里加--cluster-yes跳过。
MASTER_HOSTS="" for PORT in "${PORTS[@]}"; do MASTER_HOSTS="${MASTER_HOSTS} ${HOST_IP}:${PORT}" done echo "正在初始化 Redis 集群:${MASTER_HOSTS}" docker exec redis-6379 redis-cli -h ${HOST_IP} -p 6379 \ --cluster create ${MASTER_HOSTS} --cluster-replicas 1 --cluster-yes参数说明:--cluster-yes是 redis-cli 5.0.5+ 引入的参数,自动确认槽位分配方案。如果你的宿主机 redis-cli 版本太老没有这个参数,脚本会直接报 unknown option。所以前文说宿主机 redis-cli 必须和容器版本同步,那是最稳的,或者直接用容器里的 redis-cli。
初始化成功之后,执行/opt/redis-cluster/status.sh这样的检查脚本,可以看到类似输出:
>>> Performing hash slots allocation on 6 nodes... Master[0] -> Slots 0 - 5460 Master[1] -> Slots 5461 - 10922 Master[2] -> Slots 10923 - 16383槽位被三等分,每个主节点 5461 到 5462 个槽位,这是一开始就设计好的哈希槽结构。
4. 验证集群可用性:从 cluster info 到故障转移和路由验证
部署只是第一步,验证集群是否真的可用,才是交付前最严肃的环节。这一章讲三个验证动作,按重要性排下来分别是集群状态检查、故障转移实测和路由数据验证。
4.1 集群状态检查:cluster_state 必须为 ok
万事看cluster info。注意,是cluster info不是info。前者输出集群层面的状态,后者输出单节点运行时状态。集群部署完,第一件事就看cluster_state:
docker exec redis-6379 redis-cli -p 6379 cluster info # cluster_state:ok # cluster_slots_assigned:16384 # cluster_known_nodes:6 # cluster_size:3如果cluster_state不是 ok 而是 fail,说明有节点的槽位覆盖不完整,可能是 create 时节点没有全部加入,也可能是节点中途失败。cluster_slots_assigned必须等于 16384,少一个数字都不行。
节点级别的角色检查用cluster nodes,这也是平时用得最多的 redis 连接工具命令:
docker exec redis-6379 redis-cli -p 6379 cluster nodes | awk '{print $2, $3, $8}'第六列是 role,master 或 slave。awk '{print $2, $3, $8}'打出的第 8 列是 connected 或 fail。把 role 和 connected 结合起来看,能快速建立整个拓扑图。
为了让脚本自动化,可以把状态判断写成函数,在部署完成后自动调用:
function check_cluster_state() { local state state=$(docker exec redis-6379 redis-cli -p 6379 cluster info 2>/dev/null | grep cluster_state | awk -F: '{print $2}' | tr -d '\r') if [ "${state}" != "ok" ]; then echo "集群状态异常:${state}" exit 1 fi } check_cluster_state注意tr -d '\r'。CentOS7.x 上有时终端会带回车符号,导致字符串比对失败。这个坑体积小、杀伤力大,我当年排查了半小时才发现是\r在作怪。
4.2 故障转移实测:大部分团队从没验证过这一步
集群高可用不是部署完就自动有了,这是很多人对 Redis Cluster 的最大误解。故障转移的机制是:每个节点通过集群总线每秒发送探测,如果 master 在 cluster-node-timeout(5000ms)内无响应,从节点会发起选举,获得大多数节点的投票后晋升为新的 master。
验证故障转移应该成为部署脚本里的一个可选项。我一般提供一个--test-failover参数,测试时调用。
# 手动停掉一个主节点,比如 6379 docker stop redis-6379 # 观察对端从节点是否接管 sleep 15 docker exec redis-6380 redis-cli -p 6380 cluster nodes | awk '{print $2, $3}' # 此时 6379 对应的从节点角色应该已经从 slave 变成 master执行结果里,原本 6379 对应的从节点会把自己的 role 从 slave 变成 master,并接管 0-5460 这些槽位。等旧节点docker start redis-6379后,它会重新加入集群,自动降级为从节点,同步新主节点的数据。这是 Redis Cluster 的自动收敛机制,不用任何手工操作。
如果 15 秒内没有切换,优先检查 cluster-node-timeout 是不是设太大,以及从节点上cluster_state是否 ok。另外注意,一个从节点只有复制偏移量跟上主节点,才有资格参与选举。如果主库写入量很大而网络延迟高,从库数据落后太多,集群宁可等也不会让一个落后的从库晋升。
4.3 路由和压测:确认请求真的按槽位分发
最后是读写验证。两条命令,一条看路由,一条看基本性能。
docker exec redis-6379 redis-cli -c -h ${HOST_IP} -p 6379 set foo bar docker exec redis-6379 redis-cli -c -h ${HOST_IP} -p 6379 get foo选项-c是 cluster 模式,redis-cli 收到 MOVED 响应后自动重定向。如果加了-c却输出(error) MOVED,说明 redis-cli 版本太老或者集群节点状态不对,正常-c模式会自动切换。这条命令能执行通,就证明了客户端到集群的路由链路没问题。
性能压测用 redis-benchmark:
docker exec redis-6379 redis-benchmark -h ${HOST_IP} -p 6379 \ -t set,get -n 100000 -c 50 -P 10参数说明:-n 100000是总请求数,-c 50是并发连接数,-P 10是管道深度。跑完后重点看三个主节点的 CPU 负载是否均衡。如果有节点完全空闲,keys 分布可能严重倾斜。虽然哈希槽设计上让任意 key 分布较均匀,但 key 数量少且集中在某个范围时,偏斜确实存在。业务上解决偏斜用 hash tag 技术,把同一类 key 强制放进同一个槽位,同时也要保证各 hash tag 下的 key 总量差不多。
5. CentOS7.x 上踩过的坑与常见问题排查:七条踩坑记录
5.1 坑:create 卡在 Waiting for the cluster to join
现象:脚本执行到redis-cli --cluster create,输出>>> Waiting for the cluster to join后迟迟不动。
原因:最常见的是集群总线端口没放行。我只放了 6379,没放 16379,导致节点之间探测失败。另外,如果在容器里 bind 了某个具体 IP 而不是 0.0.0.0,也会出现类似现象。
解决:把客户端端口和总线端口成对放行。firewall-cmd --permanent --add-port=6379/tcp --add-port=16379/tcp,然后firewall-cmd --reload。云环境的话,一并检查安全组。还有一个隐藏原因是这台机器上跑着别的 Redis 占用了相关端口,ss -ltnp | grep 16379看一眼就能确认。
5.2 坑:容器重启后集群 fail,节点间地址失效
现象:宿主机重启或systemctl restart docker后,cluster nodes显示部分节点持有旧地址,集群状态直接 red。
原因:bridge 网络下,容器重启后 Docker 可能分配新的内部 IP。Redis Cluster 各节点之前记录的 nodes.conf 里保存的地址已不可达,互相连不上。
解决:改用 host 网络模式,地址基于宿主机 IP,不会漂移。如果出于某种原因必须用 bridge,就在每个节点的 redis.conf 里显式设置cluster-announce-ip 宿主机IP和cluster-announce-port 客户端端口。这两个参数就是专门解决 bridge 模式下节点地址公告问题的。
5.3 坑:设置密码后 create 报 NOAUTH
现象:redis.conf 里加了requirepass,create 集群时报NOAUTH Authentication required,日志里全是 auth 失败。
原因:集群节点间通信也需要认证。Redis 要求设置masterauth,从节点复制和集群总线连接都用它。只设 requirepass 不设 masterauth,等于给门加了锁但没给钥匙。
解决:在 docker run 参数或 redis.conf 里同时写--requirepass和--masterauth,两个值保持一致。否则节点间交互照样失败。
5.4 坑:连接超时但 ping 通,SELinux 从中作梗
现象:宿主机 ping 通、防火墙端口放行了,redis-cli 连接还是 Command timed out,telnet也连不上端口。
原因:CentOS7.x 的 SELinux 对容器访问端口和已挂载数据目录有强制策略,容器进程的 socket 操作被拦截。这就是玄学问题的代表。
解决:临时验证用setenforce 0,如果问题消失,基本就是 SELinux 的锅。生产环境不建议永久关闭,建议用chcon -Rt svirt_sandbox_file_t /opt/redis-cluster/给挂载目录打标签。如果只是测试环境,直接setenforce 0也不丢人,后续有精力再写策略。
5.5 坑:redis-cli 版本和 redis-server 版本不一致
现象:宿主机用 yum 装 redis,比如版本 5.0 之类,命令行为就很怪。比如没有--cluster-yes参数,或者cluster nodes输出的列对不上,再比如redis-cli --cluster create要求旧语法。
原因:CentOS7.x 自带的 redis 包太老,而 Docker 容器跑的是 redis:7.2,宿主机上的客户端和容器内服务端版本不匹配,语义对不上。
解决:别用宿主机 redis-cli。统一用docker exec redis-6379 redis-cli ...这种方式,版本永远和容器内的 redis-server 对齐,不会因为环境差异翻车。
5.6 坑:内存和持久化参数没调,运行几天后 OOM
现象:集群刚跑起来正常,半天后某个节点内存占满被 OOM 杀掉,主从切换完成后数据对不上或直接 fail。
原因:Redis 默认的 maxmemory 为 0,也就是不限制,而 RDB 默认策略是按变更次数触发。集群模式下数据量上来后内存会爆炸,持久化又会频繁抢占磁盘 IO。
解决:部署脚本里写死一个初始配置:maxmemory 1gb按机器内存调整,maxmemory-policy allkeys-lru,appendonly yes和appendfsync everysec。注意allkeys-lru会淘汰所有 key,如果业务数据舍不得,用volatile-lru只淘汰设置了 expire 时间的 key。无论选哪个,都比默认状态遭遇 OOM 强。
5.7 坑:拉镜像失败或镜像体积过大,卡在拉取阶段
现象:docker pull redis:7.2卡死或者超时,脚本卡在镜像拉取环节没法继续。
原因:CentOS7.x 默认 DNS 配置可能有问题,或者 Docker daemon 没有配置镜像加速器。相比国内网络环境,访问 Docker Hub 的稳定性大家心里都有数,这一环节最容易浪费十分钟。
解决:写脚本时给docker pull加timeout 180,配合registry-mirrors配置到/etc/docker/daemon.json中,然后重启 docker。如果公司内网有可用的仓库镜像,直接改源地址。另外,在脚本里保留 inspect 判断,镜像已存在就跳过拉取,二次部署会快很多。
6. 最终形态与进阶验证:给自己的部署脚本加上健康检查
6.1 健康检查和告警
到这一步,部署脚本已经覆盖了从环境检查到故障验证的完整路径。但我通常还会再补一步:给这套方案写一个配套的健康检查脚本,并挂到 crontab。原理不复杂,定期跑cluster info,一旦cluster_state非 ok 就记录日志并触发告警。集群本身有自动恢复能力,但内存不均、槽位卡住、复制中断这些持续性隐患,靠自动恢复是发现不了的。
#!/bin/bash # cluster-check.sh - 每 10 分钟检查一次 Redis Cluster 健康状态 for PORT in 6379 6380 6381; do state=$(docker exec redis-${PORT} redis-cli -p ${PORT} cluster info 2>/dev/null | grep cluster_state | awk -F: '{print $2}' | tr -d '\r') if [ "${state}" != "ok" ]; then echo "$(date '+%Y-%m-%d %H:%M:%S') redis-${PORT} cluster_state: ${state}" >> /var/log/redis-cluster-check.log fi done把这个脚本放进 crontab 每 10 分钟跑一次:*/10 * * * * /opt/redis-cluster/cluster-check.sh,集群就进入自我监控的闭环。
6.2 槽位迁移和日常变更的纪律
进阶用法里,我最常用的是redis-cli --cluster reshard。某台节点负载高了,可以把一部分槽位迁到另一台,这是集群运维的核心操作。执行前先把该节点的 nodes.conf 备份一份,这就是后悔药。做任何集群级变更前都先备份,是我给自己定的死规矩。
我自己最常提醒别人的是:第一次操作集群,千万别在宿主机上来个systemctl restart docker当测试。这个命令会让所有容器一起重启,容器不带--restart always的话集群直接全灭。我第一次干这事是在机房调设备,六个容器全挂,靠手敲 docker start 一个个拉回来,从凌晨两点折腾到天亮。所以先把一键部署脚本跑顺,再配上健康检查和预警,这整套流程才算真正闭环。希望帮到你。
本文还有配套的精品资源,点击获取