分布式数据库赛道 — 深度对比研究
调研时间:2026-06-22 基于 OpenTenBase / CockroachDB / TiDB / YugabyteDB / Citus / Vitess 源码阅读
TiDB — 原生分布式 HTAP 的标杆实现
一句话定位
MySQL 兼容的原生分布式 HTAP 数据库,通过存算分离 + 双存储引擎(TiKV 行存 + TiFlash 列存)实现一套系统同时处理事务和分析。
设计哲学上最精彩的地方
TiDB 最精彩的设计决策是用 Raft Learner 打通 TP 和 AP 的数据通道。想象一家公司里,仓库(TiKV)每天实时记录进出货,财务部(TiFlash)需要同样的数据做报表分析。传统做法是每天晚上把仓库数据拷一份给财务——这就是传统 ETL。TiDB 的做法是:财务部派一个”旁听生”坐在仓库里实时抄笔记(Raft Learner),仓库正常工作不受影响,财务部拿到的笔记自动整理成报表格式(列存)。
从源码看,这个设计体现在架构的层次分离上:pkg/planner/ 下有完整的 Cascades 优化器框架(见 pkg/planner/cascades/cascades.go),包含 Memo 结构、规则引擎和任务调度器。查询优化器可以透明地决定一条 SQL 的哪些部分下推到 TiKV(行存,适合点查)、哪些部分下推到 TiFlash(列存,适合扫描聚合),这个决策对用户完全透明。
核心技术创新点
Cascades 优化器框架:TiDB 在 pkg/planner/cascades/ 实现了经典的 Cascades 搜索框架——Optimizer 结构包含 Memo(等价表达式存储)和 Scheduler(任务调度),通过规则驱动(rule/ 目录下有丰富的转换规则如 join reorder、predicate pushdown、aggregation elimination 等)进行查询优化。这是工业级分布式数据库中少见的完整 Cascades 实现。
自研 SQL Parser:pkg/parser/ 是一个独立可用的 MySQL 兼容解析器(有独立的 go.mod),基于 yacc(parser.y)生成,包含完整的 AST 定义(ast/ 目录下有 ddl.go、dml.go、expressions.go 等),支持 MySQL 语法的绝大多数特性。
Plan Cache 机制:pkg/planner/core/plan_cache.go 和 plan_cache_instance.go 实现了非 Prepared Statement 的计划缓存(NonPrepared Plan Cache),通过 LRU 策略(plan_cache_lru.go)管理缓存实例,显著降低重复查询的优化开销。
竞争格局中的位置
TiDB 是 MySQL 兼容阵营的绝对领导者(~41K Star),在国内互联网行业(金融、电商、游戏)有大量生产部署。它的主要竞争优势是:完整的 HTAP 能力(TiKV + TiFlash)、活跃的中文社区、PingCAP 的商业支持。在全球分布式数据库领域,TiDB 和 CockroachDB 分别代表了 MySQL 和 PostgreSQL 两大生态的标杆。
CockroachDB — Spanner 设计的工业级开源实现
一句话定位
PostgreSQL 兼容的云原生分布式 SQL 数据库,直接复刻 Google Spanner 的全局一致性设计——每个节点存算一体,自动分片、自动均衡、强一致事务。
设计哲学上最精彩的地方
CockroachDB 最精彩的决策是“每个节点都是完整的数据库”。想象一个连锁便利店,每家店既能收银又能管库存,总部不需要专门的”存储中心”。任何一家店倒闭,客户去隔壁照常买东西。这种存算一体的设计消除了单点依赖,把高可用变成了架构的内在属性而非附加特性。
源码中这个设计理念无处不在。pkg/kv/kvserver/store.go 是核心——每个 Store 管理多个 Range(数据分片),每个 Range 通过 Raft 复制到多个节点。pkg/raft/ 是 CockroachDB 自己 fork 并深度定制的 etcd Raft 实现(见 doc.go 中详细的 398 行文档),增加了 Store Liveness、Fortification(tracker/fortificationtracker.go)等创新特性。pkg/storage/pebble.go 则封装了底层存储引擎 Pebble(CockroachDB 自研的 LSM-Tree 存储引擎,替代了早期的 RocksDB)。
核心技术创新点
Parallel Commits:docs/tla-plus/ParallelCommits/ 包含了用 TLA+ 形式化验证的并行提交协议——事务的提交操作与最后一轮写操作并行执行,将两阶段提交的延迟从 2 轮 RTT 降到 1 轮。这是 CockroachDB 对 Spanner 设计的重要改进。
深度定制的 Raft 实现:pkg/raft/ 不是简单的 etcd Raft 搬运。它引入了 StoreLiveness(raftstoreliveness/)机制替代传统心跳检测,以及 Fortification(rafttest/testdata/fortification_*.txt 的大量测试数据可见)机制来防止不必要的 leader 选举。异步存储写入(AsynchronousStorageWrites)允许 leader 与 follower 并行落盘,大幅提升吞吐。
MVCC 存储引擎:pkg/storage/mvcc.go 实现了基于 Pebble 的 MVCC 存储层,支持精细的时间戳管理、uncertainty interval 处理(testdata/mvcc_histories/uncertainty_interval*.txt)、lock table(lock_table_iterator.go)和 range tombstone 等高级特性。
竞争格局中的位置
CockroachDB(~32K Star)是 PostgreSQL 兼容阵营中最成功的原生分布式数据库,Cockroach Labs 已在 2024 年上市。它的核心竞争力是:极强的全局一致性保证(serializable 隔离级别为默认)、Kubernetes 原生的部署体验、企业级安全特性。主要对手是 Google Cloud Spanner(商业服务)和 YugabyteDB(开源竞品)。
Vitess — YouTube 验证的 MySQL 水平分片方案
一句话定位
CNCF 毕业项目,MySQL 的水平分片中间件——不改 MySQL 一行代码,在外面加一层智能代理实现分布式。
设计哲学上最精彩的地方
Vitess 最精彩的决策是“不碰数据库内核,只做流量调度”。想象一个快递分拣中心——它不生产货物(不改 MySQL),也不开卡车(不管存储),它只做一件事:把每个包裹(SQL 查询)准确地分拣到正确的卡车上(MySQL 实例)。这种极简策略让 Vitess 能享受 MySQL 的全部生态红利,同时用最小代价实现水平扩展。
源码中 go/vt/vtgate/ 是这个调度中心的核心实现。executor.go(1936 行)是查询执行的入口,它使用自研的 SQL 解析器(go/vt/sqlparser/,包含完整的 sql.y 语法文件)解析用户 SQL。go/vt/vtgate/engine/route.go 定义了 Route 原语——每条查询最终被翻译成若干 Route 操作,每个 Route 知道应该发往哪个 keyspace 的哪些 shard。go/vt/vtgate/vindexes/ 目录下有丰富的分片策略实现:hash.go(哈希分片)、numeric.go(数值范围)、consistent_lookup.go(一致性查找索引)等。
核心技术创新点
VSchema 声明式分片:Vitess 独创了 VSchema(Virtual Schema)概念,用 JSON/protobuf 声明表的分片规则,包含 Vindexes(虚拟索引,即分片函数)和路由规则。这让分片策略与应用代码完全解耦——改分片规则不需要改一行应用代码。
自研 MySQL 协议解析器:go/mysql/ 目录实现了完整的 MySQL 客户端/服务端协议栈(client.go、server.go、query.go),包括认证握手、查询编解码、binlog 事件解析(binlog_event_*.go),VTGate 伪装成一个 MySQL 服务器接受连接。
Gen4 查询规划器:go/vt/vtgate/planbuilder/ 实现了 Vitess 的第四代查询规划器,operators/ 子目录包含丰富的算子(aggregation_pushing.go、hash_join.go、route_planning.go 等),支持 join 下推、subquery 优化和跨 shard 聚合。go/vt/vtgate/semantics/ 提供语义分析层(analyzer.go、binder.go、scoper.go),实现了类似数据库内核的语义绑定和类型推导。
竞争格局中的位置
Vitess(~21K Star)是中间件模式的代表作,YouTube/Google 的大规模验证是其最大背书。它的核心价值在于:零侵入的水平扩展(不改 MySQL)、Kubernetes 原生(CNCF 毕业)、对 MySQL 生态的完美兼容。主要竞争对手是 ProxySQL、ShardingSphere 等中间件方案。Vitess 的独特优势是它的成熟度——经过十余年 YouTube 生产环境的考验。
Citus — PostgreSQL 扩展的极简主义典范
一句话定位
作为 PostgreSQL 原生扩展(extension)运行的分布式查询引擎,不 fork 不魔改,用最小的侵入实现 PG 的水平扩展。
设计哲学上最精彩的地方
Citus 最精彩的决策是“做 PG 的插件而不是 PG 的替代品”。想象你有一个非常好用的手机(PostgreSQL),Citus 不会让你换手机,它只是给你装了一个新 App——这个 App 让你的手机能同时控制多台设备协同工作。你手机原来的所有功能(App、设置、数据)完全不受影响。
源码完美体现了这个理念。整个项目的核心代码在 src/backend/distributed/ 目录下,通过 PostgreSQL 的 hook 机制(shared_library_init.c 是入口点)拦截查询处理的各个环节。planner/distributed_planner.c 通过替换 standard_planner hook 介入查询优化;executor/adaptive_executor.c(5359 行,项目中最复杂的单文件)实现了一个精巧的连接池 + 任务调度系统——它为每个 worker 节点维护一个 WorkerPool,通过 WaitEventSet 异步轮询所有连接的 I/O 状态。
核心技术创新点
五层渐进式查询规划:从 planner/README.md 可以看到,Citus 的分布式查询规划采用了优雅的分层策略:Fast-path Router(单分片快路径)→ Router Planner(协同分片路由)→ Modification Planning(DML 专用)→ Recursive Planning(子查询递归规划)→ Logical Planner(多关系代数树)。每一层都是前一层的回退(fallback),命中即停。
列存引擎作为 Table AM 扩展:src/backend/columnar/ 实现了一个完整的列式存储引擎,通过 PostgreSQL 的 Table Access Method 接口(columnar_tableam.c)注册。columnar_reader.c 和 columnar_writer.c 处理列存的读写,columnar_compression.c 支持压缩。这使得一张表可以在行存和列存之间切换——ALTER TABLE ... USING columnar。
自适应执行器:executor/adaptive_executor.c 的设计极为精巧。它采用 Slow Start 算法动态调整连接池大小(类似 TCP 拥塞控制),通过 ShardCommandExecution → TaskPlacementExecution 两级抽象支持多副本 failover 和引用表的串行写入。
竞争格局中的位置
Citus(~12.5K Star,2019 年被 Microsoft 收购)是 PG 扩展模式的最佳范例。它的核心竞争力是:零 fork 的 PG 兼容性(随 PG 版本自动升级)、最低的学习成本(就是 PG + 几个函数调用)。Microsoft 将其集成到 Azure Database for PostgreSQL,是 Azure 分布式 PG 的核心技术。代码量最小(~1,000 文件),是学习分布式查询规划的最佳入门材料。
YugabyteDB — 双协议兼容的 Spanner 实现
一句话定位
基于 Google Spanner 架构的分布式数据库,底层是 DocDB(RocksDB + Raft),上层同时暴露 YSQL(PostgreSQL 兼容)和 YCQL(Cassandra 兼容)两套 API。
设计哲学上最精彩的地方
YugabyteDB 最精彩的决策是“一个存储引擎,两种语言”。想象一个图书馆的书架系统——底层的书架排列方式(DocDB)是统一的,但你可以选择用中文目录(YSQL)或英文目录(YCQL)来查找书籍。两种目录系统看到的是同一批书,但提供了不同的查找体验。
源码中,src/yb/docdb/ 是这个统一存储引擎的核心。docdb.h 的注释清晰展示了 DocDB 的 KV 映射方式:<document_key> <hybrid_time> -> <doc_type>,每个文档可以有嵌套的子文档结构。src/yb/consensus/raft_consensus.cc 实现了 Raft 共识,src/yb/tablet/ 管理 tablet(数据分片),src/yb/master/ 实现 master 节点负责元数据管理和负载均衡。
而 YSQL 通过 src/yb/yql/pggate/ 桥接到修改过的 PostgreSQL 前端(src/postgres/),YCQL 则通过 src/yb/yql/cql/ 实现 Cassandra Query Language 兼容。
核心技术创新点
DocDB 文档存储引擎:src/yb/docdb/ 实现了一个基于 RocksDB 的文档存储引擎,支持 MVCC(通过 hybrid timestamp)、冲突检测(conflict_resolution.cc)、死锁检测(deadlock_detector.cc)和等待队列(wait_queue.cc)。它的独特之处在于用 KV 编码表达了丰富的文档结构。
Hybrid Logical Clock:YugabyteDB 使用混合逻辑时钟(HLC),结合物理时钟和逻辑计数器,在不需要 GPS/原子钟(Spanner 的 TrueTime)的情况下实现接近全局一致的时间戳。
向量索引支持:src/yb/vector_index/ 和 src/yb/hnsw/ 展示了 YugabyteDB 正在积极拥抱 AI 场景——集成 HNSW(Hierarchical Navigable Small World)向量索引和 usearch 库,支持向量相似度搜索。
竞争格局中的位置
YugabyteDB(~10.5K Star)的独特价值在于双协议兼容——对于同时有关系型和 NoSQL 需求的团队,可以用一个数据库替代 PostgreSQL + Cassandra。它与 CockroachDB 正面竞争 Spanner 开源替代的定位,但代码量更大(C/C++ + Java,~10,000 文件),学习曲线更陡。
OpenTenBase — 腾讯出品的 PG 内核 HTAP 方案
一句话定位
基于 Postgres-XL 架构的分布式 HTAP 数据库,保持 PostgreSQL 完整内核的同时,通过 GTM(全局事务管理器)+ Coordinator-Datanode 架构 + 双存储引擎实现分布式和 HTAP 能力。
设计哲学上最精彩的地方
OpenTenBase 最精彩的决策是“在 PG 内核里做手术而不是在外面包一层”。想象你要把一辆轿车改装成越野车——Citus 的做法是给轿车加一个拖车挂件(extension),Vitess 的做法是在轿车前面放一个导航台(中间件),而 OpenTenBase 的做法是直接打开发动机盖,换更强的引擎、加底盘护甲(内核改造)。这带来了更深层的能力(如分布式 DDL、全局事务),但也意味着更重的维护负担。
源码结构清晰展示了这个设计。src/gtm/ 是全局事务管理器的完整实现——gtm_txn.c(4029 行)处理全局事务 ID 分配和状态管理,gtm_snap.c 管理全局快照,gtm_seq.c 管理全局序列。src/backend/pgxc/ 是核心分布式扩展层——locator/locator.c(2775 行)实现数据分片定位,通过 Locator 结构体的 locatefunc 函数指针支持多种分片策略(哈希、范围、modulo 等);pool/execRemote.c(12835 行,项目中最大的单文件)实现远程查询执行;plan/planner.c 做分布式查询计划生成。
核心技术创新点
GTM 全局事务管理器:src/gtm/main/ 实现了独立进程的全局事务管理器,包含事务管理(gtm_txn.c)、快照管理(gtm_snap.c)、序列管理(gtm_seq.c)、WAL 日志(gtm_xlog.c)和主备复制(replication.c)。GTM 通过 GTM_Transactions 全局结构和 ControlXid 维护全局事务 ID 的分配和追踪。
GTM Proxy 性能优化:src/gtm/proxy/ 实现了 GTM 代理,可以在 Coordinator 本地聚合事务请求后批量发往 GTM,减少网络往返次数——这是应对 GTM 成为性能瓶颈的关键优化。
Shard Map 和分布式定位:src/backend/pgxc/shard/shardmap.c 维护了分片映射表,src/backend/pgxc/locator/locator.c 的 Locator 结构体通过函数指针模式支持可插拔的分片策略。#ifdef __OPENTENBASE__ 条件编译标记清晰标注了 OpenTenBase 对 Postgres-XL 基线的所有增强。
AI 扩展:contrib/opentenbase_ai/ 是一个有趣的扩展,展示了 OpenTenBase 在 AI 方向的探索。contrib/pgvector/ 集成了向量搜索能力。
竞争格局中的位置
OpenTenBase(~2K Star)是腾讯开源的分布式 PG 方案,在腾讯内部(微信支付等)有大规模生产验证。它的独特价值在于:PG 原生内核兼容(不是 extension 而是 fork)+ HTAP 双引擎。在犀牛鸟 2026 的语境下,OpenTenBase 是候选项目,参与贡献的门槛相对较低(C 语言,~3,000 文件),社区相对小意味着 contributor 更容易获得关注。
全景透视:6 个项目的真实关系
架构谱系图
Google Spanner (论文)
/ \
CockroachDB YugabyteDB
(Go, Pebble, (C++, RocksDB,
自研Raft) DocDB, HLC)
|
双协议(YSQL+YCQL)
PostgreSQL 内核 MySQL 内核
/ | \ / \
Citus OpenTenBase YugabyteDB TiDB Vitess
(扩展) (XL fork) (YSQL层) (原生分布式) (中间件代理)
|
TiKV(Rust,Raft)
+TiFlash(列存)
设计取舍矩阵
| 维度 | 改内核(OpenTenBase) | 做扩展(Citus) | 加代理(Vitess) | 从零造(TiDB/CRDB) |
|---|---|---|---|---|
| PG/MySQL 兼容度 | 极高(就是 PG) | 高(PG extension) | 高(代理真实 MySQL) | 中(自研解析器) |
| 分布式事务 | GTM 全局协调 | 2PC + 协调节点 | 应用层负责 | Raft + MVCC |
| 升级成本 | 高(需跟进内核) | 低(随 PG 升级) | 低(MySQL 独立升级) | 无(自主迭代) |
| 架构灵活度 | 中 | 中 | 高 | 极高 |
| HTAP 能力 | ✓(双引擎) | 有限(列存扩展) | ✗ | ✓(TiDB) / 有限(CRDB) |
代码文化差异
- CockroachDB:单仓库、极致的测试文化(TLA+ 形式化验证、data-driven 测试遍布每个模块)、超详细的代码文档(
pkg/raft/doc.go长达 398 行) - TiDB:多仓库生态(tidb + tikv + pd)、Go + Rust 双语言、Cascades 优化器和 Plan Cache 的工程深度令人印象深刻
- Vitess:Go 单仓库、CNCF 社区运营成熟、丰富的端到端测试(
go/vt/vtgate/endtoend/) - Citus:C 语言、代码量最精简、
planner/README.md是开源项目中最好的规划器文档之一 - YugabyteDB:C++ 为主、代码量庞大、积极拥抱 AI(向量索引)
- OpenTenBase:C 语言、大量
#ifdef __OPENTENBASE__标注增量改动、中文文档友好
给犀牛鸟 2026 的核心洞察
1. OpenTenBase 的参与价值
OpenTenBase 的 star 数(~2K)虽然远低于头部项目,但这恰恰意味着社区贡献者少、每个 PR 的可见度高。作为犀牛鸟候选项目,参与者有机会在以下方向做出有影响力的贡献:
- GTM 性能优化:GTM 是已知瓶颈,
src/gtm/main/gtm_txn.c的事务分配路径存在优化空间 - 查询优化器增强:
src/backend/optimizer/util/pgxcship.c的可下推判断逻辑可以更精细 - 列存引擎完善:对标 Citus 的
columnar/实现 - 向量搜索增强:
contrib/pgvector/的集成还处于早期阶段
2. 学习路径建议
先读 Citus 的 planner/README.md(开源世界最好的分布式查询规划器文档),理解分布式查询规划的核心抽象。然后读 CockroachDB 的 pkg/raft/doc.go 和 docs/tla-plus/ 理解共识协议。最后回到 OpenTenBase 的 src/gtm/ 和 src/backend/pgxc/ 理解 Coordinator-Datanode 架构。
3. 赛道趋势
从 6 个项目的最新代码可以观察到三个趋势:
- AI 融合:YugabyteDB(
vector_index/)、OpenTenBase(opentenbase_ai/)、TiDB(向量搜索支持)都在积极集成向量搜索能力 - Cascades 优化器普及:TiDB 的
pkg/planner/cascades/是完整实现,CockroachDB 也使用 Cascades 框架——这正在成为分布式查询优化的标准范式 - 存算分离深化:TiDB 的 TiKV/TiFlash 分离已经成熟,CockroachDB 也在探索 shared storage(
pkg/storage/shared_storage.go)