Redis分片集群手动故障转移

一、前言:为什么需要"手动"故障转移?

Redis 分片集群(Cluster)默认支持自动故障转移 ------当主节点宕机时,从节点会自动升主。

但在计划内维护场景 中,我们更希望主动、可控、无损地完成主从切换:

场景举例

  • 主节点所在服务器需重启或升级
  • 主节点CPU/内存持续高负载,需临时切走流量
  • 滚动升级 Redis 版本
  • 压测前主动切换,避免影响线上主节点

手动故障转移(Manual Failover) 正是为此设计:无需停机、数据零丢失、业务无感知

本文将手把手教你如何安全执行手动切换。


二、手动故障转移 vs 自动故障转移

对比项 自动故障转移 手动故障转移
触发条件 主节点宕机/失联 运维人员主动触发
切换速度 15~30 秒(依赖超时) 秒级完成
数据一致性 可能丢失最后几秒写入 完全同步,零数据丢失
业务影响 短暂不可用 几乎无感
适用场景 故障应急 计划内维护、升级、优化

核心优势在主从数据完全同步的前提下切换,确保强一致性


三、原理:如何实现"无损"切换?

手动故障转移通过以下机制保证安全:

  1. 从节点向主节点发起 SYNC 请求
    • 确保所有复制偏移量(replication offset)已追平
  2. 主节点暂停客户端写入(可选)
    • 通过 CLUSTER FAILOVER TAKEOVER 可跳过此步(强制切换)
  3. 从节点升主,主节点降从
    • 角色互换,IP 不变(客户端连接不受影响)

🔑 关键命令CLUSTER FAILOVER [FORCE|TAKEOVER]


四、实战步骤:安全执行手动故障转移

4.1 环境说明

  • 主节点:192.168.1.10:7001
  • 从节点:192.168.1.10:7004(主 7001 的从)

4.2 步骤 1:确认主从同步状态

bash 复制代码
# 在从节点执行
redis-cli -p 7004 INFO REPLICATION

关注输出:

复制代码
master_host:192.168.1.10
master_port:7001
master_link_status:up          # 必须为 up
master_last_io_seconds_ago:0   # 最近一次通信(越小越好)
slave_read_only:1

确保 master_link_status: up 且 lag 很小(< 1s)


4.3 步骤 2:在从节点触发手动故障转移

bash 复制代码
# 登录从节点(7004),执行:
redis-cli -p 7004 CLUSTER FAILOVER

⏱️ 等待 1~3 秒,命令会阻塞直到切换完成。

可选参数说明:
命令 作用
CLUSTER FAILOVER 标准模式:等待数据完全同步后切换(推荐)
CLUSTER FAILOVER FORCE 强制模式:不等待同步,立即切换(可能丢数据)
CLUSTER FAILOVER TAKEOVER 接管模式:无需主节点参与(主已宕机时使用)

💡 生产建议 :始终使用无参 CLUSTER FAILOVER,确保数据安全。


4.4 步骤 3:验证角色是否互换

查看新主(原从 7004):
bash 复制代码
redis-cli -p 7004 ROLE
# 返回:1) "master" 2) (integer) 12345 ...
查看新从(原主 7001):
bash 复制代码
redis-cli -p 7001 ROLE
# 返回:1) "slave" 2) "192.168.1.10" 3) (integer) 7004 ...
查看集群拓扑:
bash 复制代码
redis-cli -p 7004 CLUSTER NODES
# 应显示 7004 为 master,7001 为 slave

角色已成功互换!


4.5 步骤 4:验证业务读写正常

bash 复制代码
# 写入新主(7004)
redis-cli -c -p 7004 SET manual_failover_test "success"

# 读取(任意节点)
redis-cli -c -p 7001 GET manual_failover_test  # 返回 "success"

客户端无需修改连接地址!因为 slot 归属未变,只是主从角色互换。


五、高级场景:主节点已宕机,如何强制接管?

若主节点已无法响应 (如服务器宕机),但你想立即升从为主

在从节点执行:

bash 复制代码
redis-cli -p 7004 CLUSTER FAILOVER TAKEOVER

⚠️ 注意

  • 此操作绕过集群共识,仅在紧急情况下使用
  • 可能导致脑裂(若原主恢复但未降级)
  • 操作后需手动清理原主 (重启后执行 CLUSTER RESET SOFT

六、客户端影响分析

6.1 连接是否中断?

  • TCP 连接本身不断开(IP:Port 未变)

  • 但原主降从后变为 read-only ,写请求会报错:

    复制代码
    (error) READONLY You can't write against a read only replica.

6.2 如何做到"业务无感"?

现代客户端(如 Lettuce)会:

  1. 捕获 READONLY 错误
  2. 主动刷新集群拓扑
  3. 重试写请求到新主

效果 :应用层可能收到一次异常,但重试后即可成功

6.3 Spring Boot 优化建议

java 复制代码
// 配置重试机制(结合 Resilience4j 或 Spring Retry)
@Retryable(value = {RedisCommandExecutionException.class}, maxAttempts = 3, backoff = @Backoff(delay = 100))
public void setValue(String key, String value) {
    redisTemplate.opsForValue().set(key, value);
}

七、生产环境最佳实践

✅ 必须遵守

  1. 切换前检查主从延迟INFO REPLICATION
  2. 避开业务高峰期
  3. 每次只切换一个分片(避免多点故障)
  4. 切换后验证数据一致性(抽样比对)

✅ 推荐流程(维护 checklist)

html 复制代码
- [ ] 确认主从同步状态正常
- [ ] 通知相关团队(可选)
- [ ] 执行 `CLUSTER FAILOVER`
- [ ] 验证新主可写、新从可读
- [ ] 监控 QPS/延迟/错误率 5 分钟
- [ ] 记录操作日志

八、常见问题排查

❌ 问题 1:CLUSTER FAILOVER 卡住不动

  • 原因:主从数据未同步完成
  • 解决:等待或检查网络/主节点负载

❌ 问题 2:切换后客户端持续报 MOVED

  • 原因:客户端未刷新拓扑
  • 解决 :Lettuce 配置 enablePeriodicRefresh

❌ 问题 3:原主恢复后未自动降从

  • 原因:原主配置未更新
  • 解决 :重启原主,或手动执行 REPLICAOF <new-master>

九、结语

感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!

相关推荐
无名-CODING2 小时前
从零开始!Vue3+SpringBoot前后端分离项目Docker部署实战(上):环境搭建与数据库容器化
数据库·spring boot·docker
Bdygsl2 小时前
MySQL(2)—— CRUD
数据库·mysql
chushiyunen2 小时前
python edge-tts实现tts文本转语音、音频
数据库·python·音视频
原来是猿2 小时前
MySQL【事务中 - 事务的隔离级别】
数据库·mysql
2501_945423542 小时前
游戏与图形界面(GUI)
jvm·数据库·python
大傻^2 小时前
Spring AI Alibaba Agent开发:基于ChatClient的智能体构建模式
java·数据库·人工智能·后端·spring·springaialibaba
爬山算法2 小时前
MongoDB(50)副本集中的角色有哪些?
数据库·mongodb
大傻^2 小时前
Spring AI Alibaba 向量数据库集成:Milvus与Elasticsearch配置详解
数据库·人工智能·spring·elasticsearch·milvus·springai·springaialibaba
redsea_HR3 小时前
红海eHR解决方案背后的底层能力
大数据·数据库·人工智能