三十年前,经营一家大酒楼很简单:一间大厅、一套厨房、一本账,服务好老主顾就够了。但如今,“麻辣鼎”火锅要做全球连锁,在纽约、东京、上海同时开分店。问题来了——每家分店的库存和订单怎么同步?纽约改了招牌菜,东京几个月后才知道?上海分店断网,其他分店还能继续营业吗?这就是数据库在分布式时代面临的核心矛盾。 CockroachDB 是一套开源的分布式 NewSQL 数据库,名字取自蟑螂的顽强生命力——打不死、能自愈、悄悄开遍全球。它的设计哲学和连锁火锅店如出一辙:每家分店(节点)完全对等、每道菜都有多厨房备份(副本)、上新菜要多数主厨确认(共识)、客人永远去最近的分店吃饭(就近访问)。这篇文章,就带你彻底看懂这套“打不死的全球连锁数据库”。

岗位关联

对数据库架构师而言,理解 CockroachDB 的分布式一致性、全球部署与水平扩展,能让你在多区域业务、金融账务、SaaS 多租户等场景中做出更稳健的技术选型,不再被“单机瓶颈”卡住脖子。

目录
  1. 可视化演示
  2. NewSQL 起源与定位
  3. 分布式集群架构
  4. Raft 共识协议
  5. 分布式事务与一致性
  6. 多区域地理复制
  7. PostgreSQL 兼容
  8. 水平扩展能力
  9. 与 Spanner 对比
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

展示CockroachDB Range分片分布式架构、Raft强一致性共识协议(Leader选举/日志复制)与多区域地理复制策略,切换模式理解NewSQL核心机制。

本节配有交互动效(进入视口后自动加载,约 3KB)。

Range分片与分布式存储架构 数据按Key Range分片存储,每个Range默认64MB,通过Meta层级元数据定位 每个Range以3副本分布在不同节点,单节点故障不丢数据,自动Rebalance均衡负载 Data = {Range1, Range2, ...} | Range = 3 replicas on different nodes CockroachDB通过Range分片实现透明水平扩展

NewSQL 起源与定位

做餐饮,老一辈只有两条路。老字号大酒楼:菜品丰富、账目严谨、有完整事务(ACID),但大厅就摆二十张桌,客流上限明摆着。街头小吃摊:想开几个摊开几个,扩张如野火,但每摊只能卖一两种串,连像样的账本都没有,更别说一次点十道菜并结算。麻辣鼎要做全球连锁,这两条路谁都不合适——它既想要大酒楼的规范,又想要小吃摊的蔓延力。这正是 NewSQL 登上历史舞台的原因。

NewSQL 不是 NoSQL 的换皮。NoSQL 牺牲了事务和 SQL,换来了扩展性;NewSQL 则用分布式架构同时守住 SQL 和 ACID。CockroachDB 是这个领域最具代表性的开源实现。要理解它为什么诞生,先看懂分布式系统绕不开的 CAP 权衡:网络分区(P)发生时,一致性与可用性不可兼得。

CockroachDB 选择了 CP:它把“一致性”刻在骨子里,用 Raft 共识协议保证任何时刻所有分店读到的数据一致。这个选择,让它在金融账务、订单库存这类场景中成为可信赖的底座。

C+A≤1,C,A∈{0,1},P=1\displaystyle C + A \le 1, \quad C, A \in \{0, 1\}, \quad P = 1
这是 CAP 定理的简洁表达:当网络分区发生时,系统只能在“所有节点读到同样数据”和“每个请求都得到响应”之间二选一。
  1. 一致性取值C=1 表示所有分店在同一时刻读到完全相同的菜谱;C=0 则允许分店间菜谱暂时不同。
    C=1或C=0\displaystyle C = 1 \quad \text{或} \quad C = 0
  2. 可用性取值A=1 表示任何客人的点餐请求都能在可容忍时间内得到回应,无论哪家分店。
    A=1或A=0\displaystyle A = 1 \quad \text{或} \quad A = 0
  3. 分区必然发生P=1 意味着跨店网络随时可能中断,这是分布式系统的常态而不是意外。
    P=1\displaystyle P = 1
  4. 不等式含义C 和 A 不能同时为 1,麻辣鼎决定优先保证一致性——宁可让客人多等一秒,也不能让两家分店卖不同的招牌菜。
    C+A≤1\displaystyle C + A \le 1

分布式集群架构

麻辣鼎的分店和传统连锁不一样:没有“总店发号施令”的单点。每家分店都是完整的厨房,有自己的一整套冷藏柜,能独立接待客人。CockroachDB 的集群也是如此——每个节点完全对等,没有主从之分,任何节点都能接收读写请求。

数据多了怎么管理?麻辣鼎把食材按种类分装在不同的冷藏柜里:一号柜放毛肚、二号柜放鹅肠、三号柜放肥牛……数据库也这样,把一张大表按主键切成几十上百个 Range,每个 Range 默认承载约 64MiB 数据。Range 就是“冷藏柜”,柜子里装着一段连续的主键区间。

分柜之后,客人点“鹅肠”时后厨怎么知道去哪号柜拿?这就需要一张“食材地图”——元数据。CockroachDB 用专门的元数据 Range 记录每个数据 Range 分布在哪些节点上,任何节点都能通过这张地图快速定位数据。这个设计让它天然适合多区域部署:把某几号柜子(Range)刻意放在离某地客人最近的区域。

这套“对等节点 + Range 分片 + 元数据定位”的架构,让麻辣鼎新开一家分店变得异常简单:搬几台冷藏柜过去、更新一张食材地图,全世界的分店立刻知道新店的存在,不需要停机整顿。

Data=⋃j=1mRj,Rj={k∣sj≤k<ej}\displaystyle \text{Data} = \bigcup_{j=1}^{m} R_j, \quad R_j = \{ k \mid s_j \le k < e_j \}
整张表的数据是所有 Range 的并集,每个 Range 覆盖一段连续主键区间,区间互不重叠。
  1. 整体数据Data 代表一张表的全部数据,像全球所有分店的食材总和。
    Data\displaystyle \text{Data}
  2. 单个 Range每个 Range 是一段主键从 s_j 到 e_j 的连续数据切片,方括号含起点、圆括号不含终点。
    Rj={k∣sj≤k<ej}\displaystyle R_j = \{ k \mid s_j \le k < e_j \}
  3. 并集覆盖所有 Range 拼起来恰好覆盖全表,不多不少,像冷藏柜编号正好装下所有食材。
    ⋃j=1mRj\displaystyle \bigcup_{j=1}^{m} R_j
  4. 分片意义某个主键属于哪个 Range 是纯数学计算,无需问任何“总店”,因此定位速度极快且天然支持并行处理。
    k∈Rj  ⟺  sj≤k<ej\displaystyle k \in R_j \iff s_j \le k < e_j

Raft 共识协议

总部要推出全球统一的新招牌菜,不能只让一家分店主厨说了算。菜谱必须写入全球菜单,写入的规则是:让多数分店主厨试吃确认,超过半数的店都认可,这道菜才正式上架。Raft 共识协议就是这个“多数派投票”机制的工程实现。

在 Raft 中,每个数据 Range 的多个副本构成一个小组,组内通过选举产生一个“主厨”(领导者)。客户端写入先到主厨,主厨把写入记入日志,复制给其他副本;当多数派副本确认后,写入才正式提交。为什么必须多数派?因为多数派之间必有交集,能保证不会出现两个主厨各写各的账。

回到火锅店的比喻:5 家分店里只要有 3 家还开门,全球客人就依然能点到招牌菜;如果只剩 2 家,麻辣鼎就暂时打烊了。这种“多数派即生”的设计,正是 CockroachDB 名字里“打不死”的底气。

q=⌊n2⌋+1,f=⌊n−12⌋\displaystyle q = \left\lfloor \frac{n}{2} \right\rfloor + 1, \qquad f = \left\lfloor \frac{n-1}{2} \right\rfloor
q 是提交一次写入所需的最少确认副本数,f 是集群能容忍的最大故障副本数。5 副本时 q=3、f=2:倒两台照常营业,倒三台才关门。
  1. 副本总数n 表示同一 Range 的副本数量,CockroachDB 默认取 3,生产环境常见 5。
    n=5\displaystyle n = 5
  2. 向下取整地板符号取不超过 n/2 的最大整数,例如 5/2=2.5,取 2。
    ⌊n2⌋=⌊2.5⌋=2\displaystyle \left\lfloor \frac{n}{2} \right\rfloor = \lfloor 2.5 \rfloor = 2
  3. 多数派下限加 1 确保确认数严格超过半数,即至少 3 个副本确认。
    q=2+1=3\displaystyle q = 2 + 1 = 3
  4. 容错上限f 是能容忍的宕机节点数,5 个副本时最多挂 2 台,集群依然可用。
    f=⌊n−12⌋=2\displaystyle f = \left\lfloor \frac{n-1}{2} \right\rfloor = 2

分布式事务与一致性

客人点单是一件“一条龙”的事:锅底、配菜、酒水、会员积分,必须在一个账单里全部成功或全部失败。如果锅底下单了、配菜库存却没扣,全单作废重来。这就是 ACID 事务在分布式世界的挑战:一次操作横跨多个节点,怎么保证原子性?

CockroachDB 用两阶段提交配合事务记录来实现分布式事务。它默认提供“快照隔离”:每个事务在开始时刻看到一个一致的全局快照,读操作不会被并发写干扰。为了让跨节点事务能排出先后顺序,所有事件都需要一个全局一致的时间戳——但全球节点的物理时钟不可能完全同步,于是它采用了混合逻辑时钟(HLC),把物理时间和逻辑计数器结合,给每个事件盖上“谁先谁后”的章。

麻辣鼎的账房先生不再需要人工核对各分店的手写账单——分布式事务确保每一单在全世界任何分店看来都是同一笔完整交易,不多扣、不少记、不出现半笔账。

Conflict  ⟺  W(Ti)∩W(Tj)≠∅ ∧ ts(Ti)<ts(Tj)\displaystyle \text{Conflict} \iff W(T_i) \cap W(T_j) \ne \varnothing \ \wedge \ \text{ts}(T_i) < \text{ts}(T_j)
两个事务如果写相同数据且时间戳能分出先后,就构成写冲突,后提交者需要重试或回滚,避免账目错乱。
  1. 写集合W(T_i) 是事务 T_i 要修改的所有数据项的集合,像一单里要扣的所有食材。
    W(Ti)\displaystyle W(T_i)
  2. 交集非空交集不为空表示两个事务碰了同一批食材,例如同时修改同一条库存记录。
    W(Ti)∩W(Tj)≠∅\displaystyle W(T_i) \cap W(T_j) \ne \varnothing
  3. 时间戳判定HLC 提供的 ts 值能判断谁先谁后,先到者先得,后到者必须等待或重试。
    ts(Ti)<ts(Tj)\displaystyle \text{ts}(T_i) < \text{ts}(T_j)
  4. 冲突处理判定为冲突后,系统自动重试过期事务,对外表现为“事务要么全部成功要么全部回滚”。
    ⇒Retry(Tj)\displaystyle \Rightarrow \text{Retry}(T_j)

多区域地理复制

纽约人吃火锅不会跑东京,但纽约分店断货时,东京的备货能否顶上?CockroachDB 的多区域地理复制,就是把菜谱和食材在多个区域的节点上各存一份,让每个区域的客人都能就近点餐、就近读取,同时在灾难发生时自动切换区域。

CockroachDB 允许你为数据配置“副本放置策略”:例如 3 区域各放 1 个副本,或 1 区域放 3 个副本。写入需要跨区域多数派确认,所以跨洋写入的延迟比单区域高得多——这是物理定律决定的。光在光纤中大约每秒走 20 万公里,数据包一来一回,距离翻倍。

多区域复制让麻辣鼎真正变成了“全球连锁”:不同大陆的客人吃到的味道完全相同,某片区域火山爆发时,其他分店自动接管客流,客人几乎无感知——这就是容灾切换的价值。

LRTT=2Dv,v≈2×108 m/s\displaystyle L_{\text{RTT}} = \frac{2D}{v}, \quad v \approx 2 \times 10^8\ \text{m/s}
跨区域往返延迟约等于两倍距离除以光速。10000 公里外的两地,理论往返延迟约 100 毫秒——这就是“就近部署”如此重要的原因。
  1. 单程距离D 是客户端与数据副本所在地的直线距离,单位用米。上海到新加坡约 3800 公里。
    D=3.8×106 m\displaystyle D = 3.8 \times 10^6\ \text{m}
  2. 光速上限v 是光在光纤中的传播速度,约每秒 20 万公里,比真空光速慢三分之一。
    v≈2×108 m/s\displaystyle v \approx 2 \times 10^8\ \text{m/s}
  3. 往返因子分子中的 2 是因为客户端请求要去、响应要回,一来一回正好两倍距离。
    2D\displaystyle 2D
  4. 典型延迟代入计算,上海到新加坡往返约 38 毫秒,到纽约约 80 毫秒。所以 CockroachDB 尽量把副本放到用户身边。
    LRTT=2×3.8×1062×108≈38 ms\displaystyle L_{\text{RTT}} = \frac{2 \times 3.8 \times 10^6}{2 \times 10^8} \approx 38\ \text{ms}

PostgreSQL 兼容

麻辣鼎的菜谱用什么语言写?答案是全世界中餐厨师都懂的通用中文。这意味着新招一位厨师,不用重新学一门“独门暗语”,培训成本极低。CockroachDB 选择兼容 PostgreSQL,就是这个道理:它使用 PostgreSQL 的线协议和 SQL 方言,让整个 PG 生态现成可用。

对应用开发者来说,代码里连接数据库的方式、写的 SQL 语句、用的 ORM 框架,几乎原样照搬。迁移工具链也是现成的:pg_dump 可以导出数据,psql 可以直接连接操作,甚至许多 PG 扩展语法也能识别。相比从 Oracle 迁到 NoSQL 时需要重写全部数据访问层,迁移到 CockroachDB 的工作量小一个数量级。

当然,“兼容”不等于“100% 相同”。CockroachDB 重点关注的是常用 SQL 和 PG 协议,某些 PG 高级扩展、自定义类型或存储过程特性可能不支持。迁移前做一次兼容性审计,就像新厨师要先试做一遍全部菜品确认火候。

麻辣鼎从旧系统迁到新系统的故事里,最宝贵的资产不是食材,而是那本通用中文菜谱——团队不用重新学做菜,就能在全球新厨房里立刻开始营业。这就是 PG 兼容性的最大价值。

Compat=NunmodifiedNtotal≈95%\displaystyle \text{Compat} = \frac{N_{\text{unmodified}}}{N_{\text{total}}} \approx 95\%
CockroachDB 对常用 PostgreSQL 特性的兼容比例大约在 95% 左右——绝大多数 SQL 语句无需修改即可运行。
  1. 无需修改的语句N_unmodified 是迁移后完全不用改的 SQL 语句条数。
    Nunmodified\displaystyle N_{\text{unmodified}}
  2. 全部语句数N_total 是应用中全部 SQL 语句的总数,包括查询、事务、DDL。
    Ntotal\displaystyle N_{\text{total}}
  3. 兼容比例两者相除得到原样保留的比例。95% 意味着每 100 条 SQL 只有约 5 条需要调整。
    NunmodifiedNtotal≈0.95\displaystyle \frac{N_{\text{unmodified}}}{N_{\text{total}}} \approx 0.95
  4. 剩余差异剩下 5% 通常涉及 PG 特有扩展,需要在迁移方案中显式处理,不能指望自动完成。
    Ntodo=Ntotal−Nunmodified\displaystyle N_{\text{todo}} = N_{\text{total}} - N_{\text{unmodified}}

水平扩展能力

麻辣鼎想接更多客流,最直接的办法是不断新开分店。每开一家店,全系统的食材存储容量和翻台能力就上涨一截,而且老店不需要关门。CockroachDB 的水平扩展也是同一逻辑:往集群里加节点,它自动把已有的 Range 分裂、迁移、再平衡到新节点上。

整个扩展过程是全自动的。某个 Range 超过 64MiB 它会自动一分为二;某个节点负载偏高,它会自动把一部分 Range 搬到空闲节点;加机器、减机器都通过一条命令完成,业务不停机。吞吐量大体随节点数线性上涨——当然,现实世界没有免费的午餐,节点间同步、共识协议的开销都会带来收益递减。

把这句话翻译给麻辣鼎老板:开 9 家新店不等于客流变 9 倍,因为各店之间的“菜品对齐会议”(共识)总在消耗时间。CockroachDB 的工程优化,就是不断压缩这个串行比例,让扩展曲线尽量陡峭。

S(n)=1(1−p)+pn\displaystyle S(n) = \frac{1}{(1-p) + \dfrac{p}{n}}
阿姆达尔定律:扩展到 n 个节点时,加速比取决于可并行比例 p。p 越接近 1,扩展性越好;串行开销越大,加机器收益越低。
  1. 并行比例p 表示系统中可并行执行的工作占比。数据分片查询、无关联写操作都属此类。
    p≈0.9\displaystyle p \approx 0.9
  2. 节点数量n 是集群中的节点总数,可以理解为新开的分店数。
    n=8\displaystyle n = 8
  3. 分母构成1-p 是串行部分(如跨节点事务协调),p/n 是并行部分被摊到 n 个节点后的开销。
    (1−p)+pn\displaystyle (1-p) + \frac{p}{n}
  4. 扩展上限当 n 趋向无穷大时,加速比逼近 1/(1-p)。串行比例 10% 时,最大加速比也只有 10 倍。
    lim⁡n→∞S(n)=11−p\displaystyle \lim_{n \to \infty} S(n) = \frac{1}{1-p}

与 Spanner 对比

同样做全球连锁,国际巨头“九鼎集团”走的是另一条路:它给每家分店装上 GPS 定位和原子钟,让全世界分店的钟表误差不超过几毫秒,从而精确编排全球订单。这就是 Google Spanner 的 TrueTime 机制。而麻辣鼎(CockroachDB)用普通挂钟加聪明的逻辑时钟(HLC),也做到了类似的效果,代价却低得多。

Spanner 的 TrueTime 用 GPS 和原子钟给出一个时间区间 [earliest, latest],事务提交时必须等待超过这个区间,确保未来的时间戳排序不会后悔。这个等待至少是两倍的误差窗口。CockroachDB 不依赖特殊硬件,用 HLC 加上提交等待和冲突检测,同样能提供可串行化的一致性和外部一致性保证。

两位国际化选手的终极差异在“门槛”:九鼎集团必须在自家豪宅里才能运作;麻辣鼎是开源配方,任何云上都能搭灶生火。选型时,如果公司在 Google Cloud 且想要全托管,Spanner 是康庄大道;若要私有化部署、多云架构、或拥抱开源生态,CockroachDB 更对胃口。

CommitWait≥2ε,ε≈7 ms\displaystyle \text{CommitWait} \ge 2\varepsilon, \quad \varepsilon \approx 7\ \text{ms}
Spanner 的真时间误差 ε 约 7 毫秒,事务提交前必须等待约 14 毫秒以消弭不确定窗口;CockroachDB 用逻辑时钟避免了这种物理等待。
  1. 时间误差窗口ε 是 TrueTime 给出的系统时间不确定范围,约 7 毫秒。
    ε≈7 ms\displaystyle \varepsilon \approx 7\ \text{ms}
  2. 必须的等待提交前要等到时间戳越过最晚可能值,至少 2 倍 ε。
    CommitWait≥2ε\displaystyle \text{CommitWait} \ge 2\varepsilon
  3. 延迟代价代入数值,每次跨区域提交至少自带约 14 毫秒的基础延迟。
    2×7 ms=14 ms\displaystyle 2 \times 7\ \text{ms} = 14\ \text{ms}
  4. CockroachDB 的取舍不用 TrueTime,改用 HLC 逻辑时钟,用冲突检测兜底,换来的是可以在普通云服务器上部署。
    No special hardware required\displaystyle \text{No special hardware required}

AI 应用场景

全球跨境电商订单系统

阶段:数据层架构设计

解决的问题:传统单机数据库无法支撑全球用户就近访问;使用分库分表中间件后,跨地域查询和分布式事务难以保证一致性。CockroachDB 通过多区域部署 + Range 分片,让订单、库存、支付在一个逻辑库内完成强一致事务。

具体案例:某跨境电商(类似 Shein)在美东、欧盟、东南亚各部署一个区域,每个区域 3 节点。用户下单时请求就近节点,库存扣减与支付在同一分布式事务中提交;某区域机房故障时,流量自动切换到其余区域,实现了 RPO≈0 的容灾。

金融核心账务系统迁移

阶段:数据库选型与迁移实施

解决的问题:银行核心系统长期依赖 Oracle 单点,扩容成本高、容灾能力弱。CockroachDB 提供了 PG 兼容的 SQL 界面,使迁移团队不必重写全部数据访问代码,同时获得分布式扩展和多活容灾。

具体案例:某城商行将个人负债系统从 Oracle 迁移到 CockroachDB,应用层修改量控制在 15% 以内;通过 5 副本配置,在容忍 2 个节点故障的同时,日终批量跑批时间缩短 40%。

云原生 SaaS 多租户平台

阶段:分布式存储底座设计

解决的问题:SaaS 服务商需要在不同云厂商、不同地区快速复制一套独立环境,同时为每个租户提供一致的数据隔离和弹性伸缩能力。CockroachDB 的节点对等架构和自动再平衡能力,天然适配这种“随租户增长而扩容”的场景。

具体案例:某云 ERP 服务商为每个大客户分配独立数据库,集群按月自动扩容。高峰期通过横向加节点吸收流量,低峰期缩容省钱;PostgreSQL 兼容让已有 ORM 和报表工具零改造接入。

Python 演示

python31 行
import random def quorum(n):    """Compute minimum confirmed replicas for a write"""    return n // 2 + 1 def fault_tolerance(n):    """Compute max failed nodes the cluster can tolerate"""    return (n - 1) // 2 def simulate_availability(n, fail_rate, trials=100000):    """Monte Carlo: probability that a write still succeeds"""    q = quorum(n)    ok = 0    for _ in range(trials):        alive = 0        for _ in range(n):            if random.random() > fail_rate:                alive += 1        if alive >= q:            ok += 1    return ok / trials if __name__ == '__main__':    for n in (3, 5, 7, 9):        q = quorum(n)        f = fault_tolerance(n)        avail = simulate_availability(n, 0.3)        print('replicas =', n, 'quorum =', q,              'fault_tolerance =', f,              'availability =', round(avail, 4))
目的:用蒙特卡洛模拟验证 Raft 多数派机制——每个节点有 30% 概率宕机时,不同副本数下写入成功的概率。直观展示为什么副本越多可用性越高,但节点越多。
  1. def quorum(n):定义多数派计算函数,对应正文中 q = ⌊n/2⌋ + 1。
  2. def fault_tolerance(n):计算集群最多容忍几个节点宕机,5 副本时返回 2。
  3. if alive >= q:判断存活节点是否达到多数派,达到则计一次写入成功。
  4. simulate_availability(n, 0.3)执行 10 万次随机实验,得到高置信度的可用性估计。

常见误区

误区蟑螂在中文里是负面形象,名叫 Cockroach 的数据库,应该是 Bug 很多、经常崩溃的玩具项目吧?

正解恰恰相反,CockroachDB 以蟑螂的顽强生命力为灵感:被打不死的分布式特性。它把“容错自愈”当作核心卖点——节点宕机、网络分区、区域灾难都能自动恢复。名字是在宣告“怎么都打不死”,而不是自嘲工程质量。

为何常见:文化语境不同。英文里 cockroach 在此是韧性象征,而中文读者容易把“蟑螂”与“脏乱、低质”划等号。

误区NewSQL 和 NoSQL 都带 SQL,应该是在 NoSQL 基础上加了新功能,本质还是 NoSQL 那一套。

正解NewSQL 与 NoSQL 是方向相反的产物。NoSQL 为了扩展性放弃 SQL 和 ACID 事务;NewSQL 恰恰要保留 SQL、事务和关系模型,只是把存储层改造成分布式。CockroachDB 可以看成“带 SQL 的分布式关系数据库”。

为何常见:两个词都带"SQL"且都诞生于大数据时代,容易误以为是迭代关系,实际它们是并列的两条技术路线。

误区数据安全等于多备份,那我把副本数从 3 调到 9,不是更保险吗?

正解副本增多,每次写入要确认的多数派也变大(9 副本需 5 确认),写延迟显著上升;同时跨区域复制流量成本翻倍。CockroachDB 默认 3 副本正是安全与性能的平衡点。在低延迟场景,甚至可用 2 副本(多数派为 2,牺牲一点容错)。

为何常见:直觉上冗余越多越安全,忽略了分布式共识中“写入等待多数确认”的机制——冗余是要花钱花时间的。

误区官网说兼容 PostgreSQL,那我现有的 PG 库可以直接迁移,所有 SQL 和扩展都能用。

正解CockroachDB 兼容的是 PG 线协议和绝大部分常用 SQL,但并非 100% 复刻全部生态。部分自定义类型、存储过程细节、特定扩展(如 PostGIS 的完整功能)可能不兼容。迁移前需要做兼容性审计,而非直接下结论。

为何常见:厂商宣传易让人忽略“兼容”的粒度,只有动手迁移时才发现边缘特性差异。

误区集群几十个节点,查询肯定比一台 MySQL 快得多,直接用 CockroachDB 替换没错。

正解分布式系统在网络往返、共识确认、跨节点调度上都有额外开销。单表几百万行的小业务,单机数据库可能更快。CockroachDB 的优势在数据量超过单机容量、吞吐需要横向扩展、或者需要多区域容灾时才真正体现。

为何常见:把“水平扩展能力”误解为“每个操作都更快”,忽略了分布式是为了解决容量和可用性问题,而非单次查询延迟问题。

面试题

Q1. CockroachDB 属于下列哪一类数据库?

单选题 · easy

  • A.传统关系型数据库
  • B.键值型 NoSQL 数据库
  • C.分布式 NewSQL 数据库← 正确答案
  • D.文档型 NoSQL 数据库

答案:C。CockroachDB 保留 SQL 和 ACID 事务,同时采用分布式存储架构,是典型 NewSQL。A 错在“传统”——它并非单机架构;B 和 D 都是 NoSQL,牺牲了事务能力,与 CockroachDB 的设计方向相反。

Q2. CockroachDB 中一个 Range 默认承载大概多少数据?

单选题 · easy

  • A.大约 64MB 的数据← 正确答案
  • B.大约 128MB 的数据
  • C.大约 256MB 的数据
  • D.大约 512MB 的数据

答案:A。CockroachDB 把表按主键切成 Range,每个 Range 默认约 64MiB。超过这个阈值就自动分裂,类似火锅店冷藏柜装满就加一个新柜。128MB 以上都不是默认值,记住 64MiB 这个基准即可。

Q3. 在一个 5 副本 Raft 集群中,写入至少需要多少副本确认?

单选题 · mid

  • A.至少需要 2 个副本确认
  • B.至少需要 3 个副本确认← 正确答案
  • C.至少需要 4 个副本确认
  • D.至少需要 5 个副本确认

答案:B。多数派公式 q = ⌊n/2⌋ + 1,5 副本时 q=3。只要 3 个副本确认写入就算成功,2 个不足半数,5 个全确认没有必要且拖慢速度。这就像上新菜只需多数主厨点头,不必等所有店都试吃。

Q4. CockroachDB 的事务时间戳依赖下列哪种机制?

单选题 · mid

  • A.依赖 NTP 时间同步协议
  • B.依赖 GPS 加原子钟硬件
  • C.依赖混合逻辑时钟机制← 正确答案
  • D.依赖单调递增的统一时钟

答案:C。CockroachDB 用混合逻辑时钟(HLC)把物理时间与逻辑计数器结合,在普通服务器上为跨节点事务排序。B 是 Google Spanner 的 TrueTime 方案,需要特殊硬件;A 的 NTP 精度不足;D 不存在统一时钟的工程实现。

Q5. 关于 CockroachDB 地理复制的说法,正确的是哪几项?

多选题 · mid

  • A.支持跨地域多活部署← 正确答案
  • B.读写可以就近完成← 正确答案
  • C.故障时自动切换区域← 正确答案
  • D.只能部署在同一城市

答案:ABC。多区域副本配置让数据分布在全球各地,客户端可访问最近节点,区域故障时流量自动转移,实现多活容灾。D 明显错误——CockroachDB 的价值恰恰在于跨地域甚至跨大洲部署。

Q6. CockroachDB 与 PostgreSQL 的关系是什么?

单选题 · easy

  • A.基于 Postgres 改写而来
  • B.兼容其协议和 SQL 语法← 正确答案
  • C.完全不使用 PG 生态工具
  • D.是 PostgreSQL 的云托管版

答案:B。CockroachDB 实现了 PostgreSQL wire protocol,兼容大部分 SQL 语法和生态工具(psql、pg_dump、ORM),但不是从 Postgres 代码 fork 的,也不是 PG 的托管版。这点要分清楚。

Q7. CockroachDB 实现水平扩展的机制包括哪些?

多选题 · hard

  • A.自动进行 Range 分裂← 正确答案
  • B.手动进行垂直扩容
  • C.跨节点自动进行再平衡← 正确答案
  • D.停机维护后再做数据迁移

答案:AC。Range 超过 64MiB 自动分裂,节点负载不均衡时自动迁移副本,这两个机制支撑了弹性扩容。B 是加 CPU/内存的垂直方案,D 需要停机,都不是 CockroachDB 的水平扩展手段。

Q8. 与 Google Spanner 相比,CockroachDB 的关键差异是什么?

单选题 · mid

  • A.依赖 GPS 和原子钟保证时间
  • B.使用普通服务器配合逻辑时钟← 正确答案
  • C.无法保证事务的强一致性
  • D.完全不支持 SQL 标准语法

答案:B。Spanner 用 TrueTime(GPS+原子钟)提供外部一致性;CockroachDB 用 HLC 逻辑时钟在普通硬件上达到类似效果。它仍保证强一致和 SQL 支持,因此 C、D 错误;A 是 Spanner 的特征。

Q9. Raft 共识协议在分布式数据库中的作用包括哪些?

多选题 · hard

  • A.自动选举一个领导者节点← 正确答案
  • B.同步各节点的写入日志← 正确答案
  • C.允许半数以下节点继续写入
  • D.多数派存活时自动恢复服务← 正确答案

答案:ABD。Raft 通过任期选举出领导者,领导者负责把日志复制到跟随者;只要多数派存活,集群就能选出新领导者并继续服务。C 恰恰相反——不足半数时写入会失败,以保证不会出现脑裂。

Q10. 5 节点 Raft 集群跨地域容灾时,写入提交延迟主要取决于什么?

单选题 · extreme

  • A.所有节点的平均往返延迟
  • B.最慢的多数派节点延迟← 正确答案
  • C.最快节点的往返时延
  • D.客户端本地的网络速度

答案:B。Raft 提交需要 q=3 个副本确认,领导者必须等最快的 3 个(含自己)都返回。因此延迟取决于多数派中最慢者的距离和速度,而不是全部节点平均、最快节点或客户端因素。这个特性直接影响跨地域部署时副本组的选择策略。