如何备份 Redis Cluster 数据?(生产级完整方案)

如何备份 Redis Cluster 数据?(生产级完整方案)

Redis Cluster 是 Redis 的分布式集群模式,支持数据分片(16384 slots)和高可用。由于其架构复杂性,不能像单节点 Redis 那样简单地备份一个 RDB 文件

本文将详细介绍 如何正确备份 Redis Cluster 数据,涵盖 全量备份、增量备份、一致性保障、恢复验证、自动化脚本 等企业级实践。


一、Redis Cluster 备份核心挑战

挑战说明
🧩 数据分片数据分布在多个 master 节点上
🔁 复制结构每个 master 有 slave,但备份需从 master
⏱️ 一致性窗口多节点备份时间不一致可能导致数据不一致
📦 备份粒度必须备份所有 master 节点
🔄 恢复复杂恢复时需重建集群拓扑

目标:实现“集群级一致性备份”


二、备份策略选择

方法适用场景推荐指数
各节点独立 RDB 备份通用,推荐⭐⭐⭐⭐⭐
使用 redis-cli --cluster 工具辅助管理⭐⭐⭐
AOF + 增量备份高频变更数据⭐⭐⭐⭐
CDC 变更捕获(如 Debezium)核心业务⭐⭐⭐⭐
❌ 只备份一个节点❌ 完全错误⚠️

推荐组合:RDB 全量 + AOF 增量 + 外部 CDC


三、方案一:RDB 全量备份(推荐)

3.1 架构说明

Redis Cluster 通常有多个 master 节点(如 3 master + 3 slave),必须对每个 master 节点执行备份

[Master1] → BGSAVE → RDB1
[Master2] → BGSAVE → RDB2
[Master3] → BGSAVE → RDB3

3.2 获取 Cluster 节点信息

# 查看集群节点
redis-cli -c -h cluster-node -p 6379 CLUSTER NODES

输出示例:

abc123... 192.168.1.10:6379@16379 master - 0 1678901234567 1 connected 0-5460
def456... 192.168.1.11:6379@16379 master - 0 1678901234568 2 connected 5461-10922
ghi789... 192.168.1.12:6379@16379 master - 0 1678901234569 3 connected 10923-16383

提取 master 节点 IP 和端口。


3.3 全量备份脚本(Shell)

#!/bin/bash
# backup_redis_cluster.sh

CLUSTER_SEED="192.168.1.10:6379"
BACKUP_DIR="/backup/redis-cluster"
DATE=$(date +%Y%m%d_%H%M%S)
TMP_NODES="/tmp/cluster_nodes.txt"

mkdir -p $BACKUP_DIR

echo "🔍 Discovering master nodes..."
redis-cli -c -h $CLUSTER_SEED CLUSTER NODES | grep "master" | grep -v "fail" > $TMP_NODES

if [ ! -s $TMP_NODES ]; then
  echo "❌ Failed to get cluster nodes"
  exit 1
fi

SUCCESS_COUNT=0
TOTAL_COUNT=$(grep -c "" $TMP_NODES)

for node in $(cat $TMP_NODES | awk '{print $2}'); do
  IP=$(echo $node | cut -d: -f1)
  PORT=$(echo $node | cut -d: -f2)
  
  echo "🔄 Backing up $IP:$PORT"
  
  # 触发 BGSAVE
  RESPONSE=$(redis-cli -h $IP -p $PORT BGSAVE 2>&1)
  if echo "$RESPONSE" | grep -q "Background saving started"; then
    echo "✅ BGSAVE started on $IP:$PORT"
    
    # 等待完成(可优化为轮询 INFO persistence)
    sleep 15
    
    # 复制 RDB 文件(假设 RDB 在 /data/dump.rdb)
    ssh $IP "cp /data/dump.rdb /data/dump-$DATE.rdb && gzip /data/dump-$DATE.rdb"
    scp $IP:/data/dump-$DATE.rdb.gz $BACKUP_DIR/dump-$IP-$PORT-$DATE.rdb.gz
    
    if [ $? -eq 0 ]; then
      echo "✅ Backup copied: $BACKUP_DIR/dump-$IP-$PORT-$DATE.rdb.gz"
      SUCCESS_COUNT=$((SUCCESS_COUNT + 1))
    else
      echo "❌ Failed to copy backup from $IP"
    fi
  else
    echo "❌ BGSAVE failed on $IP:$PORT - $RESPONSE"
  fi
done

# 清理临时文件
rm -f $TMP_NODES

if [ $SUCCESS_COUNT -eq $TOTAL_COUNT ]; then
  echo "✅ Cluster backup SUCCESS: $SUCCESS_COUNT/$TOTAL_COUNT nodes"
  exit 0
else
  echo "❌ Cluster backup FAILED: $SUCCESS_COUNT/$TOTAL_COUNT nodes"
  exit 1
fi

3.4 加入定时任务

# 每天凌晨 2 点备份
0 2 * * * /path/to/backup_redis_cluster.sh >> /var/log/redis-cluster-backup.log 2>&1

四、方案二:AOF 增量备份

4.1 配置所有 master 节点

# redis.conf
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

4.2 增量备份脚本

#!/bin/bash
# incremental_backup_cluster.sh

for node in $(cat /tmp/master_nodes.txt); do
  IP=$(echo $node | cut -d: -f1)
  PORT=$(echo $node | cut -d: -f2)
  LAST_POS="/backup/redis-cluster/last_pos_$IP:$PORT.txt"
  
  CURRENT_SIZE=$(ssh $IP "stat -c%s /data/appendonly.aof")
  LAST_SIZE=$(cat $LAST_POS 2>/dev/null || echo 0)
  
  if [ $CURRENT_SIZE -gt $LAST_SIZE ]; then
    # 提取新增部分
    ssh $IP "dd if=/data/appendonly.aof of=/tmp/incr.aof.gz skip=$LAST_SIZE count=$((CURRENT_SIZE-LAST_SIZE)) | gzip"
    scp $IP:/tmp/incr.aof.gz $BACKUP_DIR/incr-$IP-$PORT-$(date +%Y%m%d_%H%M%S).aof.gz
    echo $CURRENT_SIZE > $LAST_POS
  fi
done

五、方案三:使用外部 CDC(推荐核心业务)

架构

[MySQL] → [Debezium] → [Kafka] → [Logstash] → [Redis Cluster]
                             ↓
                       [备份变更事件]

或:

[Redis Cluster] → [KeySpace Notifications] → [Kafka] → [备份]
启用 KeySpace 通知:
notify-keyspace-events "ExgK"
Logstash 配置:
input {
  redis {
    host => "redis-cluster-seed"
    key => "__keyevent@*:set"
    data_type => "pattern_channel"
    cluster_enabled => true
  }
}

output {
  file {
    path => "/backup/redis-events/%{+YYYY-MM-dd}.log"
    codec => json_lines
  }
}

实现逻辑层备份,可审计、可重放。


六、恢复流程

6.1 恢复前提

  • 所有 master 节点的 RDB 文件
  • 集群拓扑信息(cluster nodes 输出)

6.2 恢复脚本

#!/bin/bash
# restore_redis_cluster.sh

# 1. 停止所有 Redis 实例
for node in $MASTERS; do
  ssh $node "systemctl stop redis"
done

# 2. 替换 RDB 文件
for node in $MASTERS; do
  IP=$(echo $node | cut -d: -f1)
  PORT=$(echo $node | cut -d: -f2)
  scp /backup/redis-cluster/dump-$IP-$PORT-*.rdb.gz $IP:/data/dump.rdb.gz
  ssh $IP "gunzip -f /data/dump.rdb.gz && chown redis:redis /data/dump.rdb"
done

# 3. 启动所有节点
for node in $MASTERS; do
  ssh $node "systemctl start redis"
done

# 4. 重新创建集群(如果元数据丢失)
# redis-cli --cluster create ... 

七、一致性与验证

7.1 备份一致性检查

# 检查所有节点备份时间是否接近
ls -lt /backup/redis-cluster/dump-* | head -10

时间差应 < 1 分钟。

7.2 使用 redis-check-rdb

for file in /backup/redis-cluster/*.rdb.gz; do
  gunzip -c "$file" > /tmp/temp.rdb
  if /usr/local/bin/redis-check-rdb /tmp/temp.rdb > /dev/null; then
    echo "✅ $file is valid"
  else
    echo "❌ $file is corrupted"
  fi
  rm -f /tmp/temp.rdb
done

八、最佳实践总结

项目推荐做法
备份频率每日 1 次全量 + 每 15 分钟增量
存储位置异地(S3、NFS)+ 加密
一致性尽量缩短各节点备份时间差
监控监控每个节点的备份状态
演练每月执行恢复测试
权限备份账户仅限读取和 BGSAVE

九、参考资源


十、结语

备份 Redis Cluster 数据的关键是:

🔑 对所有 master 节点执行一致性备份,并验证可恢复性

通过自动化脚本 + 定期演练,可构建一个可靠的集群备份体系。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值