你在 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/#dns 点 Clear host cache,再到 chrome://net-internals/#sockets 点 Flush 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 分钟。
如何确认已经修好
下面三条同时为真,才算真正搞定:
- 权威正确:
dig +short yourdomain.com @<你的-NS>只返回新值。 - 公网解析器一致:
dig +short yourdomain.com @8.8.8.8和@1.1.1.1都返回新值,且 dnschecker.org 基本全绿。 - 端到端可用:清完本机缓存后,
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 验证世界其余地方都已经正确。