TTL 太高让 DNS 变更变慢:2 个原因 + 修复路径

改了 DNS 却要 24h+ 才传播——改之前先降 TTL 让传播可预测。

你把一条 A 记录从旧主机改到新主机。新服务器已经就绪——curl 新 IP 能看到新站点。但一半用户还看到的是旧站,邮件日志里还有流量打到旧 IP,手机用 4G 看到新站、笔记本连家里 Wi-Fi 看到旧站。其实什么都没坏——你正在见证全球各地缓存的 DNS 按各自的节奏过期,因为你改之前那条记录的 TTL 设得太高了。

这是”DNS 怎么还不传播”投诉最大的一类来源,而且完全可以预防。修复只需要 30 秒,但前提是你要在变更前 24 小时做,不是变更后。

TTL 到底怎么控制传播

TTL(Time To Live)是权威 DNS 服务器在每条应答里附带的一个秒数。从你到用户中间的每一层递归 resolver(用户家 ISP、公司防火墙、Cloudflare 1.1.1.1、Google 8.8.8.8)最多缓存这段时间。

  • TTL 300 = 5 分钟过期 → 下次查询回到权威 → 用户 5 分钟内看到新值。
  • TTL 3600 = 最长 1 小时。
  • TTL 86400 = 最长 24 小时。
  • TTL 172800(2 天)= 最长 48 小时。很多注册商的默认值。

决定旧值能在缓存里活多久的,是变更之前那条记录的 TTL。同一时刻改值和改 TTL 对已经在外面的缓存没用——它们早就把值和 TTL 一起拿走了,会按那个时间继续缓存。

先判断属于哪一种

情况 1:今天才改记录,到现在还没全传播

最常见。你今天同时改了值和 TTL。外面老的缓存还在按旧 TTL 倒数。

怎么看

# 直接查权威,立刻能看到新值
dig yourdomain.com @ns1.your-dns-provider.com +short

# 查公共 resolver,有的新有的旧
dig yourdomain.com @8.8.8.8 +short
dig yourdomain.com @1.1.1.1 +short
dig yourdomain.com @9.9.9.9 +short

# 看缓存中 TTL 的倒数
dig yourdomain.com @8.8.8.8
# 看 ANSWER SECTION 里 TTL 那一列,就是剩余秒数

如果权威已经返回新值,但公共 resolver 还返回旧值,那就是旧 TTL 还没走完。

修复:没有现场的修复,只能等。下次提前 24 小时降 TTL。

情况 2:DNS provider 偷偷封顶 / 忽略你设的 TTL

某些注册商自带的 DNS(老版 Namecheap 共享 DNS、部分 GoDaddy 套餐、Bluehost 免费 DNS)会把 TTL 封到 3600 或 86400,不管你填多少;或者 UI 显示 300、实际响应里却是 7200。

怎么看

# 权威实际返回的 TTL 是多少?
dig yourdomain.com @<authoritative-ns> | grep -E "^yourdomain"
# 中间那个数字就是 TTL(秒),对比 UI 上的值。

UI 显示 300 但 dig 显示 3600+,就是 provider 撒谎。

修复:换一个真正尊重 TTL 的 DNS provider(Cloudflare、Route 53、Google Cloud DNS、deSEC)。或者接受封顶,所有变更提前一天计划。

情况 3:负缓存(NXDOMAIN TTL)让新子域名迟迟不解析

你第一次加 blog.example.com,结果还是不解析。这不是 A 记录的 TTL,是 SOA minimum TTL,它控制 resolver 把 NXDOMAIN 回应缓存多久。

怎么看

dig SOA yourdomain.com +short
# 输出格式: ns1... admin... serial refresh retry expire minimum
# 最后一个数字就是负缓存 TTL
# 是 86400 的话,NXDOMAIN 最长被缓存一天

修复:在 DNS provider UI 上降低 SOA minimum 字段(界面里可能叫”Negative TTL”或”NXDOMAIN TTL”)。Cloudflare 和 Route 53 默认就是 300;老 zone 可能是 86400。

情况 4:DNS 前面有 CDN / 代理层

Cloudflare 的代理模式(橙云)会给外面发一个很短的 TTL,但对你的 origin TTL 在缓存头上完全无视。Vercel 和 Netlify Edge 各有自己的缓存。

怎么看dig yourdomain.com +short 返回的是 Cloudflare 的 IP(104.x.x.x),不是你的源站。那些 IP 上的 TTL 都很短,但 Cloudflare 的内部回源遵循他们自己的规则。

修复:DNS 层的传播,前面挂了 Cloudflare 之后 TTL 就不重要了——他们 30 秒左右就在自家边缘切完。如果你说的是”用户还看到旧站”,那是 HTTP 缓存不是 DNS——从 Cloudflare 仪表盘 purge 缓存。

最短修复路径(下一次变更前用)

修复是流程性的,不是补救式的。任何计划中的 DNS 变更前 24 小时跑这一套:

  1. 24 小时前:在权威 DNS provider 上把你打算改的每一条记录的 TTL 从当前值(往往 3600 或 86400)改成 300。值先不动,保存。

  2. 等旧 TTL 走完。旧 TTL 是 3600 就至少等 1 小时;是 86400 就等 24 小时。从这之后,所有缓存都会在 5 分钟内刷新一次。

  3. 再做真正的变更(值改 + TTL 还是 300)。

  4. 验证

    for resolver in 8.8.8.8 1.1.1.1 9.9.9.9 208.67.222.222; do
      echo "@$resolver: $(dig yourdomain.com @$resolver +short)"
    done

    5 分钟内每个 resolver 都应该返回新值。

  5. 第二天:把 TTL 升回 3600 或更高,降低 DNS 查询压力,提高缓存命中率。

怎么查当前真正在用的 TTL 是多少

# 权威 TTL(DNS provider 发出去的)
dig yourdomain.com @<authoritative-ns> | awk '$1=="yourdomain.com." {print $2; exit}'

# 公共 resolver 缓存中的 TTL 倒数(每次查询都在变)
dig yourdomain.com @8.8.8.8 | awk '$1=="yourdomain.com." {print $2; exit}'

# 60 秒后再查一次 —— 应该减少约 60
sleep 60
dig yourdomain.com @8.8.8.8 | awk '$1=="yourdomain.com." {print $2; exit}'

如果倒数突然跳回完整 TTL,说明 resolver 已经回权威拿了新值——从这一刻起,用这个 resolver 的所有用户都看到新值了。

预防

  • 把 TTL 当成维护前要拧低的旋钮。 设一个日历提醒:“T-24h: 把 TTL 降到 300”。然后变更。再”T+24h: 升回 3600”。
  • 经常改的记录(预览环境、staging、A/B 测试 endpoint)长期保持 TTL 300,查询负载基本可以忽略。
  • 几乎不会动的记录(根 MX、SPF TXT、DKIM TXT)TTL 设到 86400,缓存命中率更高,DNS provider 偶尔出问题也更稳。
  • 不要同时改 TTL 和记录值 —— 没有意义。决定缓存寿命的,是上一次的 TTL 和上一次的值。
  • 挑一个尊重 TTL 的 DNS provider。 Cloudflare、Route 53、Google Cloud DNS、NS1、DNSimple 都严格遵守。便宜注册商捆绑的 DNS 经常不遵守。

这些情况不是你的问题

  • 用户 ISP 有自己的缓存层,无视权威 TTL,按固定周期缓存(少见,但 Comcast 和一些亚洲 ISP 有记录)。
  • 公司防火墙 / WAF 单独缓存 DNS。
  • 浏览器层的 DoH 配置和操作系统缓存是分开的。
  • 用户手动改了 /etc/hosts,根本不走 DNS 了。

这几种你都没法控。能做的就是告诉用户预期的传播窗口,然后继续走。

FAQ

问:生产环境的长期 TTL 多少合适? 答:3600(1 小时)是”紧急时还能改”的最佳点。86400(1 天)适合永远不动的记录。300(5 分钟)只在计划变更期间或每周都改的 endpoint 上用。

问:降低 TTL 会影响性能吗? 答:影响很小。每次缓存 miss 多一次 DNS 回程(~20ms),并且只是该 resolver 区域里第一个用户。TTL 300 的繁忙 resolver 仍有 99%+ 的命中率,影响微乎其微。TTL 3600 影响更小。

问:Cloudflare 代理说 TTL 是 auto,什么意思? 答:记录被代理(橙云)时,Cloudflare 用自己的 IP 加固定短 TTL(约 5 分钟)发给外面。你设的”auto”对外不重要,但 Cloudflare 自己边缘在源站变更后约 30 秒就更新。DNS-only(灰云)记录就按你设的 TTL 来。

问:能强制让 resolver 清缓存吗? 答:基本不行。你只能清自己机器的,也可以让用户清。公共 resolver 不会因为你的请求就 flush。例外:Google 提供 dns.google/cache 可以从 8.8.8.8 清掉某个特定名字;Cloudflare 也有针对 1.1.1.1 的类似表单。对那 1% 死磕看旧值的用户事后管用。

问:我已经降了 TTL,但变更还是慢。 答:你今天降 TTL,今天又改记录。决定缓存中旧值寿命的是旧的TTL。如果旧 TTL 是 86400,要等 24 小时让缓存全部刷掉。之后的变更才会很快。

相关阅读

标签: #域名 #DNS #SSL #排查 #TTL #DNS 传播