DNS TTL 与故障切换:一次误判的复盘

几个月前我们做过一次“提高故障切换速度”的改造:把业务域名的 TTL 从 3600 秒降到 60 秒。按理说,主节点挂掉之后,最多一分钟客户端就该解析到备用节点。实际演练时,部分用户的恢复时间超过了十五分钟。这篇记录我们后来查到的原因。

假设

最初的假设非常朴素:TTL 决定缓存时间,TTL 小,缓存过期快,切换就快。这个模型忽略了三件事:

  • 递归解析器不一定会严格遵守 TTL,尤其是开启了“缓存优化”的公共 DNS;
  • 客户端和 CDN/网关之间的长连接不会因为 DNS 变化而重建;
  • 操作系统的 stub resolver 自己还有一层缓存。

查到的证据

1. 递归解析器的缓存

我们在切换前后用多个公共 DNS 分别查询,发现有的解析器在 TTL 到期后仍然返回旧记录,延迟几秒到几十秒不等;还有的解析器在 TTL 之外叠加了自己的最小缓存时间。也就是说,60 秒的 TTL 实际生效时间可能是 90 秒甚至更久。

2. 连接复用掩盖了 DNS 变化

这是影响最大的一点。移动端 SDK 和网关之间维持着 HTTP/2 长连接,DNS 解析结果只影响新连接的建立。故障发生时,旧连接在 TCP 层已经死了,但客户端要等到读写超时才会重建连接——这个超时设置是 30 秒,重试还有退避。DNS 再快也没用。

3. stub resolver 的 negative cache

故障期间我们把记录短暂摘除过,结果部分客户端缓存了 NXDOMAIN,恢复后仍然解析失败。后来改成直接把记录指向备用地址,而不是删除记录,问题才消失。

改了什么

  • TTL 保持在 120 秒,不再追求极端的 60 秒——收益有限,反而增加了权威 DNS 的查询压力;
  • 客户端把连接空闲超时从 30 秒降到 10 秒,并在连续失败时主动重建连接;
  • 切换流程从“删记录再加记录”改成“改记录指向”,避免 NXDOMAIN 被缓存;
  • 增加了从多个地理位置对权威 DNS 的主动探测,切换后验证而不是假设。

结论

DNS 只是故障切换链路里的一环,而且往往不是最慢的那一环。真正决定恢复时间的是客户端的连接管理和重试策略。把 TTL 当成开关,是一种很常见的错觉。

复盘的价值不在于找到“是谁的错”,而在于修正那个过于简单的模型。我们原来的模型里,只有 DNS 一个变量。

← 返回文章列表