DNS 基础 · 缓存与 TTL

DNS 缓存与 TTL
为什么改了解析要等生效

明明后台已经改了 IP,为什么用户访问还是旧站点?因为缓存不止一层——TTL 没到期之前,谁都不会去权威服务器拿新答案。

多层浏览器/系统/路由器/递归
TTLRFC 1035 · 单位秒
最长 = 旧 TTL生效等待上限
提前调小变更前标准操作
TL;DR · 核心结论

DNS 缓存分浏览器、操作系统、路由器、递归解析器四层,每一层都会把查到的结果暂存一段时间,时长由记录的 TTL(生存时间,RFC 1035 定义的秒数字段)决定。你在权威后台改了 IP 之后,旧值仍会沿着这四层缓存继续被使用,直到各层缓存按旧 TTL 自然过期——所以"全球生效"最坏要等满一个 TTL(常见 600–86400 秒)。想立刻看到新值,清本机缓存(ipconfig /flushdns)+ 无痕窗口测试即可;但要让所有用户都切到新值,只能等缓存过期,或提前把 TTL 调小。

Cache Layers

DNS 缓存分四层,改一处不够

从浏览器到递归解析器,每一层都可能"自作主张"地记住旧结果

缓存层谁在存缓存内容如何主动清掉
① 浏览器缓存Chrome / Firefox / Edge近期访问过的域名解析结果,配合 HOST 解析缓存清浏览器缓存,或用无痕/隐私窗口测试
② 操作系统缓存Windows DNS Client、nscd、systemd-resolved、mDNSResponder本机最近解析结果,TTL 内重复使用Windows ipconfig /flushdns;macOS sudo dscacheutil -flushcache
③ 路由器缓存家里/公司的路由器(dnsmasq 等)全屋设备共享的解析结果重启路由器,或登录后台手动刷新
④ 递归解析器缓存运营商 DNS、公共 DNS(8.8.8.8 等)、自建解析器大量用户共享的权威记录缓存,按 TTL 过期普通用户无法清,只能等 TTL 到期;自建解析器可手动 flush

关键认知:越靠上层(浏览器、系统),你越容易控制;越靠下层(公共递归解析器),你越无能为力。前两层你一条命令就能清,但全国/全球用户正在用的那台递归解析器,它缓存的旧结果你动不了——这就是为什么"我自己这边已经新了,别人还在访问旧站"。

What Is TTL

TTL 是什么?RFC 1035 里的那个秒数字段

TTL 由权威域名服务器写在每条记录里,所有下游缓存共同遵守

TTL(Time To Live,生存时间)是 DNS 响应报文中的一个字段,单位是秒,定义见 RFC 1035。它的含义非常直接:这条记录从权威服务器发出那一刻起,下游任何缓存——操作系统、递归解析器——最多可以把它缓存这么久;到期后缓存条目失效,下一次查询必须重新向权威服务器获取。

用 dig example.com 看输出,每条答案前都标着这个数字:

# dig 输出里的 300 就是 TTL(秒) ;; ANSWER SECTION: example.com. 300 IN A 93.184.216.34

常见 TTL 默认值与含义

  • 60–300 秒:临时值,用于即将做迁移/切流的场景,方便快速生效。
  • 600 秒(10 分钟):很多 CDN/云解析的默认值,兼顾缓存与生效速度。
  • 3600 秒(1 小时):常规网站常用,缓存命中率不错。
  • 86400 秒(24 小时):稳定不变的记录(如 MX、NS)常用,最大化缓存收益。

TTL 的取值范围是 0 到 2³¹−1 秒,但实践中很少用超过一天的值做业务解析;另外 RFC 2308 还规定了"否定缓存"(查不到的域名也按较短 TTL 缓存,避免权威服务器被反复查询打爆)。

Why Delay

为什么改了解析要等几天才生效?

因为"旧 TTL"是按旧值算的,你改记录这个动作本身不通知任何缓存

很多人误以为"我在后台点了保存,全世界立刻生效"。事实是:DNS 是拉取式系统——权威服务器不会主动告诉任何人"记录变了"。各级缓存只在自己的 TTL 到期后,才会重新来问。于是:

  • 你今天把 A 记录从 IP-A 改成 IP-B,但这条记录之前的 TTL 是 86400(24 小时)。
  • 某台递归解析器 1 分钟前刚缓存了旧值(指向 IP-A),它要再过将近 24 小时才会放弃这个缓存。
  • 这 24 小时里,所有走这台解析器的用户,访问的仍是旧 IP-A。

更麻烦的是:TTL 是由当时的旧记录带下去的。你把 TTL 从 86400 改成 60,这个"新 TTL"只对"改完之后新查出来的记录"生效——在改之前就已被缓存的旧值,依然按它当初拿到的 86400 走完。这就是为什么老手都在迁移前提前 1–2 天先把 TTL 调小,等旧的大 TTL 缓存过期得差不多了,再去改记录值。

生效时间怎么估算?

一个实用估算:最坏生效时间 ≈ 你改动前那一条记录的 TTL。举例:改之前 TTL 是 3600 秒,那么从你改记录算起,绝大多数用户在 1 小时内陆续切到新值;如果改之前 TTL 是 86400,就要预留 24 小时。想更准,就多等一个 TTL 再对外宣布"已切换完成"。

Flush Cache

如何主动刷新本机缓存

只影响你自己这台机器,但调试时立竿见影

# Windows:清空系统 DNS 缓存 ipconfig /flushdns # macOS:清空系统解析缓存 sudo dscacheutil -flushcache # Linux(systemd-resolved) sudo resolvectl flush-caches # 再用 dig 强制指定服务器查一次,看权威返回的真实值 dig @ns1.example.com example.com

操作顺序建议:①改完权威记录 → ②在自己机器上 flush 系统缓存 → ③浏览器用无痕窗口访问(绕过浏览器层缓存)→ ④若仍不对,用 dig @权威服务器域名 你的域名 直接向权威服务器查,绕开所有中间缓存,确认权威侧本身已改对。注意:这一整套只解决"你自己看到旧值",其他用户与公共递归解析器的缓存仍按旧 TTL 走,急不得。

Trade-off

TTL 调大 vs 调小:权衡表

没有完美 TTL,只有当前阶段合适的 TTL

维度TTL 小(60–300 秒)TTL 大(3600–86400 秒)
改记录后生效速度快,几分钟内全球陆续生效慢,要等几小时到一天
缓存命中率低,缓存很快过期,重复查询多高,一次缓存用很久
权威服务器压力大,更多请求落到权威侧小,被缓存挡掉大部分查询
解析延迟缓存未命中更多,体感略慢命中多,体感更快
适合场景即将迁移、切流、临时变更稳定运行期、不常变的记录(MX/NS)

标准工作流:平时 TTL 调大(享受缓存红利)→ 变更前 1–2 天先把 TTL 调小 → 等旧大 TTL 缓存过期得差不多 → 再改记录值 → 切换完成稳定后,再把 TTL 调回大值。这样既不牺牲平时的性能,又把切换窗口期压到最短。具体操作可参考 Cloudflare 关于 DNS 记录 TTL 的官方说明。

FAQ

常见问题

TTL 到底是什么?+
TTL(Time To Live,生存时间)是 DNS 响应报文中的一个 32 位字段,单位秒,由权威域名服务器设定,告诉所有下游缓存(操作系统、递归解析器等)这条记录最多可以缓存多久。到期后缓存失效,必须重新查询权威服务器。RFC 1035 定义了该字段。
为什么我改了 DNS 记录,访问还是旧的?+
因为各级缓存还存着旧结果:你的浏览器、操作系统、家里路由器、以及你用的递归解析器都按旧记录的 TTL 在缓存。TTL 没到期之前,它们不会去权威服务器拿新值。所以改完记录后要等最慢的那一级缓存自然过期,通常几分钟到 48 小时不等。
怎么立刻让本机用上新的解析结果?+
先把本地缓存清掉:Windows 执行 ipconfig /flushdns,Linux 用 systemd-resolved --flush-caches,macOS 用 sudo dscacheutil -flushcache。再强制浏览器刷新(Ctrl+F5)或开无痕窗口测试。注意:这只清你自己机器,递归解析器和其他用户的缓存仍然按旧 TTL 走。
TTL 设大好还是设小好?+
TTL 小(如 60 秒)切换生效快、适合即将迁移/变更的场景,但缓存命中率低、解析器负载大;TTL 大(如 86400 秒)缓存命中率高、减轻权威服务器压力,但改记录后要等很久才全球生效。常规做法是平时设大,变更前提前几天调小。
改 TTL 本身需要等生效吗?+
需要,而且这是最容易踩的坑:TTL 的变更同样要走缓存过期流程。你把 TTL 从 86400 改成 60 后,已经缓存了旧记录的解析器仍按 86400 秒走,新 TTL 只对之后新查询到的记录生效。这就是为什么变更要提前一两天先调 TTL。
References

参考来源