互联网上的每一次连接都始于一个问题:"这个名字对应的 IP 地址是多少?"域名系统(DNS)回答它。DNS 是互联网那本分布式、层级化、被大量缓存的"电话簿",把 sdeoffer.com 变成机器能连接的 IP。它看着像管道,其实也是个强大的基础设施工具——CDN 靠它把你路由到最近的边缘,流量靠它在多地区间均衡和故障转移,而它也常是一个被忽视的单点故障。
- DNS 把名字映射到 IP,经过一个层级:根(root)→ TLD(
.com)→ 该域的权威服务器(authoritative)。 - 递归解析器(recursive resolver)替你跑腿——你的客户端问它,它走遍层级并缓存结果。
- 缓存 + TTL 是关键——答案在每一层按 TTL 缓存;"DNS 生效(propagation)"其实就是在等旧 TTL 过期。
- 记录类型编码不同答案——A/AAAA(IPv4/IPv6)、CNAME(别名)、MX(邮件)、TXT、NS。
- DNS 是基础设施工具——GeoDNS 返回基于位置的 IP,加权/轮询记录做负载均衡和故障转移。
- anycast 让一个 IP 从多地提供服务,是高韧性根服务器和 CDN 的基础。
- 它是单点故障和攻击面——DNS 宕机看起来像"一切都挂了";DNSSEC 和 DoH/DoT 加上完整性与隐私。
DNS 通过走一个层级(根 → TLD → 权威)把主机名解析成 IP,由递归解析器干活并按 TTL 缓存结果。记录(A、CNAME、MX…)持有答案。除解析外,DNS 是个路由工具:GeoDNS 和加权/轮询记录用于引导和均衡流量,anycast 让一个 IP 从多地提供服务。因为几乎一切都依赖它,DNS 是出了名的单点故障——用多家解析商、谨慎设 TTL、上 DNSSEC/加密 DNS。
问题:名字到地址
人记得住 github.com;机器把数据包路由到 140.82.x.x。DNS 是两者之间的间接层——而这种间接超越了便利:因为名字→IP 的映射是(在缓存约束下)实时解析的,你可以在不改名字的前提下改变名字指向哪里,这正是迁移、故障转移和地理路由的基础。
解析流程
当浏览器需要 sdeoffer.com 时,它问一个递归解析器(你的 ISP 运营的,或 1.1.1.1 / 8.8.8.8)。如果答案没缓存,解析器替你走遍层级:
客户端 ─▶ 递归解析器
├─▶ 根服务器 : "去问 .com 的 TLD 服务器 → 在这"
├─▶ .com TLD 服务器: "去问 sdeoffer.com 的权威服务器 → 在这"
├─▶ 权威服务器 : "sdeoffer.com A = 203.0.113.10" ✓
└─ 缓存答案(按其 TTL),返回给客户端
客户端连接到 203.0.113.10
TTL 内的下一次查询 → 直接从解析器缓存返回
解析器的查询是迭代的(每个服务器把它再往下指一步),而客户端发给解析器的那一次查询是递归的(解析器返回最终答案)。第一次查询触及好几个服务器;TTL 内的后续每次都是缓存命中。
层级结构
DNS 是一棵树,这正是它能扩展到数十亿个名字而无需任何单一权威的原因:
- 根服务器(root)(顶端的
.)——知道 TLD 服务器在哪。有 13 个根服务器身份,每个都通过 anycast 大规模复制。 - TLD 服务器——管理顶级域(
.com、.org、.io、国家代码);它们知道每个下属域的权威服务器是谁。 - 权威服务器(authoritative)——持有某个具体域的实际记录(常由你的 DNS 服务商运营——Route 53、Cloudflare 等)。
记录类型
| 记录 | 映射 | 示例用途 |
|---|---|---|
| A / AAAA | 名字 → IPv4 / IPv6 | 核心的主机名→地址映射 |
| CNAME | 名字 → 另一个名字(别名) | www → 主域;指向 CDN 主机名 |
| MX | 域 → 邮件服务器 | 邮件路由 |
| NS | 域 → 它的权威服务器 | 委派 |
| TXT | 任意文本 | 域名验证、SPF/DKIM |
一个常见坑:CNAME 不能和同名的其他记录共存,也不允许放在区域顶点(example.com 本身)——这就是服务商提供 "ALIAS/ANAME" 扁平化来把顶点指向 CDN 的原因。
缓存与 TTL
DNS 能扩展是因为答案在每一层都被大量缓存——操作系统、递归解析器、有时浏览器。每条记录带一个 TTL(存活时间),告诉缓存保留多久。这是最重要的运维杠杆:
当你改了一条 DNS 记录、它"要几小时才生效(propagate)"时,其实没有什么在主动传播——世界各地的缓存只是还在返回旧答案,直到它的 TTL 过期。计划变更时的对策:提前调低 TTL(如调到 60s),让缓存快速刷新,改完再调回去。高 TTL 查询快但改动慢;低 TTL 反之。
DNS 作为基础设施工具
因为解析器问的是"这个名字对应什么 IP?",权威服务器可以根据是谁在问或当前状况给出不同答案——把 DNS 变成一个路由和负载均衡层:
- 轮询 / 加权 DNS——返回多条 A 记录(或轮换/加权)把客户端分散到多台服务器,一个粗糙但真实的负载均衡器(见负载均衡)。
- GeoDNS——根据解析方位置返回不同 IP,把用户送到最近的数据中心/边缘——CDN 路由流量的一种方式。
- DNS 故障转移——健康检查端点,停止返回挂掉地区的 IP,把流量引开(受 TTL 约束——这也是故障转移要用低 TTL 的原因)。
Anycast
anycast 是让单个 IP 地址同时从多个物理位置宣告的技术;互联网路由把每个客户端送到拓扑上最近的那个。13 个根服务器实际就靠它跑在全球数百台机器上,CDN 和大型 DNS 服务商也靠它兼得低延迟和韧性——一个位置挂了,路由直接把客户端送到次近的。(对比 GeoDNS 返回不同答案;anycast 用同一个 IP,让网络去挑位置。)
可靠性与安全
因为几乎一切都始于一次 DNS 查询,DNS 是个高影响的单点故障:2016 年的 Dyn 攻击搞垮主流站点,不是攻击它们本身,而是 DDoS 它们的 DNS 服务商。对策:用多家/冗余 DNS 服务商、anycast、合理的 TTL。安全上:明文 DNS 既不认证也不加密,所以 DNSSEC 给答案加密码学签名以防伪造/欺骗(缓存投毒),DoH/DoT(DNS over HTTPS/TLS)加密查询保护隐私,使中间方看不到也篡改不了你的查询。
在系统设计中
DNS 在多数设计里是第一跳:它把用户路由到 CDN 边缘或区域负载均衡器、支持蓝绿/跨区域故障转移(改个名字的指向)、并支撑服务发现(内部服务按名字互相解析,常通过平台的 DNS)。反复出现的面试要点是记住 TTL:任何你想快速改的东西(故障转移、切换),都需要提前设好低 TTL。
常见坑
- TTL 对变更太高——如果全世界缓存旧 IP 一整天,你就没法快速故障转移或迁移;提前调低 TTL。
- 把 DNS 当无防护的单点——单一服务商、无冗余;一次 DNS 宕机看起来像全站宕机。
- 顶点用 CNAME——不允许;用 ALIAS/ANAME 扁平化。
- 陈旧的否定缓存——失败(NXDOMAIN)也会被缓存;一个错配可能滞留。
- 延迟预算里忽略 DNS——一次冷查询会加往返;Web 上用
dns-prefetch/preconnect 帮忙。
DNS 是从名字到 IP 的层级化、带缓存的查找——根 → TLD → 权威,前面挡着一个递归解析器——而 TTL 主宰着"查询快"与"改动快"之间的取舍。除解析外它还是一个路由层(GeoDNS、加权记录、anycast),用于负载均衡、地理路由和故障转移。把它当关键基础设施对待:冗余服务商、有意的 TTL、DNSSEC/加密 DNS。
讲一次 DNS 查询。客户端 → 递归解析器 →(未命中)根 → TLD(.com)→ 权威服务器 → A 记录;解析器按 TTL 缓存并返回 IP。
递归 vs 权威?递归解析器跑腿并缓存;权威服务器持有某域的真实记录。根/TLD 服务器向下委派。
什么是 "DNS 生效(propagation)"?不是主动传播——是缓存在返回旧记录直到 TTL 过期。计划变更前先调低 TTL。
GeoDNS vs anycast?GeoDNS 按位置返回不同 IP;anycast 用一个 IP 从多地宣告、让路由挑最近的。
DNS 为何是可靠性隐患?一切都始于查询,所以 DNS 宕机看起来像全挂(参见 Dyn 攻击);用冗余服务商、anycast、DNSSEC。