redis集群全量备份必须遍历所有主节点分别触发bgsave再统一上传,否则会丢失部分数据;因集群分片架构下各master仅管理自身slot,单点bgsave无法覆盖全部数据。

Redis集群不能靠单个BGSAVE完成全量备份,必须遍历所有主节点分别触发,再统一上传到S3或OSS——否则漏掉任意一个master,就等于丢掉1/8甚至更多数据。
为什么直接redis-cli -h cluster-ip -p 7001 BGSAVE会丢数据
Redis Cluster是去中心化分片架构,每个master只管自己负责的16384个slot中的一部分。执行CLUSTER NODES能看到多个master行,每行对应一个独立实例;对其中任一节点调用BGSAVE,只会生成该节点本地dump.rdb,其他节点完全无感知。常见错误现象包括:
- 备份后恢复发现key数量只有预期的1/3~1/2
-
INFO replication显示从节点同步正常,但KEYS *查不到某些业务前缀的key - 备份文件大小远小于
INFO memory | grep used_memory_human报告值
用crontab调用Shell脚本遍历master并并发触发BGSAVE
关键不是“能不能并发”,而是“并发时怎么防错”。盲目用&拉起一堆redis-cli可能卡死某个响应慢的节点,拖垮整个备份窗口。推荐做法:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 先用
redis-cli -h $any_node -p $port CLUSTER NODES提取所有master地址,过滤掉fail和myself标记 - 对每个
ip:port做预检:nc -z $ip $port && redis-cli -h $ip -p $port INFO persistence | grep rdb_bgsave_in_progress | grep -q 0 - 用
timeout 8s redis-cli -h $ip -p $port BGSAVE限制单次调用耗时,超时即跳过(避免阻塞) - 不要用
wait等全部结束——改用固定sleep 12秒,覆盖最长RDB写入时间(实测Redis 8.2.3在16GB内存下通常≤9秒)
备份文件命名与上传到S3/OSS的避坑要点
默认dump.rdb没有节点上下文,直接上传到S3或OSS会导致文件名冲突、无法定位来源。必须重命名,并确保路径可追溯:
- 文件名格式建议:
redis-cluster-prod-${ip//./-}-${port}-${date +%Y%m%d_%H%M%S}.rdb(如redis-cluster-prod-192-168-1-10-7001-20260530_210512.rdb) - 上传前检查目标路径是否存在同名文件:
aws s3 ls s3://my-bucket/ | grep -q "$filename",存在则加-retry后缀 -
阿里云OSS需用
ossutil cp而非curl,因ossutil自动处理分块上传和断点续传;S3优先用aws s3 cp --sse AES256启用服务端加密 - 上传完成后立即校验MD5:
md5sum "$local_file" | awk '{print $1}'与aws s3api head-object --bucket my-bucket --key "$key" --query 'Metadata.md5' --output text比对
crontab里不能直接写长命令,必须封装为独立脚本
把逻辑塞进crontab -e的一行里(比如*/30 * * * * /usr/bin/redis-cli ...)会导致:
- 特殊字符(如
$、|、&)被shell提前解析,date +\%Y\%m\%d变成空字符串 - 出错时日志难追踪,
crond只记录“exit code 1”,不输出stderr - 无法复用预检逻辑,每次都要重新写nc+grep+timeout
正确做法:把完整流程写成/opt/redis-backup/cluster-bgsave-to-oss.sh,在crontab中仅调用它,并重定向日志:0 2 * * * /opt/redis-backup/cluster-bgsave-to-oss.sh >> /var/log/redis-backup.log 2>&1。注意脚本开头加#!/bin/bash -e,遇到任何命令失败立即退出,不继续执行后续上传步骤。










