CockroachDB 的多地域能力通过数据库级 survival goal 来控制数据在故障域之间的副本放置。ZONE 和 REGION 两个目标表面上是容灾等级不同,实际上会改变 Raft 多数派的构成位置、租约分布、写入延迟以及节点数量要求。如果在同城三机房与跨地域三活之间犹豫,先把这两个目标分别对应的故障域和副本策略理清,再决定配置方式。

一、ZONE 与 REGION 在副本与故障域层面的差异
ZONE survival goal 面向可用区级故障。它要求数据库至少跨越三个可用区,每个可用区放置一个具有投票权的副本。副本通常位于同一个地域,因此节点之间的网络往返在毫秒级。当某个可用区整体中断时,剩余两个可用区仍然拥有多数派副本,Raft 可以继续选举和提交,业务写入不中断。实现方式是通过 ALTER DATABASE ... SURVIVE ZONE FAILURE 调整,也可以在建库时直接指定。
REGION survival goal 则把故障域提升到整个地域。它至少需要三个地域,每个地域至少保留一个投票副本。这样做的好处是,即使某个地域因自然灾害、骨干网中断或云厂商区域故障导致所有节点不可用,剩余地域的副本依然可以形成多数派,集群的可用性不受影响。不过代价也很明显:Raft 的日志提交需要跨地域往返,事务延迟会从同地域的几毫秒上升到数十甚至上百毫秒。
需要特别注意,ZONE 与 REGION 不是简单的高中低关系。三副本在同一个地域的三个可用区只能容忍单可用区故障,无法防住整个地域失效。如果业务真的要求地域级容灾,至少要规划三个地域;只有两个地域时设置 REGION survival goal 会报错,或者会因为多数派无法在剩余的一个地域形成而导致目标无法真正达成。
ALTER DATABASE orders SURVIVE ZONE FAILURE; ALTER DATABASE orders PRIMARY REGION 'us-east1'; ALTER DATABASE orders ADD REGION 'us-west1'; ALTER DATABASE orders ADD REGION 'eu-west1'; ALTER DATABASE orders SURVIVE REGION FAILURE;
二、延迟、成本与吞吐的量化比较
选择 ZONE 还是 REGION,本质上是在故障恢复能力和性能成本之间做取舍。同地域三个可用区的网络往返通常只有 1 到 5 毫秒,写入事务在多数派确认后返回,对在线业务几乎无感。跨地域三个区域之间,以美国东部到西部为例,往返时间普遍在 60 到 80 毫秒;跨大西洋或太平洋可能超过 100 毫秒。事务如果要等待远端副本确认,单次写入延迟会显著增加,读写敏感的系统需要评估是否能接受。
成本方面,REGION 配置不只是节点数量增加。跨地域的数据同步会产生大量出口流量,云厂商对跨可用区流量一般免费或低价,但跨地域流量通常按 GB 计费。其次,至少三个地域意味着要在每个地域维护独立的节点、存储和备份,运维复杂度上升。ZONE 配置下,同一地域内跨可用区的流量成本较低,网络故障隔离也更简单,更适合刚刚开始做多活架构的团队。
吞吐量也会受 Raft 同步影响。写密集场景下,REGION 配置的持久化延迟容易被远端最慢副本放大,虽然 CockroachDB 可以通过并行复制和异步非投票副本优化读扩展,但写入的多数派确认无法绕过。如果读多写少,可以在远端增加非投票副本改善本地读;但写入仍然需要跨地域投票。因此评估时不能只看总 QPS,还要看 p99 写延迟。
| 维度 | ZONE survival goal | REGION survival goal |
|---|---|---|
| 最小故障域 | 单个可用区 | 单个地域 |
| 最低拓扑 | 同地域 3 个可用区 | 3 个地域,每地域至少 1 节点 |
| 写入延迟 | 通常 1-5ms | 通常 60-150ms |
| 跨地域流量成本 | 低 | 高 |
| 防全区故障 | 否 | 是 |
三、实际配置与拓扑规划
规划 REGION 容灾时,节点的 locality 标志必须与数据库区域元数据一致。比如三个地域分别命名为 us-east1、us-west1、eu-west1,每个地域可以再细分可用区。启动节点时通过 --locality 参数声明 region 和 zone,数据库才会把副本放到正确的故障域中。节点启动后,再在数据库层添加 region 并设置 survival goal。
cockroach start \ --insecure \ --store=node1 \ --listen-addr=0.0.0.0:26257 \ --http-addr=0.0.0.0:8080 \ --join=10.0.0.1:26257,10.0.1.1:26257,10.0.2.1:26257 \ --locality=region=us-east1,zone=us-east1-a
切换 survival goal 时,CockroachDB 会自动调整表的 zone configuration,触发副本重新平衡。例如从 ZONE 改为 REGION 后,系统会在其他地域补齐副本,可能造成短时间的 CPU、网络和磁盘 I/O 上升。对于大表,这个过程可能持续数十分钟甚至更久。建议在业务低峰执行,并通过 SHOW RANGES FROM TABLE orders WITH DETAILS 观察副本迁移进度。
为了降低跨地域写延迟,可以结合表级 locality 做分级。核心交易表必须满足 REGION survival goal,而历史归档表或只读报表可以继续使用 ZONE survival goal,甚至设置 GLOBAL 或 REGIONAL BY TABLE 的表级 locality。CockroachDB 支持在同一个数据库内混合使用不同 survival goal,只要数据库级目标是最严格的那个。
四、常见误区和故障演练清单
常见误区之一是把多可用区等同多地域。某个团队的集群部署在同一个城市的三个机房,就认为已经做到异地容灾。实际上,同城三机房只能防机房级火灾、电力或网络设备故障,无法防住城市级断网、洪水或区域云服务中断。如果监管或业务连续性要求地域级灾难恢复,必须使用 REGION survival goal 并且物理上分布在足够远的地域。
另一个误区是只配置了 region 名称,却没有在启动参数中正确声明 locality。CockroachDB 依据节点 locality 来放置副本,如果节点实际在弗吉尼亚,但 locality 标成 us-west1,系统会错误地认为副本分布在西部,导致故障时数据不可用。启动脚本应该由配置管理工具统一下发,避免手工修改。
故障演练不能只停留在纸面。建议定期用网络分区或直接停止某一地域节点的方式,验证 REGION survival goal 下业务是否仍可读写。可用以下 SQL 检查副本投票分布:
SELECT range_id, lease_holder, voting_replicas, non_voting_replicas FROM crdb_internal.ranges WHERE table_name = 'orders';
观察 voting_replicas 是否分布在三个地域。若分布正确,再检查故障期间 p99 延迟变化和恢复时间。演练中如果发现 leaseholder 集中在某一个地域,应调整 lease_preferences 让租约在故障后能平滑转移到其他地域。
CockroachDB容灾survival goalsZONE与REGION修改时间:2026-09-23 07:54:14