跨数据中心复制

功能成熟度通知

跨数据中心复制目前处于 alpha。如果您计划在生产环境中使用此解决方案,请结合告警和定期备份等功能使用。同时,灾难恢复切换需要手动干预,以防止因未知问题导致数据丢失。

概述

系统的核心功能覆盖整个复制链路,包括数据拦截、命令解析、操作日志(Oplog)持久化、全量和增量数据同步,以及日志切片。工作流从命令执行入口点拦截所有写操作开始。随后,系统会对命令进行深度解析,并将其转换为幂等的结构化 Oplog 格式。这些日志会高效地持久化到本地磁盘,形成完整可靠的数据变更历史,为后续的数据恢复和故障转移提供坚实基础。

在数据同步方面,系统设计了一套高效且灵活的同步机制。它支持全量同步:通过生成 Redis Database(RDB)快照,并结合 Oplog 的起始位置,在下游快速构建完整的数据副本。更重要的是,我们创新性地引入了与 Oplog 紧密集成的 Offset 机制,构建了具有超大窗口期的增量同步能力。不同于依赖有限内存积压区的 Redis 原生复制,我们的 Oplog 持久化在磁盘上,这意味着增量同步的追赶范围仅受磁盘空间限制。因此,即使上下游实例之间发生数小时甚至数天的网络中断,连接恢复后,下游仍可从上次记录的 Offset 位置请求增量数据,实现高效的数据追赶和一致性恢复,从而大幅提升架构的可靠性和健壮性。

此外,为确保系统长期稳定运行并实现资源可控,我们设计了精细化的日志切片功能。该功能会根据预设的大小策略,自动滚动并分割本地 Oplog 文件。这一机制不仅能有效防止单个日志文件无限增长并耗尽存储资源,还极大方便了日志的归档、清理和管理,是确保服务在生产环境中持续稳定运行的关键环节。

最后,系统提供全面而强大的可观测性。通过实时比较上游 Oplog 的最新写入位置与下游已同步的 Offset,系统可以以极低的开销准确计算上下游实例之间的数据同步延迟。这些关键性能指标(KPI)可以无缝接入主流监控面板(如 Prometheus/Grafana)和告警系统。这样,运维团队便能实时、直观地掌握系统健康状态、同步链路状态和数据差异,从而在潜在风险演变为实际故障之前及时介入,有效保障业务连续性和数据安全。

核心优势

  • 高可靠性:基于持久化 Oplog 和大窗口增量同步机制,可以从容应对长期网络分区和延迟,确保数据变更得到准确记录并可靠恢复。
  • 高性能:作为轻量级 Redis Module,核心逻辑经过高度优化,直接在 Redis I/O 线程中执行,将对 Redis 核心性能的影响降至最低。
  • 高稳定性:智能日志切片机制会自动管理存储资源,有效防止日志累积导致磁盘空间耗尽,确保服务持续稳定运行。
  • 强可观测性:提供精确到操作级别的延迟计算和丰富的监控指标,使系统状态完全透明,便于集成和自动化运维,实现主动的风险预防与控制。

复制模式

从 Alauda Cache Service E1 v5.1.0 开始,跨数据中心复制提供两种模式,可通过 spec.activeRedis.mode 在 Redis 资源上为每个实例单独选择。这两种模式都运行上述复制引擎——使用相同的 Oplog、相同的全量和增量同步机制,以及相同的代理层。两者的区别在于成员如何相互发现,以及哪些成员接受原生应用写入。

灾难恢复双活
spec.activeRedis.modepeerof — 当 mode 为空时的默认值mesh
原生应用写入仅上游。下游处于待命状态。每个成员都在自己的数据中心中接受写入。
拓扑有向链路。一个上游向多个下游扩散(星型)。每个成员都与其他所有成员进行复制。
成员关系声明式。每条链路对应一个 ActiveRedisConnection,在下游侧创建。自动发现。每个成员对应一个 ActiveRedisMesh,其中指定若干种子地址;Gossip 会发现其余成员。
丢失一个数据中心手动故障转移——断开链路、提升一个下游并重定向客户端。无需提升步骤——将客户端重定向到存活的成员。
并发冲突写入只要写入持续发送到上游,就不会发生。持续存在,并由模块自动解决。
跨数据中心的时钟同步不要求。必需。
Redis 版本6.0、7.2仅 7.2

每种模式都有各自的页面:灾难恢复 和 双活。命令支持 和 限制与风险 适用于两种模式。

选择模式

当一个数据中心承载工作负载,而其他数据中心仅用于在该数据中心丢失时接管工作负载时,请选择灾难恢复。这是默认模式,在两代模块上均可用,并且其一致性逻辑很简单:只有一个写入者,因此无需将任何写入与其他位置的并发写入进行协调。代价是恢复需要有意执行手动操作,而不是自动完成——请参阅故障转移。

当多个数据中心中的应用必须写入各自的本地实例时,请选择双活——这可以降低本地写入延迟,或在任意一个数据中心丢失时无需执行提升步骤即可继续提供服务。代价是每个成员都是写入者,因此对同一个键的并发写入将按照不同于独立 Redis 的规则进行协调,并且这些规则由挂钟时间决定。由此产生两项要求,二者均不可省略:

  • 在将应用指向双活组之前,请阅读命令支持。其中逐条说明哪些写入会被拒绝、哪些写入会保留在本地,以及每种复制写入如何解决冲突。
  • 保持所有成员的系统时钟同步。模块会测量时钟偏差并发出告警,但绝不会因此阻止写入——请参阅时钟同步。

双活为 alpha,且仅适用于 Redis 7.2。已经在灾难恢复模式下进行复制的实例不应原地转换;应使用尚未接入灾难恢复组的实例构建双活组。

模式名称与 API 值不同

spec.activeRedis.mode 字段接受字面值 peerof 和 mesh。peerof 选择灾难恢复,并且当 mode 为空时为默认值;mesh 选择双活。本文档在行文中使用模式名称,在写入资源时使用 API 值。

模块代际与版本适用性

复制模块分为两代。实例加载哪一代模块由其 Redis 版本决定,而模块代际决定了功能集、身份验证模型和对等端传输方式。

在 v5.1 之前只有一种模块:适用于 Redis 6.0 的灾难恢复模块,于 v4.1.0 引入。Redis 7.2 实例和双活模式随 v5.1 中的新模块推出,旧模块代际目前仅为现有实例提供维护。

Redis 6.0(旧模块)Redis 7.2(新模块)
模块冻结的旧实现,仅为现有实例提供维护持续开发中的实现
灾难恢复(peerof)支持支持
双活(mesh)不支持支持
复制的命令集较小 — Redis 6.0 之后引入的命令不会被复制完整;请参阅命令支持
命令限制无 — MOVE、SWAPDB、RESTORE、FLUSHALL 和 FLUSHDB 会被复制,而不是被拒绝MOVE、SWAPDB 和 RESTORE 始终被拒绝;对等端连接时,FLUSHALL 和 FLUSHDB 会被拒绝
对等端身份验证模块级别不进行身份验证。链接会以实例的默认账户进行身份验证,operator 会通过 spec.activeRedis.redisUserRef 为你绑定该账户必需。实例会通过 spec.activeRedis.redisUserRef 绑定一个 RedisUser — 通常是其自身的默认账户,而该账户随后必须在每个数据中心中使用相同的密码
对等端传输Proxy Redis Serialization Protocol(RESP)端口(6379)相同的 Proxy RESP 端口(6379)— 一个端点承载两种传输。双活会在该端点上额外发布一个 Service 端口
持久化建议使用 RDB仅支持 RDB — appendonly=yes 会被准入拒绝
数据库数量标准databases 必须为 <= 16
不支持跨代际复制

Redis 6.0 实例与 Redis 7.2 实例之间的复制不是设计支持的路径 — 两代模块的协议不兼容。一个复制组中的每个成员都必须运行相同的模块代际。在 Redis 6.0 上启用复制会返回准入告警,并建议使用 Redis 7.2。

如需将现有 Redis 6.0 复制组迁移到新模块,请参阅将灾难恢复组从 Redis 6.0 升级到 Redis 7.2。

架构说明

本节所述组件 — proxy 层、其两个端口和 Service ID — 对两种模式都通用。

为简化访问不同 Redis 架构的复制系统的复杂性,我们设计了专用的 proxy 层。作为系统的核心组件,proxy 层为 Sentinel 和 cluster 模式提供统一的状态检测和数据同步入口。无论后端 Redis 采用何种部署形式,对等端都通过这一统一的 proxy 接口进行交互。proxy 层负责封装与特定架构(Sentinel、cluster)通信的内部逻辑,从而将复制系统与后端 Redis 的实现细节解耦,大幅简化实例的访问和管理。

两代模块都会部署一个 proxy。启用跨数据中心复制会创建一个 proxy Deployment 和一个名为 activeredis-proxy-<instance-name> 的 proxy Service。

对于 Sentinel 实例,实例名称会添加 rfr- 前缀。

端口

端口名称用途适用范围
6379proxyRESP 端点,也是两代模块的复制传输端点。proxy 会区分对等端会话和客户端会话,并相应地进行路由,因此一个端点可承载两者。这是记录在 mesh seed 条目和 ActiveRedisConnection 的 spec.addresses 中的地址。所有版本
由 Service 发布peer同一 proxy 监听器的别名,仅在双活模式下添加。mesh 成员会在模块自行固定的端口上广播对等端地址,此条目就是在该端口上响应的地址。请从 proxy Service 读取端口号,而不要自行假定。仅限 Redis 7.2 双活模式
灾难恢复链接使用一个端点

peerof 实例的 proxy Service 仅发布 RESP 端口,数据中心之间无需开放其他端口。灾难恢复链接仅寻址该端点 — 即下游的 ActiveRedisConnection 中记录的地址。

在双活模式下,原样发布每个 proxy 端口

当外部负载均衡器或防火墙位于双活成员的 proxy 前端时,必须发布 proxy Service 暴露的每个端口,并且每个端口都使用相同的端口号。mesh 会通过模块自行固定并原样播报的端口访问成员,因此重新映射该端口会导致 mesh 中断。RESP 端口是例外 — 可以通过 announcePort 重新映射。

实例 ID:Service ID

为在复制系统中唯一标识和管理每个 Redis 实例,我们引入了 service_id 的概念。此 ID 是整个系统中用于路由和数据同步的核心凭证。

  • 唯一标识符:每个 Redis 实例,无论是上游还是下游,都必须配置全局唯一的 service_id。系统使用此 ID 在成员之间建立映射关系。
  • 值范围:service_id 的有效范围为 [0-15]。
  • 拓扑限制:受 ID 范围限制,单个上游最多可关联 15 个下游实例,支持“一上游多下游”拓扑。
Service ID 不可变

实例创建后无法更改 spec.activeRedis.serviceID,启用跨数据中心复制后也无法将其关闭。两者都会被准入拒绝,因为模块的 Oplog 状态与该身份绑定。

术语

复制方向描述为上游(产生变更的实例)和下游(消费变更的实例)。ActiveRedis 资源状态字段 upstreamPeer、downstreamPeers 和 downstreamPeerCount 使用这些术语。

配置 Disaster Recovery 实例时,Web Console 将相同的概念显示为源端和目标端。源端是上游,目标端是下游。在 Disaster Recovery 模式下,实例的角色并非固定不变 — 目标端在故障转移期间也可以提升为源端。

这对名称描述的是流动方向,而非永久角色。在双活模式下,每个成员既是其发起的变更的上游,也是其从每个对等成员接收的变更的下游。

命令支持

并非所有 Redis 命令都可以跨越数据中心边界。某些命令会因错误而被拒绝,某些命令仅在本地执行且永不复制,而参与复制的写命令则按照不同于独立 Redis 的规则解决并发冲突。命令支持 是两种模式和两代模块的完整参考。将应用程序指向复制组之前,请先阅读该文档。

限制和风险

有关跨数据中心复制的风险和限制,请参阅文档限制和风险。