📚 第五章 IP协议相关技术
📄 一句话概括

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 秒实验

  1. 想一下:为什么每个区至少要两台 DNS 服务器?
  2. 想一下:「委派」和「复制」有什么区别?
  3. 想一下:DNS 为什么不做强一致?

常见误区

  1. 以为「DNS 有一台总服务器」。 没有,分层授权、各管一段。
  2. 以为「域和区是一回事」。 域是名字,区是数据,一个域可以切成多个区。
  3. 以为「DNS 应该强一致」。 最终一致就够,强一致会让全球查询慢得没法用。
自测三问(点开对答案) 1. 什么是「区」? —— **一段被授权管理的名字空间数据**,通常对应一个文件。 2. 「委派」解决什么问题? —— **把子域交给别人管**,从而把一个大文件拆成很多小文件,方便扩张。 3. DNS 为什么不做强一致? —— **全球查询量太大**,强一致要频繁同步,延迟和成本都受不了。

DNS 讲完了。下一节讲「IP 变 MAC」:ARP。

相关笔记