在线 Aeron® 集群跨区域迁移
早晚你都要搬一个在线集群——区域迁移、换数据中心,或者当前部署已经用到瓶颈。让人安心的结论是:有了 Premium Cluster Standby,这是一份运维手册,而不是一次重建,而唯一有意义的停机,就是一次你能靠优雅让位参数压短的 leader 跨越。本页覆盖两种已验证的方式、它们的实测代价,以及那个会悄无声息破坏透明路径的隐患。
它承接 Aeron® 集群部署 收尾的地方:那页讲的是选哪种拓扑,本页讲的是如何在拓扑之间搬迁而不重建。除非另行标注,下面所有数字都是在单机上实测(3 节点集群,无 WAN)——把它们当作代价的形状,而不是对 WAN 延迟的预测。
前置状态:区域 B 里的 standby 已在 tailing
Section titled “前置状态:区域 B 里的 standby 已在 tailing”两种方式的起点相同,而且都是纯粹的 Cluster Standby:在线的 3 节点集群跑在区域 A;区域 B 里三个 standby 节点持续跨 WAN 拉取日志。standby 不投票,所以在你做准备期间,共识提交完全留在 A 本地——热路径里没有 WAN。两种方式的区别,在于你怎么把 B 从 tailing 翻转成对外服务。
| 逐节点(滚动) | 整集群切换(一次性割接) | |
|---|---|---|
| 机制 | 通过 PremiumClusterTool transition-as-member <id> + 主机名重指向逐个替换成员;全程同一个集群 | 把整个 B standby 组(2 参数的 transition)提升为一个新集群;再重指向客户端 |
| 集群身份 | 一个连续的集群,成员就地替换 | B 里一个全新的、独立的集群 |
| 步骤 | N 次顺序替换,每个节点都要 DNS 重指向 + 严格排序 | 一次提升触发 + 一次客户端切换 |
| 客户端端点变更 | 否——复用主机名,客户端自动跟随 | 是——新集群,客户端必须重指向 |
| 已验证 | follower:是——standby 加入运行中集群的槽位 k,3/3 健康。leader 跨越:在我们的单机测试台上尚未干净收敛(见下文) | 是——B 组组成一个集群,客户端恢复 |
在下面逐步走一遍两种迁移——切换场景,再用 播放 或 下一步 看每一步。留意两个仪表:OMS → leader 延迟(面向客户端的那一跳)和共识提交路径(只有当投票多数派不在 leader 一侧时才跨越 WAN)。
逐节点 —— follower 免费,leader 才是全部代价
Section titled “逐节点 —— follower 免费,leader 才是全部代价”一次一个地把 standby 提升进成员槽位。先换 follower,最后换 leader:
- follower 替换几乎零客户端中断(实测:正好 0 条消息丢失)。leader 和多数派都留在 A;换一个 follower 对客户端是透明的。
- 一次只动一个成员——Raft 的成员变更在设计上就是单服务器的。在一个 3 节点集群里一次换两个,会瞬间跌破多数派并停摆。预热好的 standby 让每一步都很快(只回放一小段尾部日志,而不是拉整个快照)。
- 那唯一一次 leader 替换,才是唯一客户端可见的冲击。 移除 A 里最后一个成员——也就是 leader——会触发一次由 B 成员胜出的选举。默认且非优雅方式下,这是 ~11.8 秒(幸存者要熬过 ~10 秒的
LEADER_HEARTBEAT_TIMEOUT,再加 ~1 秒选举)。AeronCluster客户端会根据推送来的NewLeaderEvent自动跟随到新 leader——无需应用代码,也不用改端点。
有一个值得点名的临时窗口:一旦三个投票成员里有两个落在 B、而 leader 还在 A,提交路径就要跨越 WAN(leader 需要一个 B 的 ack 才能凑够多数派)。推荐的顺序会通过直接进入 leader 步骤,把这个窗口压短。
整集群切换 —— 对所有人一次有界的冲击
Section titled “整集群切换 —— 对所有人一次有界的冲击”静默或强制下线整个 A 集群,把三个 B standby 作为一组提升进一个全新集群,再重指向客户端:
- 一次 ~7–8 秒的中断,一次性冲击所有客户端(实测,强行 fail)。没有免费的 follower 步骤——整组一起动。
- B 组会跑一次全新的启动选举(
STOP_FOR_EXPORT → RECOVER_CONSENSUS_MODULE → CONSENSUS)。这里没有在任者需要让位,所以没有优雅交接 /RESIGN的手段——它的 ~7–8 秒接近下限,不是一个可压缩的数字。 - 客户端必须重指向。 B 是一个端点不同的不同集群,已死的 A 集群没法通告这些端点。你要把 B 的 ingress 列表显式交给客户端(配置/DNS 推送,或
switchToStandby模式)。从构造上就对客户端不透明。
实测停机时间
Section titled “实测停机时间”| 阶段 | 逐节点 | 整集群切换 |
|---|---|---|
| follower 迁移 | ~0 客户端中断(0 条消息丢失) | 不适用(整组一次动) |
| leader 转换 | ~11.8 秒重新选举(熬过 LEADER_HEARTBEAT_TIMEOUT) | ~7–8 秒新组的启动选举 |
| transition 本身 | 每节点 ~2 秒(对 follower 而言不在客户端路径上) | ~0.4 秒 |
| leader 出现后的客户端切换 | <100 ms(自动跟随) | <100 ms(切换后) |
| 客户端可见的总中断 | ~11.8 秒——但只在那唯一一次 leader 替换 | ~7–8 秒,一次性冲击所有客户端 |
| 客户端端点变更 | 否 | 是 |
要仔细读这些总数:逐节点把工作摊到 N 步,其中只有 leader 替换是客户端可见的;整集群切换是对所有人的一次冲击。“哪个更快”归结为你能把那一次 leader 选举做到多便宜——这正是下一节的内容。
把故事补完整:让 leader 跨越变便宜
Section titled “把故事补完整:让 leader 跨越变便宜”leader 跨越是两种方式里唯一可压缩的停机,而它和日常的 leader 再平衡是同一根杠杆——所以集群部署相关的页面早已覆盖它。这也是迁移和日常运维交汇的地方:
- 调低
LEADER_HEARTBEAT_TIMEOUT(默认 10 秒 → 1–2 秒)——leader 空档的单一主导项,纯配置。代价是在抖动/高延迟链路上会多出误判选举。见 调优集群故障切换时间。 - 优雅让位 /
RESIGN——一次显式的自愿让位会确定性地强制走快速选举路径。实测:一次计划内的交接是 调优后 ~57 ms / 默认 ~266 ms,而一次非计划死亡要付 ~11 秒——调优前便宜 ~40 倍,调优后 ~190 倍。这和你在任何故障切换后收回主节点所在可用区用的是同一套机制。完整走查:主节点放置与优先主节点控制,逐个参数的时间线见 调优优雅让位时间。
有了 RESIGN,逐节点的 leader 步骤会降到 ~1–2 秒 / 亚秒级——低于整集群切换的下限——而它的 follower 步骤仍然免费。这就把默认的排名颠倒了过来:有了优雅让位,逐节点既更快又对客户端透明。
DNS / JVM 缓存隐患(逐节点、复用主机名时)
Section titled “DNS / JVM 缓存隐患(逐节点、复用主机名时)”逐节点只有在 B 节点复用 A 的主机名、且每个 JVM 都重新解析这个被重指向的名字时,才对客户端透明。这一环是关键,而且很容易做错——但隐患到底存不存在,取决于你跑的是哪种解析器:
- Aeron 会周期性地重新解析(
aeron.driver.reresolution.check.interval,默认 1 秒)。解析器是可插拔的(MediaDriver.Context.nameResolver(...));暴露程度完全看你选哪一种。 - 用默认的
InetAddress解析器——隐患存在。DefaultNameResolver调的是InetAddress.getByName,它受 JVM DNS 缓存约束(networkaddress.cache.ttl,在 SecurityManager 下会永久缓存)。一旦 JVM 缓存了旧 IP,Aeron 那个 1 秒的重解析循环就会一直拿到陈旧答案,重指向于是悄无声息地不生效——成员卡在那个已失效的 IP 上,而 Raft 不报任何错。只要在任意一个节点或客户端上漏掉-Dnetworkaddress.cache.ttl=0,就会踩中。缓解办法是到处都设cache.ttl=0,并为了快速割接优先用/etc/hosts改写(即时、本地)而不是外部 DNS。这些能减轻隐患,但去不掉。 - 用自定义
NameResolver——隐患消除(已验证)。 一个通过InetAddress.getByAddress(name, rawBytes)从你自己的控制平面返回地址的解析器,根本不碰 JVM DNS 缓存,也不碰平台解析器。 一次 EC2 实测用最狠的方式证明了这点:把 JVM 缓存钉在高位(networkaddress.cache.ttl=600)、并让 Aeron 的身份名字完全不进 DNS,逐节点的 follower 替换照样加入了运行中集群,重指向在 ~1 秒内生效——因为解析走的是自定义解析器,而不是InetAddress。一个由 Consul/etcd/配置服务/文件支撑的NameResolver,才是正经生产部署该选的。 - 无论哪种,这都不会左右停机时间——客户端可见的停机是那次 leader 选举,它的发生和 DNS 毫无关系。解析只决定替换成员何时变得可达(也就是何时恢复到 3/3 容错)。
落到决策上:DNS 缓存隐患只有在你依赖 InetAddress/DNS//etc/hosts 时才是真问题。如果你能部署自定义解析器,它就不再是偏向整集群切换的理由。整集群切换则是从构造上绕开它:B 用的是不同的端点,所以客户端是全新连到新名字——不存在”同名换 IP”这种会被陈旧缓存搞砸的情况。(只有当你故意为 B 复用 A 的主机名时才需要在意。)
什么时候选哪个
Section titled “什么时候选哪个”| 选择… | 当… |
|---|---|
| 整集群切换 | 你想要更简单的路径,并且能接受对所有客户端一次性、有界的 ~7–8 秒冲击。当你没有(也不想维护)RESIGN 分支时的默认选项。客户端必须重指向到 B 的端点。 |
| 逐节点 | 你需要客户端透明的成员搬迁(复用主机名、不改端点),且 follower 以 ~0 中断迁移;并且 / 或者你能部署 RESIGN 分支(或调低心跳超时),让那唯一一次 leader 跨越做到亚秒级。代价:N 步的复杂度;同主机名的纪律(外加要么 cache.ttl=0//etc/hosts、要么一个自定义 NameResolver——后者能把 DNS 缓存隐患彻底去掉);每次替换期间一段容错降低(2/3,无备份)的窗口;以及一次非优雅时约 11.8 秒、且我们还没能证明其干净收敛的 leader 跨越(follower 步骤是免费且已验证的)。 |
生产注意事项
Section titled “生产注意事项”- 按分片逐一进行。 每个 ME 分片都是独立的集群。先迁非关键分片,观察约 5 分钟,再分批错峰迁其余的——绝不一次全上。
- 把容错降低的窗口压短。 逐节点替换期间集群跑在 bare quorum(2/3,无备份)。在下一次替换之前,先重启每个已让位的节点、让它作为 follower 重新追平;别把已让位的节点晾着不管。
- 网关在两个区域都保留,这样外部客户端在整个迁移期间及之后都能连到任意一个区域。
另见:Aeron® 集群部署、集群 Standby 与多可用区 HA 设计、客户端与集群通信(NewLeaderEvent 与客户端重连),以及 主节点放置与优先主节点控制。
本站与 Adaptive Financial Consulting Limited 或 Aeron 项目无任何关联,未获其背书或赞助。 Aeron 是 Adaptive Financial Consulting Limited 的注册商标。
Aeron 是 Adaptive Financial Consulting Limited 在英国及其他国家/地区的商标。