面试官:CNAME和A记录有什么区别?

配置域名解析的时候,经常看到A记录、CNAME这些选项:

  • A记录和CNAME到底有什么区别?
  • 为什么GitHub Pages要求添加CNAME记录?
  • 什么时候该用A记录,什么时候该用CNAME?

先说结论

对比项 A记录 CNAME记录
指向目标 IP地址 另一个域名
解析次数 1次 2次或更多
根域名支持 支持 不支持
典型场景 直接指向服务器 CDN、托管平台
灵活性 低(IP变更需修改) 高(目标域名IP变更无感知)

两种记录的本质区别

A记录:直接指向IP

A记录(Address Record)是最基础的DNS记录,直接把域名映射到IP地址。

css 复制代码
# A记录配置
example.com.    IN    A    185.199.108.153

DNS查询过程很简单:

复制代码
用户查询 example.com → DNS返回 185.199.108.153 → 完成

CNAME:指向另一个域名

CNAME(Canonical Name)记录不直接指向IP,而是指向另一个域名。

objectivec 复制代码
# CNAME配置
blog.example.com.    IN    CNAME    username.github.io.

DNS查询需要两步:

lua 复制代码
用户查询 blog.example.com → DNS返回 username.github.io → 继续查询 → DNS返回 185.199.108.153 → 完成

用流程图表示更清楚:

flowchart LR subgraph A记录解析 A1[用户查询\nexample.com] --> A2[DNS服务器] A2 --> A3[返回IP\n185.199.108.153] end subgraph CNAME解析 C1[用户查询\nblog.example.com] --> C2[DNS服务器] C2 --> C3[返回CNAME\nusername.github.io] C3 --> C4[继续查询] C4 --> C5[返回IP\n185.199.108.153] end

为什么需要CNAME

看起来CNAME多了一次查询,更慢了。那为什么还要用它?

场景一:服务器IP会变

假设你用A记录把域名指向了一台服务器:

css 复制代码
www.example.com.    IN    A    1.2.3.4

有一天服务器迁移了,IP变成了 5.6.7.8,你需要手动改DNS配置。如果有多个域名都指向这台服务器,每个都要改。

用CNAME就不一样了:

objectivec 复制代码
www.example.com.     IN    CNAME    myapp.hosting.com.
blog.example.com.    IN    CNAME    myapp.hosting.com.
api.example.com.     IN    CNAME    myapp.hosting.com.

服务器IP变了,只需要托管平台(myapp.hosting.com)更新它的A记录,你的所有域名自动生效。

场景二:CDN加速

CDN服务商会根据用户位置返回最近的节点IP。这个IP是动态的,不可能用A记录。

csharp 复制代码
# 接入阿里云CDN
static.example.com.    IN    CNAME    example.com.w.kunlunsl.com.

阿里云的CDN会自动把用户引导到最近的节点,你不需要关心具体IP是什么。

场景三:托管服务

GitHub Pages、Vercel、Netlify这类托管平台都要求用CNAME,原因是:

  1. 平台的服务器IP可能随时变化
  2. 平台需要通过域名识别你的站点
  3. 便于实现负载均衡和故障转移

CNAME的限制

根域名不能用CNAME

这是DNS协议的硬性规定。根域名(如 example.com)可能有MX记录(邮件)、NS记录(域名服务器)等,CNAME会与这些记录冲突。

objectivec 复制代码
# 错误:根域名不能设置CNAME
example.com.         IN    CNAME    username.github.io.

# 正确:使用www子域名
www.example.com.     IN    CNAME    username.github.io.

那根域名怎么办?有两个方案:

方案一:用A记录直接指向IP

css 复制代码
example.com.    IN    A    185.199.108.153
example.com.    IN    A    185.199.109.153
example.com.    IN    A    185.199.110.153
example.com.    IN    A    185.199.111.153

方案二:用ALIAS记录(部分DNS服务商支持)

ALIAS是一种"假的CNAME",在DNS服务商那边做了一层转换:

bash 复制代码
# Cloudflare、DNSPod等支持
example.com.    IN    ALIAS    username.github.io.

实际返回给用户的还是IP地址,但配置时可以填域名。

CNAME不能和其他记录共存

同一个域名,如果设置了CNAME,就不能再设置A记录、MX记录等。

erlang 复制代码
# 错误:CNAME和MX冲突
mail.example.com.    IN    CNAME    mailserver.com.
mail.example.com.    IN    MX       10 mailserver.com.

# 正确:分开使用不同子域名
www.example.com.     IN    CNAME    hosting.com.
mail.example.com.    IN    MX       10 mailserver.com.

实战配置示例

GitHub Pages自定义域名

  1. 在仓库根目录创建CNAME文件:

    blog.example.com

  2. 在域名服务商添加CNAME记录:

bash 复制代码
# DNS配置
blog.example.com.    IN    CNAME    username.github.io.
  1. 验证配置:
bash 复制代码
# 查看CNAME记录
dig CNAME blog.example.com

# 输出示例
;; ANSWER SECTION:
blog.example.com.    300    IN    CNAME    username.github.io.
username.github.io.  300    IN    A        185.199.108.153

Vercel部署

bash 复制代码
# www子域名用CNAME
www.example.com.    IN    CNAME    cname.vercel-dns.com.

# 根域名用A记录
example.com.        IN    A        76.76.21.21

Cloudflare CDN

bash 复制代码
# 接入Cloudflare
www.example.com.    IN    CNAME    example.com.cdn.cloudflare.net.

Cloudflare的特殊之处在于它支持"CNAME Flattening",即使是根域名也可以配置CNAME,它会自动转换成A记录返回。

常见问题排查

配置了CNAME但不生效

检查TTL:DNS缓存可能还没更新,等待TTL时间过期。

bash 复制代码
# 查看TTL
dig blog.example.com

# 缩短TTL加快测试(配置时设置)
blog.example.com.    60    IN    CNAME    username.github.io.

检查传播状态

bash 复制代码
# 使用nslookup指定DNS服务器
nslookup blog.example.com 8.8.8.8

# 或用在线工具
# https://dnschecker.org/

循环引用

css 复制代码
# 错误:A指向B,B又指向A
a.example.com.    IN    CNAME    b.example.com.
b.example.com.    IN    CNAME    a.example.com.

DNS服务器会检测循环引用并报错,但排查起来比较麻烦。配置时避免复杂的CNAME链。

HTTPS证书问题

CNAME只是DNS层面的跳转,HTTPS证书需要在最终服务器上配置。

如果你把 blog.example.com CNAME到了 username.github.io,那么:

  • GitHub Pages需要支持你的自定义域名
  • 证书要能覆盖 blog.example.com

GitHub Pages会自动申请Let's Encrypt证书,但需要在仓库设置里开启HTTPS。

决策指南

objectivec 复制代码
需要配置域名解析
├─ 托管在第三方平台(GitHub Pages、Vercel、Netlify)?
│   └─ 用 CNAME 指向平台域名
├─ 接入CDN?
│   └─ 用 CNAME 指向CDN域名
├─ 直接部署在自己的服务器?
│   ├─ IP固定且不会变?
│   │   └─ 用 A 记录
│   └─ IP可能变化?
│       └─ 考虑用 CNAME 指向一个自己控制的域名
└─ 根域名?
    └─ 只能用 A 记录或 ALIAS(如果DNS服务商支持)

小结

  • A记录:域名 → IP,简单直接,但IP变了要手动改
  • CNAME:域名 → 域名 → IP,多一次查询,但更灵活
  • 根域名不能用CNAME,这是DNS协议限制
  • CDN、托管平台都用CNAME,因为它们的IP是动态的

选择的核心原则:如果目标IP可能变化,用CNAME;如果IP固定,用A记录。


如果你觉得这篇文章有帮助,欢迎关注我的 GitHub,下面是我的一些开源项目:

Claude Code Skills (按需加载,意图自动识别,不浪费 token,介绍文章):

全栈项目(适合学习现代技术栈):

  • prompt-vault - Prompt 管理器,用的都是最新的技术栈,适合用来学习了解最新的前端全栈开发范式:Next.js 15 + React 19 + tRPC 11 + Supabase 全栈示例,clone 下来配个免费 Supabase 就能跑
  • chat_edit - 双模式 AI 应用(聊天+富文本编辑),Vue 3.5 + TypeScript + Vite 5 + Quill 2.0 + IndexedDB
相关推荐
艾文伯特29 分钟前
Charles + Proxifier 实现软件HTTPS抓包
网络协议·http·https
AI视觉网奇4 小时前
ue http 请求学习笔记
网络·网络协议·http
集智飞行4 小时前
mavros udp url
网络·网络协议·udp
一颗青果10 小时前
HTTP协议详解
linux·网络·网络协议·http
晚枫歌F18 小时前
TCP协议详解
网络·网络协议·tcp/ip
秋42718 小时前
防火墙基本介绍与使用
linux·网络协议·安全·网络安全·架构·系统安全
sweet丶18 小时前
扩展了解DNS放大攻击:原理、影响与防御
网络协议·安全
科技块儿20 小时前
我应该如何选择并使用IP数据库评估不同地区的定位精度(⊙_⊙?)
网络·网络协议·tcp/ip
万粉变现经纪人21 小时前
如何解决 pip install SSL 报错 ValueError: check_hostname requires server_hostname 问题
网络·python·网络协议·beautifulsoup·bug·ssl·pip
松涛和鸣1 天前
DAY42 SQLite3 : Dictionary Import and Data Query Implementation with C Language
linux·c语言·数据库·单片机·网络协议·sqlite