TiDB分布式数据库架构解析
// 目录 · contents
引言
传统的分库分表方案虽然解决了单机数据库的容量和性能瓶颈,但引入了大量的业务复杂性:跨分片查询、分布式事务、数据迁移等问题让开发和运维成本居高不下。NewSQL数据库的出现正是为了在不牺牲SQL能力的前提下,提供原生的分布式存储和计算能力。TiDB是国内最具代表性的NewSQL数据库,由PingCAP公司开发,兼容MySQL协议,提供水平扩展、强一致性和HTAP能力。
TiDB 整体架构
graph TD
Client[客户端<br/>MySQL协议兼容] --> TiDB1[TiDB Server 1<br/>SQL Layer]
Client --> TiDB2[TiDB Server 2<br/>SQL Layer]
Client --> TiDB3[TiDB Server N<br/>SQL Layer]
TiDB1 --> PD[PD Cluster<br/>Placement Driver<br/>元数据 + 调度]
TiDB2 --> PD
TiDB3 --> PD
TiDB1 --> TiKV1[TiKV Node 1<br/>Region 1, Region 5]
TiDB1 --> TiKV2[TiKV Node 2<br/>Region 2, Region 6]
TiDB2 --> TiKV3[TiKV Node 3<br/>Region 3, Region 7]
TiDB3 --> TiKV4[TiKV Node N<br/>Region 4, Region 8]
TiDB1 --> TiFlash1[TiFlash Node<br/>列式存储副本]
PD --> TiKV1
PD --> TiKV2
PD --> TiKV3
PD --> TiKV4
TiKV1 <-->|Raft| TiKV2
TiKV2 <-->|Raft| TiKV3
TiKV3 <-->|Raft| TiKV4
TiDB的架构由三个核心组件组成:
| 组件 | 角色 | 特点 |
|---|---|---|
| TiDB Server | SQL计算层 | 无状态,水平扩展,MySQL协议兼容 |
| TiKV | 分布式存储层 | 有状态,KV存储,Raft复制 |
| PD (Placement Driver) | 调度中心 | 元数据管理,TSO时钟,负载均衡 |
TiDB Server:SQL 计算层
功能职责
TiDB Server是无状态的SQL计算节点,负责接收SQL请求、解析优化、生成执行计划并从TiKV获取数据。
flowchart TD
A[Client SQL] --> B[Protocol Layer<br/>MySQL协议解析]
B --> C[Parser<br/>SQL解析为AST]
C --> D[Planner<br/>逻辑优化 + 物理优化]
D --> E[Executor<br/>火山模型/向量化执行]
E --> F{DistSQL API}
F --> G[TiKV Coprocessor<br/>下推计算]
F --> H[TiFlash<br/>OLAP查询]
SQL 兼容性
1 | |
计算下推
TiDB会将部分计算下推到TiKV的Coprocessor执行,减少网络传输:
sequenceDiagram
participant TiDB as TiDB Server
participant TiKV1 as TiKV Region 1
participant TiKV2 as TiKV Region 2
participant TiKV3 as TiKV Region 3
Note over TiDB: SELECT COUNT(*) FROM orders WHERE status='paid'
TiDB->>TiKV1: Coprocessor请求<br/>过滤 status='paid' 并 COUNT
TiDB->>TiKV2: Coprocessor请求
TiDB->>TiKV3: Coprocessor请求
TiKV1->>TiDB: count=1500
TiKV2->>TiDB: count=2300
TiKV3->>TiDB: count=1800
Note over TiDB: 汇总: 1500+2300+1800=5600
TiDB->>TiDB: 返回 COUNT=5600
可下推的操作: - 过滤条件(WHERE) - 聚合函数(COUNT, SUM, AVG, MIN, MAX) - TopN(ORDER BY + LIMIT) - 表达式计算
TiKV:分布式存储层
Region 分片
TiKV将整个Key-Value空间按Key的范围划分为多个Region,每个Region默认大小96MB。
graph LR
subgraph "Key Space"
R1["Region 1<br/>[Key_a, Key_d)"]
R2["Region 2<br/>[Key_d, Key_h)"]
R3["Region 3<br/>[Key_h, Key_m)"]
R4["Region 4<br/>[Key_m, Key_z)"]
end
subgraph "TiKV Nodes"
N1[Node 1]
N2[Node 2]
N3[Node 3]
end
R1 -->|Leader| N1
R1 -->|Follower| N2
R1 -->|Follower| N3
R2 -->|Leader| N2
R3 -->|Leader| N3
R4 -->|Leader| N1
数据编码
TiDB将SQL表数据编码为KV对存储在TiKV中:
1 | |
Raft 复制
每个Region使用Raft协议在多个TiKV节点间复制,保证数据的强一致性。
sequenceDiagram
participant C as TiDB
participant L as Leader
participant F1 as Follower 1
participant F2 as Follower 2
C->>L: Write Request
L->>L: 写入Raft Log
L->>F1: Append Entries
L->>F2: Append Entries
F1->>L: ACK
F2->>L: ACK
Note over L: 过半数确认(Quorum)<br/>提交日志
L->>L: Apply to RocksDB
L->>C: Write Success
Note over F1, F2: 异步Apply to RocksDB
Raft的关键特性: - Leader选举:每个Region的Raft Group选举一个Leader,所有读写请求由Leader处理 - 日志复制:写入必须在过半数节点(Quorum)确认后才提交 - Leader Transfer:PD可以调度Leader在节点间迁移,实现负载均衡
Multi-Raft
TiKV采用Multi-Raft架构,每个Region是一个独立的Raft Group:
graph TD
subgraph "Node 1"
A1["Region 1 (Leader)"]
A2["Region 3 (Follower)"]
A3["Region 5 (Leader)"]
end
subgraph "Node 2"
B1["Region 1 (Follower)"]
B2["Region 3 (Leader)"]
B3["Region 5 (Follower)"]
end
subgraph "Node 3"
C1["Region 1 (Follower)"]
C2["Region 3 (Follower)"]
C3["Region 5 (Follower)"]
end
A1 <-->|Raft| B1
A1 <-->|Raft| C1
A2 <-->|Raft| B2
A2 <-->|Raft| C2
A3 <-->|Raft| B3
A3 <-->|Raft| C3
PD:调度中心
PD 的核心职责
graph TD
PD[PD Cluster<br/>基于etcd] --> F1[TSO时钟分配<br/>全局唯一递增时间戳]
PD --> F2[元数据存储<br/>Region -> Store映射]
PD --> F3[Region调度<br/>负载均衡 热点打散]
PD --> F4[Label调度<br/>跨机房/跨AZ部署]
TSO(Timestamp Oracle)
PD负责分配全局唯一的时间戳(TSO),用于MVCC和事务排序:
1 | |
调度策略
flowchart TD
A[PD调度器] --> B[Region均衡调度]
A --> C[Leader均衡调度]
A --> D[热点调度]
A --> E[Region分裂/合并]
B --> B1["当节点间Region数量差异过大<br/>迁移Region到负载低的节点"]
C --> C1["当节点间Leader数量差异过大<br/>Transfer Leader到负载低的节点"]
D --> D1["检测热点Region<br/>分裂热点Region<br/>调度Leader到不同节点"]
E --> E1["Region > 96MB: 分裂为两个Region<br/>Region < 20MB且相邻: 合并"]
分布式事务
TiDB实现了Percolator模型的分布式事务,支持Snapshot Isolation。
事务执行流程
sequenceDiagram
participant C as TiDB
participant PD as PD (TSO)
participant TiKV as TiKV
Note over C: BEGIN TRANSACTION
C->>PD: 获取 start_ts
PD->>C: start_ts = 100
Note over C: 执行SQL读写操作...
C->>TiKV: 读取数据 (snapshot at ts=100)
TiKV->>C: 返回数据
C->>C: 在内存缓存写入
Note over C: COMMIT
Note over C, TiKV: Phase 1: Prewrite
C->>TiKV: Prewrite (选择一个key作为Primary)
TiKV->>TiKV: 检查冲突, 写入Lock + Data
TiKV->>C: Prewrite OK
C->>PD: 获取 commit_ts
PD->>C: commit_ts = 105
Note over C, TiKV: Phase 2: Commit
C->>TiKV: Commit Primary Key (commit_ts=105)
TiKV->>TiKV: 清除Lock, 写入Commit记录
TiKV->>C: Commit OK
Note over C: 事务成功, 异步清理Secondary Locks
C->>TiKV: 异步Commit Secondary Keys
乐观事务 vs 悲观事务
1 | |
| 维度 | 悲观事务 | 乐观事务 |
|---|---|---|
| 冲突检测时机 | DML执行时 | Commit时 |
| 冲突处理 | 等待锁释放 | 事务重试 |
| 适用场景 | 高冲突(默认推荐) | 低冲突,高吞吐 |
| MySQL兼容性 | 行为一致 | 需要应用层重试逻辑 |
HTAP 与 TiFlash
HTAP 架构
TiDB通过TiFlash列式存储引擎实现了HTAP(混合事务分析处理)能力。
graph TD
subgraph "OLTP Path"
TiDB1[TiDB] --> TiKV1[TiKV<br/>行存储<br/>事务处理]
end
subgraph "OLAP Path"
TiDB2[TiDB] --> TiFlash1[TiFlash<br/>列存储<br/>分析查询]
end
TiKV1 -->|Raft Learner<br/>异步复制| TiFlash1
subgraph "智能路由"
TiDB3[TiDB优化器] --> R{查询类型?}
R -->|点查/事务| TiKV1
R -->|分析/聚合| TiFlash1
R -->|混合| TiKV1
R -->|混合| TiFlash1
end
TiFlash 配置
1 | |
TiFlash vs TiKV 对比
| 维度 | TiKV | TiFlash |
|---|---|---|
| 存储格式 | 行存(RocksDB) | 列存(Delta Tree) |
| 适用查询 | 点查、小范围查询 | 聚合、扫描、分析 |
| 数据一致性 | Raft Leader读 | Raft Learner,强一致读 |
| 压缩率 | 一般 | 高(列式压缩) |
TiDB vs CockroachDB
graph LR
subgraph "TiDB"
TA[MySQL协议兼容] --> TB[TiKV: Rust实现]
TB --> TC[RocksDB存储引擎]
TA --> TD[Percolator事务模型]
TA --> TE[TiFlash HTAP]
end
subgraph "CockroachDB"
CA[PostgreSQL协议兼容] --> CB[Go实现<br/>计算存储一体]
CB --> CC[Pebble存储引擎]
CA --> CD[Serializable隔离级别]
CA --> CE[原生多区域部署]
end
| 维度 | TiDB | CockroachDB |
|---|---|---|
| 协议兼容 | MySQL | PostgreSQL |
| 实现语言 | Go (TiDB) + Rust (TiKV) | Go |
| 架构 | 计算存储分离 | 计算存储一体 |
| 默认隔离级别 | Snapshot Isolation | Serializable |
| HTAP | TiFlash列存 | 无专门列存 |
| 多区域 | TiDB 6.0+ Placement Rules | 原生支持 |
| 开源协议 | Apache 2.0 | BSL (核心功能) |
| 生态 | 国内生态更好 | 海外生态更好 |
运维与监控
关键监控指标
1 | |
扩缩容操作
1 | |
总结
TiDB作为NewSQL数据库的代表,在很多场景下可以替代传统的分库分表方案:
- 架构设计精巧:TiDB(无状态SQL层)+ TiKV(Raft分布式存储)+ PD(智能调度)三层分离
- MySQL高度兼容:大部分MySQL应用可以低成本迁移
- Raft保证强一致性:数据不会丢失,读取一致
- 分布式事务支持悲观和乐观两种模式,默认悲观事务与MySQL行为一致
- HTAP能力:TiFlash列存引擎让同一份数据同时服务于OLTP和OLAP
- 自动运维:Region自动分裂/合并/调度,扩缩容对业务透明
- 但也有局限性:单行事务延迟高于单机MySQL(网络RTT),不适合延迟要求极高的场景;运维复杂度高于单机数据库