为了方便,造出了DNS,看到这个需求就能想到当时写代码的艰苦路程。本文从分库视角简述DNS原理。
把握主体
从Javaer的视角,DNS其实就是一个接口:
interface Dns {
String getIpByDomain(String domain);
}
当然这个接口在java中已经实现了:
InetAddress.getByName("www.baidu.com");
言归正传,查询www.baidu.com,DNS协议交互流程是什么?
- java层调用API接口
InetAddress.getByName("www.baidu.com"); - 进入native,调用操作系统提供过的dns接口从ISP(网络服务提供商)网关处查询DNS,查不到进入下一步
- 从本机hosts文件解析dns,查不到进入下一步
- 从ISP(网络服务提供商)网关处查询DNS,查不到进入下一步
- ISP向最近的根服务器发送请求查找
www.baidu.comIP,根服务器返回顶级域名com服务器IP地址。 - ISP向步骤5返回的顶级域名服务器请求获取域名
www.baidu.comIP,顶级域名服务器返回权威域名baidu.com服务器IP - ISP向权威域名服务器IP进行请求
www.baidu.comIP,权威域名服务器返回域名对于的IP地址。
以上是迭代的查询方式,还有一种方式是递归查询,比如在ISP第一次请求根服务器时由根服务器再去查询,而不是返回顶级域名服务器。两者的区别在于迭代查询压力放在客户端,而递归查询压力在DNS的根服务器。
从分裤视角看DNS
域名解析的数据,数据量很大,可以说是无穷无穷尽,因为只要符合域名格式的字符串都是一个合法的域名,甚至还能包含中文文字。面对如此海量数据,单库单表根本无法支持,分裤分表势在必行。
涉及到分裤分表,两个问题:
- 怎么分? 如果按照首个字段切分,最大可以切分到26个库出来(如果没有中文域名的情况下),这种情况的弊端是如果26个库都满了,需要再次进行切分的时候就会涉及到数据迁移,比如再次按照前两位进行切分。这种情况下进行数据迁移非常麻烦,一定要极力避免这种情况。比如在设计时考虑数据量按照前几位进行切分。
dns基本也是按照这个思路进行切分,由于url格式具备点分隔符的层级性质,所以DNS按照了前几级进行切分,比如按照前二级域名进行切分域名www.baidu.com,其对应存储的数据库因该是“baidu.com”。
那么几级存储到一个库中呢?请接着看。
- 怎么查?
我有域名
www.baidu.com我应该查哪个库呢?此时应该有一个具备全局视野的服务器提供域名解析“数据库”IP的功能,暂时称这个服务器叫解析1,假设层级是.com经过解析1返回“数据库”IP,解析就已经完成。
但是如果.com下数据了又变得非常巨大影响查询呢?比如baidu.com下面有非常大数量的数据,这时我们可以选择在解析1中增加一条记录 baidu.com 解析到“数据库2”IP。如此一来,又会有一个问题,解析1中的数据了也变大了怎么办?
DNS给出了很好的实现,再次增加一个解析2,解析1仅记录映射到解析2的IP。比如baidu.com解析com域名通过解析1映射到解析2,然后在向解析2查询baidu.com对于的IP。
这样层级全局表(解析1、2)+数据表的分裤思想非常的巧妙,当某个节点数据量变大时只需要迁移层级域名数据到一台数据表服务器,然后修改上层域名解析到改服务器即可。