DNS缓存是什么?
DNS缓存是指解析器、操作系统、浏览器和应用程序对DNS查询结果的临时存储。执行DNS查找时,结果将按照记录的TTL(生存时间)值进行缓存,允许同一域名的后续请求在无需查询权威服务器的情况下立即得到答复。
DNS缓存为什么重要
如果没有缓存,每个Web请求都需要完整的DNS查询——增加延迟并产生大量DNS流量。DNS缓存提供:
- 更快的响应时间:缓存答复返回时间为微秒级,而完整查询为毫秒级
- 减少网络流量:向权威服务器发送更少的查询
- 改进的复原力:即使DNS服务器暂时无法访问,本地缓存也能提供答复
- 降低服务器负载:权威服务器处理更少的查询
DNS缓存的工作原理
缓存层次结构
DNS缓存发生在多个层级:
浏览器缓存(几秒到几分钟)
↓
操作系统缓存(几秒到几分钟)
↓
本地解析器缓存(几分钟到几小时)
↓
互联网服务商解析器缓存(几分钟到几小时)
↓
权威名称服务器(信息源)
缓存查询过程
1. 用户请求 example.com
2. 浏览器检查 其缓存
3. 如果未命中,操作系统检查 其缓存
4. 如果未命中,解析器检查 其缓存
5. 如果未命中,向权威服务器发送递归查询
6. 根据TTL在每个级别缓存结果
7. 将响应返回给用户
TTL过期机制
每条DNS记录都包含TTL值:
example.com. 300 IN A 203.0.113.50
^^^
TTL值,单位为秒(5分钟)
缓存在300秒后存储此记录并将其丢弃。下一个查询触发新的查询。
DNS缓存层级
浏览器缓存
现代浏览器独立缓存DNS结果:
Chrome:使用自己的DNS缓存(chrome://net-internals/#dns) Firefox:维护内部缓存(about:networking#dns) Safari:使用系统解析器典型浏览器缓存TTL:60秒(不管DNS TTL)
操作系统缓存
Windows:DNS客户端服务缓存结果# 查看缓存
ipconfig /displaydns
# 清空缓存
ipconfig /flushdns
macOS:mDNSResponder处理缓存
# 清空缓存(macOS 10.15+)
sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder
Linux:因系统而异,通常使用systemd-resolved
# 清空systemd-resolved缓存
sudo systemd-resolve --flush-caches
# 检查统计信息
sudo systemd-resolve --statistics
解析器缓存
递归DNS解析器(ISP DNS、8.8.8.8、1.1.1.1)维护为数百万用户服务的大型缓存:
| 解析器 | 缓存策略 |
|---|---|
| Google (8.8.8.8) | 遵守TTL,全球缓存 |
| Cloudflare (1.1.1.1) | 遵守TTL,分布式缓存 |
| ISP解析器 | 可能忽略低TTL值 |
缓存行为示例
正常操作
查询1:example.com
→ 完整查询:50ms
→ 缓存300秒(TTL)
查询2:example.com(1分钟后)
→ 缓存命中:1ms
查询3:example.com(10分钟后)
→ 缓存过期,完整查询:50ms
→ 重新缓存300秒
DNS记录更新
原始:example.com → 203.0.113.50 (TTL: 300s)
时间:10:00 - DNS更新为203.0.113.51
客户端在10:02查询
→ 仍缓存:203.0.113.50(在10:05到期)
客户端在10:06查询
→ 缓存已过期,新查询:203.0.113.51
→ 缓存直到10:11
TTL策略和缓存
选择TTL值
| 使用场景 | 推荐TTL | 原因 |
|---|---|---|
| 静态基础设施 | 3600-86400秒(1-24小时) | 很少更改,减少DNS负载 |
| 生产网站 | 300-1800秒(5-30分钟) | 平衡性能和灵活性 |
| 活跃迁移 | 60-300秒(1-5分钟) | 加快更改传播 |
| 负载均衡 | 60-120秒 | 在服务器更改时快速故障转移 |
迁移前降低TTL
计划DNS更改时的最佳做法:
Day -7: example.com TTL 3600秒(1小时)
Day -2: 减少到300秒(5分钟)
Day 0: 进行DNS更改
→ 最多缓存5分钟
Day +1: 如需要,恢复TTL为3600秒
DNS缓存中毒和安全
DNS缓存中毒攻击
攻击者试图将虚假DNS记录注入缓存:
1. 攻击者用虚假响应淹没解析器
2. 如果响应与待处理查询匹配,则缓存该响应
3. 用户收到合法域名的恶意IP
4. 被污染的缓存提供给许多用户
安全缓解措施
DNSSEC:密码签名的记录防止中毒example.com. IN A 203.0.113.50
IN RRSIG A 8 2 300 ...
源端口随机化:使响应更难伪造
0x20编码:查询中的随机大小写辅助验证
解析器安全:使用信誉良好的解析器(Cloudflare、Google、Quad9)
检查DNS缓存
查看缓存内容
Windows:ipconfig /displaydns | more
macOS(有限信息):
sudo killall -INFO mDNSResponder
# 检查Console.app以查看日志
Linux(systemd-resolved):
sudo systemd-resolve --statistics
测试缓存行为
# 第一个查询(缓存未命中)
time dig example.com
# 立即重复(缓存命中)
time dig example.com
# 比较时间
缓存相关问题
DNS更改后缓存陈旧
问题:更新的DNS记录未向用户反映 解决方案:1. 等待TTL过期
2. 在未来更改前降低TTL
3. 要求用户清空本地缓存
过度激进的缓存
某些ISP忽略TTL并缓存更长时间:
问题:更改需要数小时/天才能传播 解决方案:- 使用较低的TTL值(ISP通常至少尊重300秒)
- 考虑对关键服务使用任播DNS
- 记录有问题的已知ISP
负面缓存
失败的查询(NXDOMAIN)也会被缓存:
查询:newsubdomain.example.com
响应:NXDOMAIN(不存在)
缓存:3600秒(SOA最小TTL)
结果:新子域在1小时内无法解析
解决方案:在添加新记录前降低SOA最小TTL
清空DNS缓存
何时清空
- 立即测试DNS更改
- 排除解决故障
- DNS提供商迁移后
- 怀疑缓存中毒
如何清空
Windows:ipconfig /flushdns
macOS:
sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder
Linux(systemd-resolved):
sudo systemd-resolve --flush-caches
Chrome:
导航至:chrome://net-internals/#dns
点击:"Clear host cache"
Firefox:
在about:config中切换network.dnsCacheExpiration
或重启浏览器
最佳实践
1. 设置适当的TTL:平衡性能和变更速度
2. 更改前降低TTL:在DNS更新前24-48小时降低TTL
3. 监控传播:使用工具检查全局DNS解析
4. 记录缓存行为:了解您的基础设施的缓存层
5. 使用DNSSEC:防止缓存中毒
6. 彻底测试:在声称成功前验证DNS更改有效
7. 用户教育:在需要时提供缓存清空的说明
高级缓存概念
预取
浏览器和解析器可能会预取页面上链接的DNS:
<!-- 向浏览器提示 -->
<link rel="dns-prefetch" href="//cdn.example.com">
缓存预热
负载均衡器和CDN可能会为关键记录预填充缓存。
任播和缓存
任播DNS将查询路由到最近的服务器,为最佳性能创建地理分布式缓存。
DNS缓存是Internet性能的基础——正确理解和配置TTL可确保DNS更改高效传播,同时保持快速解析时间。