DNS 是一个「分层授权」的分布式数据库:没有一台机器知道全部,但合起来什么都知道。 每个「区」自己管自己,上级只负责「指路」。
5.2.4 讲了查询过程,这一节讲「数据是怎么分布的」。 4.4.2 的「路由聚合」是另一种「分层」,可以对照着看。
一、区(zone)是什么
「区」是 DNS 的管理单位:一个区就是「一台(或一组)服务器负责的那一段名字空间」。
| 概念 | 含义 | 例子 |
|---|---|---|
| 域(domain) | 名字的层级 | example.com |
| 区(zone) | 一段被授权管理的数据 | example.com 的文件 |
| 委派(delegation) | 把子域交给别人管 | blog.example.com |
第二行和第一行的区别常被混淆:域是「名字」,区是「数据」。 一个域可以切成多个区(比如把 blog 子域委派出去),这时「域还在,但数据不归你管了」。 第三行「委派」是这套系统能扩张的关键: example.com 可以只写一行「blog 归 ns1.blog.example.com 管」, 剩下的记录全交给那台服务器——这就把「一个巨大的文件」拆成了「很多小文件」。
二、主从与冗余
每个区至少要两台服务器,一台主、一台从:
| 角色 | 干什么 | 为什么需要 |
|---|---|---|
| 主(master) | 接受修改 | 唯一的数据源 |
| 从(slave) | 定时同步 | 主挂了还能答 |
第二行「定时同步」靠的是「区传送」(zone transfer): 从服务器定期问主服务器「版本号变了吗」,变了就整段拉过来。 所以「加一台从服务器」几乎不增加管理成本。 这也解释了为什么「DNS 挂了全网瘫」很少见:因为关键域名都有多台服务器、还分布在不同网络里。
三、它像个数据库,但不一样
说它「像数据库」,是因为它有「记录」「查询」「更新」; 说它「不一样」,是因为三条:
| 项 | 普通数据库 | DNS |
|---|---|---|
| 一致性 | 强一致 | 最终一致(靠 TTL) |
| 查询方式 | 任意条件 | 只能按名字查 |
| 写入 | 随时可写 | 要改主服务器再同步 |
第一行是最大的区别:DNS 允许「不同地方看到不同答案」,只要最终一致就行。 所以「我这里能解析、你那里不能」是正常现象,不是 bug。 第二行「只能按名字查」意味着它不支持「查所有以 abc 开头的域名」—— 这种需求要靠「证书透明日志」之类的旁路数据,DNS 本身给不了。
四、动手 Demo:一个域名可以对应一堆地址
查三个域名,看各自返回几个 IPv4 地址。 第二列就是「冗余度」,也是最原始的负载均衡。
import socket
for name in ('www.baidu.com', 'www.qq.com', 'github.com'):
ips = {x[4][0] for x in socket.getaddrinfo(name, 443,
socket.AF_INET)}
print(name, len(ips), sorted(ips)[:1])
实跑输出:
--------------------------------------------------------------------
一个域名可以对应一堆地址
--------------------------------------------------------------------
**DNS 不是「一对一」的电话簿**:**一个域名可以返回多个 IP,客户端挑一个用。**
**这就是最原始的负载均衡。**
域名 IPv4 个数 其中一个
-----------------------------------------------
www.baidu.com 1 183.2.172.177
www.qq.com 2 14.152.80.169
github.com 1 20.205.243.166
**第二列就是「冗余度」**:**返回多个地址,一台挂了还能连别的。**
**所以「DNS 轮询」是最古老也最便宜的负载均衡。**
**但它有三个局限**:
**一是客户端会缓存**(不一定每次都重新挑);**二是它不知道服务器忙不忙**(只会轮着发);
**三是「挂了」这件事有延迟**(要等 TTL 过期才不再返回)。
**所以今天的负载均衡更多是靠「前面放一台专门的设备或服务」**,DNS 只做第一层粗分流。
**顺带说清「DNS 是分布式数据库」这句话**:**全球没有一台机器存着所有域名**,
**而是「每层只管自己那一段」**——
**根服务器知道「.com 归谁管」,.com 的服务器知道「baidu.com 归谁管」。**
**这种「分层授权」让它能撑住全球的查询量。**
「返回多个地址」是 DNS 做负载均衡的方式:客户端随便挑一个,流量自然分散。 这种方式的好处是「不用改客户端」,坏处是「控制很粗」。 粗在哪:它不知道服务器忙不忙、也不知道网络近不近,只能「轮着发」或者「按来源大致分」。 精细的调度要靠「前面放一台负载均衡器」或者「用任播」。 「DNS 是分布式数据库」这句话的落点是「分区」: 每个区只管自己的记录,查询时靠「委派」一层层找过去。 所以它没有「全局索引」,也永远不会有「全局事务」——这正是它能撑住全球查询量的原因。
30 秒实验
- 想一下:为什么每个区至少要两台 DNS 服务器?
- 想一下:「委派」和「复制」有什么区别?
- 想一下:DNS 为什么不做强一致?
常见误区
- 以为「DNS 有一台总服务器」。 没有,分层授权、各管一段。
- 以为「域和区是一回事」。 域是名字,区是数据,一个域可以切成多个区。
- 以为「DNS 应该强一致」。 最终一致就够,强一致会让全球查询慢得没法用。
自测三问(点开对答案)
1. 什么是「区」? —— **一段被授权管理的名字空间数据**,通常对应一个文件。 2. 「委派」解决什么问题? —— **把子域交给别人管**,从而把一个大文件拆成很多小文件,方便扩张。 3. DNS 为什么不做强一致? —— **全球查询量太大**,强一致要频繁同步,延迟和成本都受不了。DNS 讲完了。下一节讲「IP 变 MAC」:ARP。
- ☐ (本节完,下一节 5.3.1 ARP概要)