5.3 地域与可用区
一句话
地域(Region)决定 “数据离用户与监管有多近”,可用区(AZ)决定 “一次机房级故障能带走多少”;两者都是故障域与合规边界的选择,不是 “哪里便宜选哪里”。
三个地理单元,各自决定什么
| 单元 | 隔离的是什么 | 典型 RTT | 决定哪个属性 |
|---|---|---|---|
| 边缘节点(CDN / PoP) | 只缓存静态内容与少量动态加速 | 同城 1–10ms | 首屏延迟、回源带宽 |
| 可用区 AZ | 独立的供电、制冷、网络与机房 | 同地域跨 AZ 1–2ms | 单机房故障的存活率 |
| 地域 Region | 地理 + 政治边界(数据驻留、法域) | 同国跨地域 30–50ms,跨洲 150–250ms | 合规、多地域容灾、成本 |
量级说明:RTT 随距离线性增长,光纤中约 5μs/km(往返 10μs/km),所以 1000 公里天然就是 20ms 起。任何 “跨地域做到 10ms” 的说法都不成立,除非是 “就近接入 + 本地区域内闭环”。
选地域:四条判据,顺序不能换
| 判据 | 怎么量 | 常见错误 |
|---|---|---|
| ① 合规 | 数据能不能落地该法域、审计要求、出境限制 | 先选便宜的地域,再找法务 “想办法” |
| ② 延迟 | 用户分布 × 网络实测(不是 ping 服务器) | 用 “机房到机房” 的延迟冒充用户体验 |
| ③ 服务可用性 | 新机型、新特性、新版本在哪个 Region 先上线 | 架构依赖了只在某一个 Region 才有的能力 |
| ④ 成本 | 单价差异(同规格不同地域可差 10%–20%)+ 出口费 | 只看单价,不看跨地域流量与专线费 |
顺序不能换的原因:合规是硬边界(不可谈),延迟是体验底线,服务可用性是架构约束,只有成本可以商量。反过来按 “成本优先” 选地域,后面三项都会以返工的形式补回来。
AZ:故障域,不是 “机架”
- AZ 之间物理独立:独立供电、制冷、网络出口,所以 “一个 AZ 全灭” 不会连带另一个。
- 但 AZ 之间网络互联,跨 AZ 调用有 1–2ms 的 RTT 与流量费(量级每 GB 一分钱上下,以价目表为准)。
- 因此 “把三副本放三个 AZ” 换来的是 “挂一个 AZ 仍有两副本”;而 “三副本放同一个 AZ 的三个机架”,挂一个 AZ 等于三副本全灭——这是最常见的假高可用。
多数地域提供 3 个上下(部分 2 个或 5 个以上,以官方文档为准)。3 AZ 的最优用途是放 quorum 副本:3 副本分布在 3 个 AZ,任意 1 个 AZ 故障仍满足多数派,W + R > N 的相交条件不变(推导见 21.2 Quorum 与 W + R > N 的证明)。2 个 AZ 则必须做 “1 + 1” 的副本布局,此时挂一个 AZ 就只剩 1 副本,多数派不成立——双 AZ 不是缩小的三 AZ,而是另一种取舍。
放置策略:让副本真的分开了
| 手段 | 保证什么 | 什么时候会失效 |
|---|---|---|
| 反亲和(anti-affinity) | 同角色的 Pod 不落在同一节点/AZ | 资源不足时调度器 “软失败”,照样挤在一起 |
| 拓扑分布约束(topologySpreadConstraints) | 按 AZ/节点均分副本数 | maxSkew 设太大,等于没约束 |
| 云厂商的分布组(spread placement group) | 实例分散到不同物理机 | 只覆盖计算,不覆盖存储与网络 |
| 手工指定子网 | 明确每个实例在哪个 AZ | 扩容模板没同步,新实例又回到单 AZ |
四种手段的共同前提是可验证:部署完抽查一次实际分布(kubectl get pod -o wide 看节点所属 AZ、或云控制台的分布视图)。没有抽查的 “已做多 AZ”,通常只是 “填了参数”。
多 AZ 不等于多活:上限由共享依赖决定
理论上,两个独立 AZ 各 99.9% 可用性,组合可用性约 1 − (1 − 0.999)² ≈ 99.9999%。现实中做不到,因为共同依赖才是瓶颈:
| 共同依赖 | 它挂了会怎样 | 缓解 |
|---|---|---|
| 单主数据库(写在 AZ-A) | AZ-A 挂 = 写入全停 | 跨 AZ 同步副本 + 自动切主(RTO 决定可用性) |
| 负载均衡 / DNS / 证书 | 全局入口挂 = 全部不可用 | 入口本身做多 AZ + 多供应商 |
| 控制面(K8s API、IAM、配额服务) | 扩不了容、验不了权 | 提前缓存凭证、预留容量 |
| 同一条专线 / 同一个 NAT | 网络单点 | 双专线、每 AZ 独立 NAT |
| 同一个人值班 | 人的单点 | on-call 轮转 + runbook |
| 部署形态 | 覆盖的故障域 | 年停机量级(目标) | 成本倍数 |
|---|---|---|---|
| 单 AZ | 无 | 99.9% → 约 8.8 小时 | 1× |
| 多 AZ(同地域) | 机房级 | 99.95%–99.99% | 1.2–2× |
| 多地域(双活) | 地域级 | 99.99%+ | 2× 起,含数据复制 |
| 单元化多活 | 地域 + 租户级 | 99.995%+ | 3× 起,含流量调度 |
这张表的用法是先定目标再选形态,而不是 “能多活就多活”:年停机 8.8 小时可接受时,多 AZ 的 1.2 倍成本已经足够,多地域是纯浪费。灾备目标(RTO / RPO)与拓扑的完整推导见 36.1 RTO / RPO 与 36.4 两地三中心与多活。
跨 AZ 的账:延迟与流量费要一起算
一个请求如果经过 4 个服务、每个服务跨 AZ 一次,就多 4 段跨 AZ 往返:RTT 增加约 4–8ms,流量费按进出两次计。两种常见放大:
- 聊天式调用:一次业务请求拆成 20 次 RPC,全部跨 AZ,延迟与流量费同时翻倍。修法是同 AZ 优先路由(拓扑感知负载均衡)+ 减少调用次数。
- 缓存与数据库的跨 AZ 读:为了 “均匀” 把读也打到跨 AZ 副本,代价是每次读 1–2ms。修法是读写都在本地 AZ 闭环,跨 AZ 只做复制。
流量费的具体结构见 5.6 云成本结构:跨 AZ 与出口流量是账单里最容易漏的两项。
决策表
| 你的情况 | 选择 |
|---|---|
| 单机可承受停机,成本敏感 | 单 AZ,但把备份放另一个 AZ |
| 有状态主库 + 要求 99.95% | 多 AZ + 同步副本 + 自动切主(演练过) |
| 用户只在一个城市、延迟敏感 | 单地域多 AZ + 边缘缓存,不跨地域 |
| 用户跨洲、有数据驻留要求 | 多地域,每地域数据闭环,只同步脱敏聚合结果 |
| 有监管要求 “境内存储” | 地域选择先过合规,再谈成本(见 5.2 部署模型:公有 / 私有 / 混合) |
代码:查清 AZ 与实例的实际可用性
# 1) 这个地域有哪些可用区(注意:AZ 名字与物理机房是“每账号随机映射”的)
aws ec2 describe-availability-zones --region ap-southeast-1 \
--query 'AvailabilityZones[].[ZoneName,State,ZoneId]' --output table
# 2) 某个实例规格在哪些 AZ 有货(“AZ 存在 ≠ 该规格能买到”)
aws ec2 describe-instance-type-offerings --region ap-southeast-1 \
--location-type availability-zone \
--filters Name=instance-type,Values=m6i.xlarge \
--query 'InstanceTypeOfferings[].[Location,InstanceType]' --output table
# 3) 跨 AZ 的实际延迟(两台机器互 ping,看 P50/P99)
ping -c 100 <peer-ip-in-another-az> | tail -2
# Terraform:把“多 AZ”写成“每个 AZ 一个子网”,而不是一个子网挂所有实例
resource "aws_subnet" "app" {
for_each = toset(data.aws_availability_zones.available.names)
availability_zone = each.key
cidr_block = cidrsubnet(var.vpc_cidr, 8, index(data.aws_availability_zones.available.names, each.key))
}
反模式
| 反模式 | 后果 |
|---|---|
| 三副本放同一 AZ 的三个机架 | 以为做了高可用,一次 AZ 故障全灭 |
| 双 AZ 却按 “3 副本多数派” 设计 | 挂一个 AZ 只剩 1 副本,写不进去 |
| 多 AZ 但数据库单主 | 计算层冗余,故障时写入全停 |
| 为了省跨 AZ 流量费把副本挤在一起 | 省下的钱远小于一次故障的损失 |
| 只填了反亲和参数,没抽查分布 | 资源紧张时调度器静默合并 Pod |
| 选地域只看单价 | 合规返工、延迟不达标、专线费反超 |
| 认为 “跨地域可以做到 10ms” | 物理定律不配合,方案从前提就是错的 |
三条铁律
🔑 AZ 是故障域,机架不是:只把副本分到不同机器,等于没分。
🔑 多 AZ 的可用性上限由共同依赖决定,不由 AZ 数量决定;先列共享单点,再谈拓扑。
🔑 先定年停机目标(几个 9),再选单 AZ / 多 AZ / 多地域;反过来选,成本一定花在看不见的地方。
自检
Q1 一个服务部署了 3 个副本,分在同一 AZ 的 3 台不同物理机上。能扛住 AZ 故障吗?
▸ 答案:不能。AZ 故障会同时带走该 AZ 内所有机器,3 个副本 100% 丢失。AZ 内的反亲和只解决 “单机 / 单机架” 故障;要扛 AZ 故障,副本必须分布到 ≥ 2 个 AZ,并且多数派布局要匹配(3 副本跨 3 AZ 时,挂 1 个 AZ 仍满足多数派)。
Q2 两个 AZ 各 99.9%,为什么实际做到 99.99% 都很难?
▸ 答案:因为 1 − (1 − 0.999)² 的 99.9999% 假设了故障完全独立,而真实系统共享一堆依赖:单主数据库、DNS、负载均衡、IAM、专线、甚至同一个值班的人。只要这些共享依赖里的任意一个挂掉,两个 AZ 一起不可用。所以多 AZ 的可用性上限取决于 “共同依赖有几个、各自多可靠”,不取决于 AZ 个数。
Q3 用户分布在华东与华南,是否应该直接上 “两地双活”?
▸ 答案:先算账:华东到华南 RTT 约 30ms,单地域多 AZ + 边缘缓存通常已能把首屏压到可接受范围。两地双活要解决的是数据双写与冲突(写入延迟、跨地域一致性、切流演练),成本 2 倍起。判断标准是 “RTO 目标是否要求地域级故障也能续命”,而不是 “用户分在两个地方”。若只是延迟,靠 CDN + 就近接入更便宜。
Q4 跨 AZ 架构上线后,账单里多出一笔 “区域间数据传输费”,怎么解释给老板?
▸ 答案:这是跨 AZ 的必然成本:副本复制、跨 AZ 调用、跨 AZ 备份都会产生流量费(量级每 GB 一分钱上下)。取舍是明确的:花这笔钱买 “单 AZ 故障不丢服务”。要压低它,靠三件事——同 AZ 优先路由、减少跨 AZ 调用次数、把非关键流量(日志、分析)留在本 AZ。
Q5 云厂商在 B 地域上线了新机型,团队想整体迁过去。该考虑哪三件事?
▸ 答案:① 合规(数据驻留与审计口径是否允许换地域);② 迁移成本(跨地域数据搬迁的时长与流量费,见 5.7 云厂商锁定与迁移 的量化方法);③ 延迟与用户分布(新地域离用户更近还是更远)。只为 “新机型便宜 10%” 迁移,通常会被搬迁成本与业务中断风险吃掉。
跨篇相关:服务模型决定 “地域里你能控制到哪一层”,见 5.1 服务模型:IaaS / PaaS / FaaS;部署形态与合规边界见 5.2 部署模型:公有 / 私有 / 混合;容灾目标与拓扑见 36.1 RTO / RPO、36.4 两地三中心与多活;多数派放置见 21.2 Quorum 与 W + R > N 的证明;跨 AZ 与出口流量的计费结构见 5.6 云成本结构;跨地域搬迁的代价见 5.7 云厂商锁定与迁移。