目录 #
1. 背景 #
- Redis 集群自身已经具备了高可用的特性,即使几个Redis节点异常或者挂掉,Redis 集群也会实现故障自动转移,对应用方来说也可以在很短时间内恢复故障。
- 但是,如果发生了机房故障(断电、断网等极端情况),Redis集群节点全部挂掉(过半主节点挂掉),会造成集群服务不可用,对于核心业务来说是不可接受的。
- 为了应对机房故障情况,保障在这种极端情况下,核心业务仍然可以正常访问 Redis 服务,本文将给出适合我司的 Redis 跨机房高可用解决方案。
2. 目标 #
- 保障单机房整体故障时 Redis 缓存服务正常运行。
- 单机房故障 RTO:30s,RPO:1s
3. 解决方案 #
3.1 核心能力 #
- 客户端流量路由:支持按一定的策略,把流量分流到不同机房;机房故障后,流量自动流向其他机房。
- 服务端故障转移:支持机房故障后,当前机房原来主节点的从节点,通过选举自动倒换成新的主节点。
- 管理平台正常服务:任一机房故障,Renault 管理平台使用不受影响。
3.2 工作模式 #
组件在机房高可用场景下一般有多种工作模式,典型的有单集群模式及多集群模式。本节描述组件在各种工作模式下的部署方式及工作机制。
| 部署方案 | 方案说明 |
|---|---|
| 跨机房混合部署 | 将Redis集群主节点平均分配到各个机房,主从节点在不同机房 |
| 各机房独立部署集群 + 数据单向同步 | 各机房均独立部署集群,集群为热备模式,写请求均写入同一个集群,然后同步到其他集群 |
| 各机房独立部署集群 + 数据双向同步 | 每个机房部署一套Redis集群,同步核心业务写请求 |
数据同步方法:
| 数据同步方案 | 方案说明 |
|---|---|
| 客户端双写 | 客户端同时写入到各个集群 |
| 客户端代理 | Netflix开源实现的Dynomite,通过代理层接受数据后写入各个需要同步的节点 改造难度大 客户端需要优化添加Dyno Client 服务端每个节点需要部署Dyno Node read/write性能较原生差异较大,主要体现在write上,之间的差异随着node节点数越多越严重 |
| 伪从节点 | 基于Redis的Master-Slave复制协议,实现低延时、高可用的Redis多数据中心、跨公网数据复制 携程开源系统:https://github.com/ctripcorp/x-pipe 阿里RedisShake同步工具 |
| 写事件监听+MQ跨集群消息同步 | 读写在本机房,监听写事件 + MQ消息同步到其他机房 需要开启事件通知(PUB),修改Redis配置文件中的 notify-keyspace-events 配置(默认的redis并没有开启这个功能) 需要独立服务订阅写事件(SUB),并同步到其他集群 依赖MQ组件 |
不考虑客户端代理、发布订阅写事件
下面详细比较如下四种方案
- 方案一:跨机房混合部署
- 方案二:伪从节点+单向同步
- 方案三:伪从节点+双向同步
- 方案四:客户端双写+写监听服务+MQ消息队列
3.2.1 方案一:跨机房混合部署 #
3.2.1.1 部署方式 #
Redis集群主节点平均分配到各个机房,每个机房都有一个分片的副本;单个机房主节点数据占比不能过半。
[pic]
跨机房部署注意事项
- 从节点选举需要过半主节点投票,因此不适合双机房部署,至少需要3机房
- 业务请求访问响应时间会不稳定,同机房请求延迟在0.1ms,跨机房请求在1-3ms
3.2.1.2 工作机制 #
-
流量路由
-
- 默认读主节点(ReadFrom:Master)
- 读从节点(ReadFrom: Replication)
- 随机读主从(ReadFrom: Any)
- 优先读本地机房(ReadFrom:LocalDC)— TODO:新增路由策略
-
故障切换
-
- 机房故障后,Redis 集群高可用机制,会将集群在30s内自动倒换并恢复正常访问
- 同城机房间网络传输响应延迟2ms内,几乎不影响集群故障判定
- Redis 集群故障转移后,客户端30s内自动刷新集群拓扑关系
-
故障恢复
-
- 机房恢复后,故障节点 Redis 会以从节点角色自动启动,并全量同步主节点数据(数据同步流量风暴 – 会在机房间路由器端口上限速控制)
-
迁移方案
-
- 服务核心业务 Redis 集群将会改造成跨三机房部署模式,不影响客户端正常使用
- 业务根据实际情况,可将读请求路由策略修改为优先从本地机房读
Redis 故障恢复机制
-
投票选主:只有持有槽的主节点才会处理故障选举消息,获得N/2+1以上选票的从节点将为新主。
-
替换主节点:取消复制 → clusterDelSlot/clusterAddSlot把槽委派给自己 → 向集群广播通知变为主节点并接管了故障主节点的槽信息。
-
- 全量同步过程
-
-
- 从服务器连接主服务器,发送SYNC命令;
- 主服务器接收到SYNC命名后,开始执行BGSAVE命令生成RDB文件,并使用缓冲区记录此后执行的所有写命令;
- 主服务器BGSAVE执行完后,向所有从服务器发送RDB文件;
- 从服务器收到快照文件后丢弃所有旧数据,载入收到的RDB快照;
- 主服务器快照发送完毕后,开始向从服务器发送缓冲区中的写命令;
- 从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令。
-
-
- 全量同步数据评估,假如100GRedis集群,三机房,一主二从
-
-
- 根据Renault公共集群统计,8G使用容量的Redis,生成RDB文件大小约3G左右,生成时间75s
- RDB传输,单一机房故障恢复时,将有10台Redis执行主从同步,约有30G流量从其他两个机房流入。
- RDB加载,3G RDB数据加载时间约90s
-
3.2.2 方案二:伪从节点+单向同步 #
3.2.2.1 部署方式 #
双机房部署,业务读写默认集群,开发部署 Renault 复制服务(RRS, Renault Replicate Service),伪装从节点实时将默认集群数据同步到备用集群。
[pic]
3.2.2.2 工作机制 #
-
流量路由
-
- 双机房独立部署,均访问默认集群(热),故障后访问备用集群(冷)
-
故障切换
-
- 默认集群故障时,SDK熔断默认集群请求,并将流量切换到备用集群
-
故障恢复
-
- 机房故障恢复后,原默认集群将被reset,RRS 服务将反向同步
-
迁移方案
-
- 服务核心业务 Redis 集群将会搭建备用集群,并实时同步默认集群数据
- 业务客户端需要升级 SDK,支持自动故障切换功能
DC2机房业务客户端自动故障切换:
[pic]
故障恢复后(反向同步):
[pic]
3.2.3 方案三:伪从节点+双向同步 #
3.2.3.1 部署方式 #
双机房独立部署,均访问本地集群;开发部署 Renault 复制服务(RRS, Renault Replicate Service),伪装从节点实时双向同步。
[pic]
3.2.3.2 工作机制 #
-
流量路由
-
- 双机房独立部署,业务优先访问本地机房集群(TODO:需要开发一种集群选择策略)
- RRS 服务双向同步数据(需要解决双向同步成环问题)
-
故障切换
-
- DC1机房集群故障时候,上层流量自动切换到DC2机房,Redis层不需要处理
-
故障恢复
-
- DC1机房集群故障恢复,首先通过RRS服务从DC2全量同步数据,之后增量同步
-
迁移方案
-
- 服务核心业务 Redis 集群将会搭建双活集群,并通过 RRS 服务实时双向同步
- 业务客户端需要升级 SDK,支持启动时选择哪个集群
数据库层面的多活,双向同步存在以下困难:
-
两边都改了如何解决冲突?
-
- 跨机房双写无法保证缓存的一致性,需要应用侧可以容忍对应的缓存不一致场景
-
RRS复制中断或者故障如何处理?
-
数据同步如何防环?
-
- 方法1:通常需要应用方配置使用,按业务类型分流(不能为通用解决方案)
- 方法2:数据层面添加字段标识数据源(带来一定开销,并且对于数值计算类数据不能添加标识)
- 方法3:x-pipe - 定制Redis,在内容分发上做处理,服务端能够识别不同的链接类型,在同步数据之初便加以控制在内容分发上做处理,服务端能够识别不同的链接类型,从而做到有的放矢,在同步数据之初便加以控制
3.2.4 方案四:客户端双写+写监听服务+MQ消息队列 #
3.2.4.1 部署方式 #
双机房/三机房每个独立部署,应用客户端均访问本地集群;借助MQ通过异步双写机制双写同步到其他集群。
[pic]
3.2.4.2 工作机制 #
-
流量路由
-
- 多机房独立部署,业务优先访问本地机房集群(同方案三)
- MQ中间件+写事件监听服务做双写同步
-
故障切换
-
- DC1机房集群故障时候,上层流量自动切换到DC2机房,Redis层不需要处理(同方案三)
-
故障恢复
-
- DC1机房集群故障恢复,首先通过RRS服务从DC2全量同步数据,之后增量同步(同方案三)
-
迁移方案
-
- 服务核心业务 Redis 集群将会搭建多活集群,并通过 MQ 发布订阅方式实现多集群间双向同步
- 业务客户端需要升级 SDK,支持启动时选择哪个集群
双机房/三机房每个独立部署,多活部署主要问题:
-
两边都改了如何解决冲突?
-
跨机房双写无法保证缓存的一致性,需要应用侧可以容忍对应的缓存不一致场景,应用如果依赖缓存强一致性,则不合适该方案。
-
- DC1和DC2两边都写了同一个Key,最终互相覆盖
-
如何保证消息的顺序?如何保证消息成功发送及消费?
3.3 成本比较 #
| 部署成本 | 改造成本 | 使用成本 | |
|---|---|---|---|
| 方案一:跨机房混合部署 | 成本-低 适用于三机房及以上 2副本,增加50%容量 |
改造成本-低 只用按照要求部署集群 SDK路由-优先读本地机房 |
性能有下降 本机房访问不受影响,跨机房访问延迟1-3ms |
| 方案二:伪从节点+单向同步 | 成本-中 新增备用集群,增加100%容量 部署同步服务 |
改造成本-中 需要开发集群间数据同步服务(已有待完善) 读写分离 |
性能有下降 本机房访问不受影响,跨机房访问延迟1-3ms 读可优化成读本地机房,性能不受影响 |
| 方案三:伪从节点+双向同步 | 成本-中 各机房均新增集群,双机房增加100%容量,三机房增加200% 容量部署同步服务 |
改造成本-高 双向复制成环很难解决,需要定制Redis 两边都写,冲突问题难解决 需要开发集群间数据同步服务(已有待完善) |
性能不受影响 读写本地机房 |
| 方案四:客户端双写+写监听+MQ消息同步 | 成本-高 各机房均新增集群,双机房增加100%容量,三机房增加200%容量 部署写监听服务 部署MQ消息集群 |
改造成本-中 依赖MQ中间件 |
性能稍有下降 同步写跨机房访问,性能会严重下降 异步写性能稍有下降 应用能容忍两边不一致场景 |
方案选定:
- 目前同城多活选用方案一(跨机房混合部署)
- 未来异地多活再考虑方案三和四
3.4 场景建议 #
方案一适应场景
- 适用于三机房及以上【两机房故障时候无法成功选举】
- 要能接受写缓存时间在1-2ms内【不可避免跨集群写数据,目前sh1读写tx1时延约1.3ms,sh1读写sh1时延约0.2ms】
- 配置优先读本地机房的话,能接收读数据时延【主从数据同步毫秒级时延】
其他场景建议
-
不接受写缓存慢场景、不接受读从节点数据延迟场景
-
- 服务端:每个机房都要独立部署Redis集群,并且双向同步数,推荐方案三
- SDK改造:需要支持优先读写本地Redis集群路由策略
- 业务端:升级SDK版本
4. 里程碑 #
描述组件为了达成机房高可用需要做的事情,包括事项、优先级、预期完成时间、负责人等信息。
对于中间件,一般有如下重要时间点:
- 服务端机房高可用方案设计完成
- 服务端机房高可用方案在测试集群验证通过
- 客户端机房高可用方案设计开发完成
- 业务集群机房高可用方案验证:明确 RPO 和 RTO
方案一跨机房混合部署改造事项:
-
管理平台:
-
- 搭建核心集群
-
-
- 机器添加机房标识 (Done),
- 机架标识,是否属于同一机架,
- 机房高可用校验 (Done)
-
-
-
-
- 主从节点数至少3个,且分布在不同机房
- 单机房主节点数不能过半
-
-
-
-
- 集群调整,确保核心集群Redis实例机房按大集群要求部署,
-
-
- 核心应用识别及迁移
-
-
- 核心缓存标识 - 源于用户?核心应用标识?
- 新增核心缓存将绑定到核心集群,非核心缓存绑定到公共集群
- 缓存客户端监控(CAT QPS)集成到管理平台 - 便于缓存迁移时,从技术角度判定是否需要迁移
- 核心缓存迁移
-
-
-
-
- 已迁移(arch-100%,cl-100%)
- 待迁移(md、mkt、yw)(需要推动升级客户端并迁移)
-
-
-
客户端:
-
- 读写分离,优先读本机房实例 ,
-
-
- 熟悉Lettuce 读写分离相关源码,确定可行方案(方案可行 - 选择NEAREST或者自定义ReadFrom)
-
-
-
- 自定义ReadFrom,优先从本机房读,本机房无实例则从Master节点读 (done)
-
-
-
-
- 用户在 Apollo 配置读取数据方式(Master/Slaver/Any/Nearest/LocalZone)
-
-
-
Redis集群:
-
- 故障演练,
-
-
- repl-timeout 60s适当大小;
- 完整操作机房Redis实例下线、Redis实例恢复操作
-
-
- 缓存恢复时的数据同步抑制方法, (Done,需要时在交换机端口上限速)
-
-
- 机房故障后,强制下线故障机房Redis实例
- 机房恢复后,重新部署Redis实例,逐一添加到集群,并调整合理主从关系
-
-
ZK & Apollo ,
-
- 切换演练
- 在线客户端列表对比(老zk的会清零,新zk临时节点数目和原来的一致)
- 将线上ZK从zk1切换到zk3
2021-11-30 Redis 集群机房高可用方案整体设计完成
2021-12-31 客户端路由开发、跨集群测试验证通过
2022-2-28 推广接入试点,及真实数据故障演练
2022-3-31 业务集群机房高可用方案验证
5. 相关文档 #
6. 参考资料 #
- 美团KV存储架构及实践 ***
- 华为容灾多活策略
- Redis异地多活行业方案
- 携程Redis多数据中心复制管理系统
- 携程异地多活-MySQL实时双向(多向)复制实践
- Redis Cluster多机房高可用实现–基于客户端
- 同城双活-Redis篇
- 饿了么实时双向复制工具
-
CKV+异地容灾探索和实践 *** 未
-
企业打开Redis的正确方式,来自阿里云云数据库团队的解读 未 Figure 2:Redis异地多活架构方案示意图