先记住这个答案
一次域名解析通常经过三级缓存:浏览器先查自己的内存 DNS 缓存;未命中则调用系统 API(如 getaddrinfo),由操作系统的解析缓存(含 hosts 文件)应答;仍未命中才向配置的本地递归解析器(运营商或公共 DNS)发查询,递归解析器自己也有按 TTL 管理的缓存,命中就直接返回。各层通常按 TTL 管理缓存,到期后重新向上游获取,但浏览器和部分操作系统会实施自身的缓存策略,实际保留时间不一定严格等于 TTL,后续会具体说明。三层缓存的意义是就近拦截重复查询,降低延迟和上游负载。
- 缓存顺序:浏览器→操作系统→递归解析器
- 通常受 TTL 约束,但部分层可能例外
- 改 DNS 不生效先逐层清缓存再查权威
- 递归解析器缓存是跨用户共享的最大一层
三级缓存的存在意义与查询顺序
浏览器拿到一个域名后,最先查的是自己进程内的 DNS 缓存,例如 Chrome 会把最近解析过的域名和 IP 放在内存里,有自己的过期时间,往往短于记录本身的 TTL。命中就直接建连,零网络开销。未命中时浏览器不会自己发 DNS 报文,而是调用操作系统的 getaddrinfo 之类的接口。
操作系统这一层先查 hosts 静态映射,再查系统解析缓存(如 Windows 的 DNS Client 服务、macOS 的 mDNSResponder)。仍未命中时,系统把查询发给网卡配置的递归解析器。递归解析器是缓存容量最大、共享面最广的一层:它按每条记录的 TTL 缓存应答,同一个小区宽带下的用户互相受益,命中就秒回,未命中才走完整的递归加迭代流程去问权威服务器。
# 查看递归解析器返回的剩余 TTL(ANSWER SECTION 第二列)
dig example.com A
# 绕过系统缓存,直接指定递归解析器对比
dig @8.8.8.8 example.com A
# macOS 清系统 DNS 缓存
sudo dscacheutil -flushcache && sudo killall -HUP mDNSResponder
# Chrome 浏览器缓存:访问 chrome://net-internals/#dns 点 Clear host cache适用于 macOS/Linux 加 Chrome 环境。dig 输出里 TTL 数字每秒递减说明结果来自递归解析器缓存;浏览器缓存只能用浏览器自带页面清理。
切换业务 IP 后部分用户仍访问旧地址
假设某服务把 api.example.com 的 A 记录从旧 IP 改到新 IP,TTL 为 300 秒。五分钟后运维发现监控正常但仍有用户报错到旧 IP。排查发现:运维自己改过 hosts 验证过旧环境,本地 hosts 仍指向旧 IP;公司出口递归解析器缓存了旧记录且 TTL 还剩两分钟;个别用户浏览器从切换前就一直开着,进程内缓存也是旧结果。
处理方式是逐层定位:先用 dig @8.8.8.8 确认公共递归解析器已返回新 IP,说明权威侧已生效;再清本机 hosts 和系统缓存;让用户重启浏览器或等浏览器缓存过期。结果约十分钟后流量全部迁移。这个场景说明 DNS 切换的生效时间不是由权威服务器决定,而是由各级缓存里最慢失效的那一层决定。
缓存机制失效与不可控的边界
这套机制有几个容易失效的条件:一是浏览器和操作系统可能不严格遵守 TTL,存在最短或最长缓存策略,实际停留时间不可精确预测;二是运营商递归解析器可能违规延长缓存时间,导致 TTL 到期后仍返回旧记录;三是启用 DoH 的浏览器会绕过操作系统缓存,直接向 DoH 服务器查询,此时系统层清空缓存对它无效。
对应处理:切流前提前把 TTL 降到 60 秒以内并等待一个旧 TTL 周期再切换;排查时用 dig 指定不同递归解析器对比,区分是哪一层缓存了旧值;对 DoH 用户只能在浏览器内清缓存或换网络验证。代价是低 TTL 会增加权威服务器查询量,也会让递归解析器缓存命中率下降,日常不宜长期设置过低的 TTL。
容易答错的地方
- 以为只有递归解析器才有 DNS 缓存
- 浏览器和操作系统各有独立缓存,且浏览器缓存最先被查询。只清递归解析器或换公共 DNS,无法解决本机两层缓存里的旧记录,排障时必须三层都考虑到。
- 认为 TTL 到期后所有缓存同时失效
- 各层缓存的写入时间不同,递归解析器记录的是剩余 TTL 而非绝对时间点,不同解析器缓存到期时刻错开,所以 DNS 变更生效是一个渐进过程而非瞬间切换。
面试官还会怎么问?
为什么浏览器要有自己的缓存,直接用系统缓存不行吗?
调用系统接口有进程间通信和系统调用的开销,浏览器内存缓存能显著降低热点域名重复解析的时延,且能配合预解析提前解析页面里的链接域名,代价是与系统缓存可能出现结果不一致。
hosts 文件和 DNS 缓存是什么关系?
hosts 是操作系统层的静态映射,通常优先于普通 DNS 查询结果,也没有 TTL,修改后新查询立即生效;但启用 DoH 的浏览器可能绕过系统 hosts,此时 hosts 不生效。它常用来临时指向测试环境,但容易忘记删除,是 DNS 排障时的常见干扰源。
递归解析器缓存会不会返回过期数据?
正常情况下按剩余 TTL 倒计时,归零即丢弃重新查询。但少数运营商会强制延长缓存或做劫持改写,此时可用 dig @ 指定可信解析器对比,或改用 DoH 绕过本地链路验证。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。