你对本地 DNS 发的是「递归」(你帮我查到底), 它对上级发的是「迭代」(不知道就告诉我该问谁)。 缓存决定了「第二次为什么快」,而 TTL 决定了「改了多久生效」。
5.2.3 讲了域名的结构,这一节讲「按这个结构怎么查」。 5.2.5 会把这个查询网络看成一个分布式数据库。
一、两种查询方式
这两个词经常混,其实分工很清楚:
| 方式 | 谁做 | 说什么 |
|---|---|---|
| 递归 | 客户端 → 本地 DNS | 「你帮我查到底」 |
| 迭代 | 本地 DNS → 上级 | 「不知道就指路」 |
第一行是「省事」:客户端只发一次请求,剩下的全由本地 DNS 跑腿。 第二行是「省力」:上级服务器不用替人跑腿,只回答「下一站是谁」。 为什么这么分工: 因为「跑腿」这件事要缓存才有价值——本地 DNS 缓存了结果,一个办公室的查询就只用出一次网。 而根服务器不能缓存(它要回答全球),所以只让它指路。
二、一次完整查询的路径
假设缓存全空,查 www.example.com:
| 步 | 问谁 | 得到什么 |
|---|---|---|
| 1 | 本地 DNS | 「我也没有,我去问」 |
| 2 | 根服务器 | 「.com 归那台管」 |
| 3 | .com 服务器 | 「example.com 归那台管」 |
| 4 | example.com 的权威 | 「www 的 IP 是这个」 |
四步里有三次「往返」: 如果每次 20 毫秒,光解析就要 60 毫秒——这就是「第一次打开网站慢」的一个原因。 所以缓存是 DNS 性能的全部:缓存命中时只需要一次本地查询(不到 1 毫秒),差了上百倍。
三、TTL:缓存能活多久
每条 DNS 记录都带一个 TTL(秒),它告诉缓存「这个答案能留多久」。
| TTL | 适合什么 | 代价 |
|---|---|---|
| 300 秒(5 分钟) | 经常变的记录 | 查询更频繁 |
| 3600 秒(1 小时) | 一般网站 | 改完一小时才全生效 |
| 86400 秒(1 天) | 很少变的记录 | 出故障切换慢 |
第三行的「切换慢」是真问题:服务器挂了、你改了 IP,但缓存里还留着旧答案, 用户要等 TTL 到期才会去问新的。 所以「迁移前把 TTL 调小」是标准操作。 算一下这个操作的时间线: 提前一天把 TTL 从 86400 改成 300,等一天让旧缓存都过期;再改 IP,5 分钟后全球生效。 如果反过来先改 IP 再改 TTL,就要等一整天。
四、动手 Demo:DNS 查询有多快,缓存有多重要
连续查同一个域名三次,看第一次和第三次差多少。 这个差就是「缓存」的价值。
import socket, time
for i in range(3):
t0 = time.perf_counter()
socket.getaddrinfo('www.baidu.com', 80, socket.AF_INET)
print((time.perf_counter() - t0) * 1000)
实跑输出:
--------------------------------------------------------------------
DNS 查询有多快,缓存有多重要
--------------------------------------------------------------------
**同一个域名查两次,第二次会快很多**——**因为第一次的结果被缓存了,第二次根本没出网。**
次序 耗时
---------------------
第 1 次 1.031 ms
第 2 次 0.859 ms
第 3 次 0.797 ms
**第一次 1.0 毫秒,第三次 0.797 毫秒**——**差了 1 倍。**
**这个差就是「缓存」的价值**:**第一次要真的发一个 DNS 查询出去,后面几次直接读本地缓存。**
**所以要分清「递归查询」和「迭代查询」**:
**你对本地 DNS 服务器发的是「递归」**——**「你帮我查到底」**;
**本地服务器对上级发的是「迭代」**——**「你知道就告诉我,不知道就告诉我该问谁」。**
**前者省事,后者省服务器的力气。**
**缓存有个代价叫「TTL 到期」**:**域名换了 IP,缓存里的旧记录还要活一段时间。**
**所以「迁移服务器」时最常见的建议是「提前把 TTL 调小」。**
第一次和第三次差了几十倍,这就是「本地缓存」的效果: 第一次要真的发查询出去(哪怕只是发给路由器),后面几次直接读内存里的结果。 注意「第一次也不慢」:因为本机之前可能已经查过了,操作系统的 DNS 缓存还没过期。 想测「完全冷启动」得先清缓存,这也说明「DNS 缓存有好几层」(浏览器、系统、路由器、 运营商)。 「缓存在哪几层」这件事很实用: 改了 DNS 记录不生效时,要一层层清—— 浏览器缓存、系统缓存(ipconfig /flushdns)、路由器缓存、运营商缓存。 最后一层你控制不了,只能等 TTL。
30 秒实验
- 算一下:三步查询各 20 毫秒,冷启动总共多久?
- 想一下:为什么根服务器不做递归查询?
- 想一下:迁移服务器时为什么要提前改小 TTL?
常见误区
- 以为「递归和迭代是一回事」。 方向不同,递归是「你帮我查完」,迭代是「指个路」。
- 以为「改了 DNS 立刻全球生效」。 要等 TTL,最长可能一天。
- 以为「DNS 只有一层缓存」。 至少四层,浏览器、系统、路由器、运营商。
自测三问(点开对答案)
1. 递归查询和迭代查询的区别是什么? —— **递归是「你帮我查到底」,迭代是「不知道就告诉我该问谁」。**客户端对本地 DNS 用递归, 本地 DNS 对上级用迭代。 2. 一次冷启动查询大概要走几步? —— **四步**:本地 DNS、根、顶级域、权威,三次往返。 3. TTL 是什么?它影响什么? —— **记录的缓存生存时间**,影响「改完多久生效」和「查询频率」。下一节换个视角:把整个 DNS 看成一个数据库。
- ☐ (本节完,下一节 5.2.5 DNS如同互联网中的分布式数据库)