DNS 传播:为什么各地区看到的 IP 不一样(附验证方法)

改完 DNS,有人看到新 IP、有人还是旧的。本文讲清楚为什么地区不一致是正常现象,并给一套可量化的修复与验证路径。

你在 Cloudflare、GoDaddy 或 Route 53 改完一条 A 记录或 CNAME:本机 dig 已经返回新值,公司同事还是打不开,海外朋友刷新一次新一次旧。这不是 bug,而是 DNS 缓存的工作方式:全球数万台递归解析器各自按你设的 TTL 缓存这条记录,没有”一键全球清缓存”这种按钮。

最快的修复(先做这个):直接问域名自己的权威 NS(dig +short yourdomain.com @<你的-NS>),确认改动确实落到了 authoritative,然后清掉本机缓存,让你自己先看到新值。其他人会随着各自缓存的 TTL 到期而陆续更新——对标准 A/CNAME/TXT 记录来说,通常是几分钟到一两小时,而不是常被人引用的 24–48 小时(那个数字是改域名 NS 服务器时的,不是改记录)。

先判断你属于哪种情况

动手之前先跑这三条检查。它们能告诉你:改动有没有生效、延迟是全球性的还是只在本机、以及这到底是真传播延迟还是 GeoDNS 的设计。

检查项命令显示值说明显示值说明
权威是否已更新dig +short yourdomain.com @<你的-NS>改动已生效,等缓存过期记录根本没保存成功,去改
公网解析器是否一致dig +short yourdomain.com @8.8.8.8@1.1.1.1传播接近完成resolver 缓存延迟(正常)
是否只有本机旧浏览器旧但 dig @8.8.8.8 已是新值清本机 + 浏览器缓存再等一个 TTL

常见原因

按命中率从高到低。

1. 旧 TTL 还在递归解析器里倒计时

如果改之前那条记录的 TTL 是 3600 秒(1 小时),那么在你改完的那一刻,全世界已经缓存它的解析器会按各自剩余的秒数继续返回旧值——最坏情况是改完前 1 秒被缓存,要整整 1 小时(差 1 秒)才轮到失效。

$ dig +short yourdomain.com @8.8.8.8
76.76.21.21      # 新值(Vercel)

$ dig +short yourdomain.com @1.1.1.1
185.199.108.153  # 旧值(GitHub Pages)— Cloudflare 缓存还没过期

如何判断:用 dig 对同一个域名分别问几个公网解析器(8.8.8.8 / 1.1.1.1 / 9.9.9.9 / 114.114.114.114)。结果不一致就是 resolver 缓存延迟,随着各自缓存到期会自动消失。

2. ISP 解析器不尊重你的 TTL

部分运营商(特别是中国大陆、印度、东南亚)的递归解析器会强制把所有记录的 TTL 抬到 1 到 24 小时以节省回源开销,无论 authoritative 那边设的是多少。

如何判断:用 dig +noall +answer yourdomain.com 看返回里的 TTL 数值。如果远高于你 authoritative 设的值,就是被运营商重写了。(隔几秒再跑一次——如果 TTL 完全不往下走,基本可以确认是静态覆盖。)

3. 同时存在多个 authoritative DNS 源

域名注册商默认 NS 没改、但你已经把 zone 搬到了 Cloudflare;或者历史上加过 GoDaddy 加 Cloudflare 的双重托管。不同 resolver 命中不同 authoritative,给出不同答案,于是无论等多久都不会收敛。

如何判断

dig +short NS yourdomain.com
# 期望看到一组一致的 NS(比如全部 *.ns.cloudflare.com)
# 出现混合厂商就是多源,去注册商把 NS 改成一家

4. 本机的操作系统、浏览器或 stub resolver 缓存

macOS 的 mDNSResponder、Linux 的 systemd-resolved / nscd / dnsmasq、Chrome 内置的 host cache,都会再缓存一层。你 authoritative 已经更新、公网 resolver 也已经刷新,本机这层还在用旧 IP。

如何判断dig +short yourdomain.com @8.8.8.8 直接问公网已经是新值,但浏览器仍然连旧 IP。这个差距几乎总是本机缓存造成的(清理见 Step 3)。

5. CDN / 负载均衡在 DNS 之上做了 GeoDNS

Cloudflare、AWS Route 53 latency-based routing、Vercel Anycast 会按用户地理位置返回不同 IP——这本身就是设计,看起来像”传播不一致”,但它永远不会收敛成单一 IP。

如何判断:用 https://dnschecker.org 看各地区返回的 IP 是不是都属于同一家厂商的不同 PoP;用 whois <ip> 查两个不一样的答案,如果归属同一个网络,那就是 GeoDNS,正常。

最短修复路径

DNS 传播没法”加速”,但你可以做到:先确认 authoritative 正确、再用工具看清传播进度、最后让本机立即生效。

Step 1:先验证 authoritative 已经更新

直接问域名的 NS,跳过所有 resolver 缓存:

# 找出当前的权威 NS
dig +short NS yourdomain.com
# 例如返回 ns1.vercel-dns.com.

# 直接问权威,必须返回新值
dig +short yourdomain.com @ns1.vercel-dns.com

如果这一步还是旧值,说明记录根本没改成功。回控制台核对一遍。两个最常见的坑:CNAME 的 FQDN 末尾少了一个 .,以及用了过时的厂商目标值。截至 2026 年 6 月,Vercel 现在给的是项目专属的 CNAME,例如 cname.vercel-dns-017.com,而不是通用的 cname.vercel-dns.com;旧的通用值和 76.76.21.21 这条 A 记录仍然可用,但请直接复制控制台显示给你的那个目标值。

Step 2:用 dnschecker 看全球传播进度

打开 https://dnschecker.org,输入域名,选好记录类型(A、CNAME 等),看那张绿勾对红叉的地图:

已更新节点比例含义
< 30%还在早期,可能只过去几分钟
50–80%正常推进,再等一个 TTL 即可
> 80% 但某地区始终旧那个地区的 ISP resolver 在硬扛它的旧 TTL

如果大多数地区已经返回新值、只有零星节点旧,就属于正常推进中。如果等满一个 TTL 比例还纹丝不动,回去查原因 3(多个 authoritative 源)。

Step 3:清掉本机各层缓存让自己先看到

# macOS(Catalina 及以后)
sudo dscacheutil -flushcache && sudo killall -HUP mDNSResponder

# Linux —— systemd-resolved
sudo resolvectl flush-caches
# Linux —— 老版本 systemd-resolve 命令
sudo systemd-resolve --flush-caches
# Linux —— nscd
sudo systemctl restart nscd
# Linux —— dnsmasq
sudo killall -HUP dnsmasq

# Windows(以管理员身份运行 命令提示符 或 PowerShell)
ipconfig /flushdns

Chrome 单独有一层缓存,跟操作系统的是分开的:地址栏访问 chrome://net-internals/#dnsClear host cache,再到 chrome://net-internals/#socketsFlush socket pools(即使清了 host cache,Chrome 也可能还保持着一条连向旧 IP 的连接)。

Step 4:暂时绕开自己 ISP 的 resolver

把系统 DNS 改成 1.1.1.1 或 8.8.8.8(这两家对 TTL 处理最规矩),重启浏览器再试:

# macOS 临时改
networksetup -setdnsservers Wi-Fi 1.1.1.1 8.8.8.8
# 恢复成 DHCP 下发的 DNS
networksetup -setdnsservers Wi-Fi empty

Step 5:等满一个旧 TTL

记下你改记录时上一版的 TTL(注册商面板通常能查历史)。从改动时刻开始等满那个时间——常见值 300s / 1800s / 3600s。如果不知道,按 1 小时等。等满之后,绝大多数 resolver 都会回源拉新值。

下一次迁移前一天先把 TTL 降到 300s,迁完观察一段时间再升回去,可以把”等多久”从 1 小时压到大约 5 分钟。

如何确认已经修好

下面三条同时为真,才算真正搞定:

  1. 权威正确dig +short yourdomain.com @<你的-NS> 只返回新值。
  2. 公网解析器一致dig +short yourdomain.com @8.8.8.8@1.1.1.1 都返回新值,且 dnschecker.org 基本全绿。
  3. 端到端可用:清完本机缓存后,curl -sI https://yourdomain.com 返回预期结果(正确的 server 头、正确的证书、HTTP 200 或你设计的跳转)。curl -v 里的 IP 应该等于新记录的值。

注意:迁移的头几个小时里,站点可能解析正确却仍然 TLS 失败;如果 curl 报证书错误,那是 SSL 签发延迟、不是 DNS 问题,参见下方 SSL 文章。

预防建议

  • 计划迁移前 24 到 48 小时先把对应记录的 TTL 降到 300s,迁完观察 1 天再升回去。
  • DNS 只保留一个权威来源(Terraform、OctoDNS 或单一厂商),杜绝双家托管。
  • CNAME 记录始终用 FQDN(末尾带 .),避免被解析成 foo.example.com.example.com
  • 上线前用 dig +trace yourdomain.com 走完整 root、TLD、authoritative 链路,确认没有 lame delegation。
  • 维护一个”DNS 健康检查” cron:每 5 分钟对 3 个以上公网解析器查同一个域名并对比结果,不一致就告警。

常见问题

DNS 传播到底要多久? 对标准 A、CNAME、TXT 记录的改动,通常是几分钟到一个 TTL(多半在 1 小时以内)。常被引用的”24 到 48 小时”指的是改域名的 NS 服务器,不是在现有 zone 里改记录。

dig 已经是新 IP,浏览器还是打开旧站,为什么? 你的浏览器或操作系统还留着旧缓存。两层都要清(见 Step 3),包括 Chrome 的 chrome://net-internals/#dns host cache 和 socket pools,然后彻底重启浏览器。

能强制 DNS 全球立即更新吗? 不能。递归解析器的缓存没有全球清除手段。你只能清自己的机器、换自己的 resolver;互联网其余部分会随各自缓存的 TTL 到期而更新。

不同地区一直返回不同 IP、始终不收敛,是坏了吗? 多半没坏。如果这些 IP 都属于同一家厂商(用 whois <ip> 查),那是 GeoDNS 的设计。如果属于不同厂商,那很可能是有两个 authoritative 源同时在线——去修 NS 记录(原因 3)。

为什么过了一天只有我的 ISP 还是旧值? 部分 ISP 解析器会覆盖你的 TTL、缓存长达 24 小时。用 dig +noall +answer 确认(返回的 TTL 不会往下走),再通过 1.1.1.1、8.8.8.8 和 dnschecker.org 验证世界其余地方都已经正确。

相关阅读

标签: #部署 / 托管 #排查 #排查 #DNS