8.4 DNS 解析链路与缓存

一句话

一次域名解析不是 “一个查询”,而是一条链路:浏览器缓存 → 操作系统 stub → 递归解析器 → 根 → 顶级域 → 权威;每一层都缓存、每层都有 TTL,所以 “改了域名为什么没生效” 的答案几乎总是 “某一层还没到期”。

链路:六跳,每跳都可能缓存

环节 谁 缓存什么 典型 TTL
浏览器 Chrome/Firefox 内部缓存 域名 → IP 60 秒(Chrome 固定约 60s)
操作系统 stub resolver / nscd / systemd-resolved 同上 受记录 TTL 限制
递归解析器 ISP、公司内网、8.8.8.8、223.5.5.5 全链路结果 按记录 TTL
根服务器 13 组 anycast 顶级域委派(NS) 天级
顶级域(TLD) .com / .cn 的服务器 你的权威 NS 列表 小时–天级
权威服务器 你的 DNS 服务商 记录本身(A/CNAME/TXT…) 由你设定
dig +trace example.com          # 从根开始走一遍委派链,看每一跳给了什么
dig example.com A +noall +answer  # 看 TTL 还剩多少(第二列)
dig @8.8.8.8 example.com        # 换一个递归解析器对比,判断是不是本地缓存

记录类型:只用四种就够看懂 90% 的场景

类型 指向 用途 坑
A / AAAA IPv4 / IPv6 最终地址 只配 A 不配 AAAA,纯 IPv6 客户端直接失败
CNAME 另一个域名 别名(CDN、托管服务) 不能与其它记录共存;CNAME 套 CNAME 会增加解析跳数与延迟
NS 权威服务器 委派 改 NS 要等父区 TTL + 子区生效
TXT 任意文本 域名验证、SPF/DKIM、CAA 校验 内容过长会被拆成多段
MX / SRV 邮件 / 服务 邮件路由、服务发现 SRV 的优先级与权重语义容易搞反

“改完多久生效” 的算法

生效时间 ≈ max(各级缓存剩余 TTL) + 递归解析器的负缓存/预取行为
你改了什么 要等多久 怎么缩短
A 记录换 IP 原记录 TTL(可能几小时) 变更前 24–48 小时把 TTL 降到 60–300 秒
换权威 NS 父区委派的 TTL(天级) 只能提前规划,无法加速
新增记录 通常几十秒–1 个 TTL 无缓存时几乎立即生效
删除记录(变成 NXDOMAIN) 受 SOA 的 negative TTL 影响 少用 “删除”,改用 “指向维护页”

负缓存常被忽略:查询一个不存在的名字,解析器会把 “不存在” 也缓存起来(时长取 SOA 的 minimum 字段)。所以 “刚加了解析怎么还说不存在”——前面那次失败被缓存了。

递归解析器与调度:CDN 为什么依赖 DNS

  • 递归 vs 权威:递归替客户端跑完全链路并缓存;权威只回答自己区内的记录。
  • ECS(EDNS Client Subnet):递归把客户端网段带给权威,权威才能按地理位置返回最近的节点。递归不支持 ECS 时,CDN 会把节点调度到解析器所在地(常常是省会的机房),而不是用户所在地——这是 “调度不准” 的头号原因。
  • GeoDNS:权威按来源返回不同 A 记录,本质是把 “就近” 放在 DNS 层;它的精度受递归位置与本地 DNS 影响,所以大型 CDN 还要在 HTTP 层做二次调度(302 或 anycast),见 9.1 边缘缓存原理。

常见故障对照表

现象 最可能原因 验证
SERVFAIL DNSSEC 校验失败、权威不可达 dig +dnssec、换公共 DNS 对比
NXDOMAIN 记录不存在 / 拼错 / 未生效 dig +trace 查委派链
部分地区解析失败 权威多线不全(只配了电信) 各地拨测(第三方 DNS 监测)
解析到旧 IP 某层 TTL 未到期 逐层 dig @<resolver> 看 TTL
解析很慢(>200ms) 走公网递归、CNAME 链过长、ECS 缺失 dig +stats 看 query time
内网域名解析不到 搜索域/ndots 与集群 DNS 配置(见 7.8 网络模型 (CNI / NetworkPolicy));私有域名还依赖 VPC 的解析器与子网边界(见 8.7 VPC、子网、安全组) 看 /etc/resolv.conf、VPC 的私有 DNS 配置

反模式

反模式 后果
TTL 设 86400 还指望分钟级切流 切换窗口以小时计,故障时想回滚也回不去
用 DNS 做负载均衡(多条 A 轮询) 无健康检查,挂掉的 IP 继续接流量
CNAME 套三层以上 解析跳数增加、首包延迟上升、排障困难
只配一个权威服务商 权威挂 = 全站域名不可解析(比机房挂更致命)
忽略 AAAA 记录 纯 IPv6 网络下直接不可达
变更 DNS 不留回滚窗口 切错后要等 TTL 才能切回

三条铁律

🔑 TTL 是切换速度的上限;要大改,先把 TTL 降下来,等一个旧 TTL 周期再改。

🔑 DNS 只解决 “找到哪个入口”,不做健康检查与负载均衡(那是 LB/网关的事)。

🔑 权威要有两家或双活;单权威的可用性通常低于你的机房。

自检

Q1 把 A 记录从旧 IP 切到新 IP,TTL 是 3600,切完 5 分钟就有人报 “还访问旧站”,为什么?

▸ 答案:因为部分递归解析器与客户端仍持有旧记录(最长 1 小时)。DNS 变更天然是 “渐进生效”,无法保证所有客户端同时切换。正确做法是:变更前先把 TTL 降到 60–300 秒并等一个旧周期,让缓存 “变短”;切换后旧 IP 至少保留一个原 TTL 时长继续可用(双写过渡),而不是立刻下线。

Q2 为什么说 “用 DNS 做负载均衡” 不可靠?

▸ 答案:因为 DNS 没有健康检查与连接感知:返回的 IP 挂了,客户端仍会拿到它;记录被缓存后,权重调整也不生效。此外不同递归的缓存时间不同,流量分布不可控。真正的负载均衡要放在四层/七层(8.9 四层与七层负载均衡),DNS 只负责 “把用户带到入口”。

Q3 CDN 调度不准、用户被分配到远端节点,先从哪查?

▸ 答案:先看递归是否支持 ECS。不支持时权威只能看到解析器的 IP,于是按 “解析器所在地” 调度,可能离用户几百公里。验证:dig +short TXT o-o.myaddr.l.google.com @<公共DNS> 看递归出口,或在权威侧看收到的 ECS 字段。缓解:启用支持 ECS 的权威/CDN,或在 HTTP 层做二次调度(302/anycast)。

Q4 dig 显示解析正常,但应用就是连不上,可能是什么问题?

▸ 答案:解析正常 ≠ 可达。区分三类:① 解析到的是内网 IP,客户端不在同一网络;② 证书/SAN 与域名不匹配(见 8.6 TLS 握手、证书与 mTLS);③ 应用使用了缓存的连接池/长连接,仍连着旧 IP(DNS 变更对长连接无效)。用 curl -v 看它实际连的 IP,比 dig 更能反映问题。

Q5 为什么要给关键域名配两个权威服务商?

▸ 答案:因为权威故障会让所有下游一起失败:递归拿不到记录,缓存过期后全站不可解析,而且恢复要等 TTL 与递归重试。双权威(不同厂商、不同 anycast 网络)能把 “单厂商故障” 降级为 “部分递归抖动”。这比多机房更便宜,也常常更有效。

关联