TiKV存储引擎 #

一、TiKV概述 #

1.1 核心定位 #

TiKV 是 TiDB 的存储层,提供分布式、事务性的 Key-Value 存储服务。

text
TiKV 核心特性
├── 分布式存储
│   ├── 数据分片 (Region)
│   ├── 多副本复制
│   └── 水平扩展
│
├── 事务支持
│   ├── ACID 事务
│   ├── 分布式事务
│   └── MVCC
│
├── 高可用
│   ├── Raft 一致性协议
│   ├── 自动故障恢复
│   └── 强一致性
│
└── 高性能
    ├── RocksDB 存储
    ├── LSM-Tree 结构
    └── 批量写入优化

1.2 架构层次 #

text
TiKV 架构层次
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   ┌─────────────────────────────────────────────────────┐   │
│   │                   TiKV Server                       │   │
│   │                                                     │   │
│   │   ┌─────────────────────────────────────────────┐   │   │
│   │   │              gRPC Server                    │   │   │
│   │   │         (对外服务接口)                      │   │   │
│   │   └─────────────────────────────────────────────┘   │   │
│   │                        │                            │   │
│   │   ┌─────────────────────────────────────────────┐   │   │
│   │   │              Storage Layer                  │   │   │
│   │   │                                             │   │   │
│   │   │   ┌─────────────────────────────────────┐   │   │   │
│   │   │   │         Transaction Manager         │   │   │   │
│   │   │   │    (事务管理、MVCC、锁管理)         │   │   │   │
│   │   │   └─────────────────────────────────────┘   │   │   │
│   │   │                                             │   │   │
│   │   │   ┌─────────────────────────────────────┐   │   │   │
│   │   │   │           Raft Layer                │   │   │   │
│   │   │   │    (共识协议、日志复制)             │   │   │   │
│   │   │   └─────────────────────────────────────┘   │   │   │
│   │   │                                             │   │   │
│   │   │   ┌─────────────────────────────────────┐   │   │   │
│   │   │   │         Region Manager              │   │   │   │
│   │   │   │    (Region 分裂、合并、调度)        │   │   │   │
│   │   │   └─────────────────────────────────────┘   │   │   │
│   │   │                                             │   │   │
│   │   └─────────────────────────────────────────────┘   │   │
│   │                        │                            │   │
│   │   ┌─────────────────────────────────────────────┐   │   │
│   │   │            RocksDB Engine                   │   │   │
│   │   │         (底层存储引擎)                      │   │   │
│   │   └─────────────────────────────────────────────┘   │   │
│   │                                                     │   │
│   └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

二、Key-Value模型 #

2.1 数据编码 #

表数据编码

text
表数据 Key 编码
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   SQL 表:                                                   │
│   CREATE TABLE users (                                      │
│       id BIGINT PRIMARY KEY,                                │
│       name VARCHAR(100),                                    │
│       age INT                                               │
│   );                                                        │
│                                                             │
│   Key 编码规则:                                             │
│   ┌─────────────────────────────────────────────────────┐   │
│   │                                                     │   │
│   │   行数据 Key:                                       │   │
│   │   t{table_id}_r{row_id}                            │   │
│   │                                                     │   │
│   │   示例 (table_id = 10):                            │   │
│   │   id=1 → t10_r1                                     │   │
│   │   id=2 → t10_r2                                     │   │
│   │   id=3 → t10_r3                                     │   │
│   │                                                     │   │
│   │   Value:                                            │   │
│   │   [name, age] 编码后的二进制数据                   │   │
│   │                                                     │   │
│   └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

索引编码

text
索引 Key 编码
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   索引类型:                                                 │
│                                                             │
│   1. 唯一索引                                               │
│   ┌─────────────────────────────────────────────────────┐   │
│   │                                                     │   │
│   │   Key: t{table_id}_i{index_id}{index_value}        │   │
│   │   Value: {row_id}                                  │   │
│   │                                                     │   │
│   │   示例: CREATE UNIQUE INDEX idx_email ON users(email)│   │
│   │   email='alice@test.com' → t10_i1'alice@test.com'  │   │
│   │   Value: 1 (row_id)                                │   │
│   │                                                     │   │
│   └─────────────────────────────────────────────────────┘   │
│                                                             │
│   2. 非唯一索引                                             │
│   ┌─────────────────────────────────────────────────────┐   │
│   │                                                     │   │
│   │   Key: t{table_id}_i{index_id}{index_value}{row_id}│   │
│   │   Value: null                                      │   │
│   │                                                     │   │
│   │   示例: CREATE INDEX idx_age ON users(age)         │   │
│   │   age=25, row_id=1 → t10_i2'25'1                   │   │
│   │   age=25, row_id=2 → t10_i2'25'2                   │   │
│   │                                                     │   │
│   └─────────────────────────────────────────────────────┘   │
│                                                             │
│   3. 复合索引                                               │
│   ┌─────────────────────────────────────────────────────┐   │
│   │                                                     │   │
│   │   Key: t{table_id}_i{index_id}{col1}{col2}...      │   │
│   │                                                     │   │
│   │   示例: CREATE INDEX idx_name_age ON users(name,age)│   │
│   │   name='Alice', age=25 → t10_i3'Alice'25           │   │
│   │                                                     │   │
│   └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

2.2 有序性保证 #

text
Key 有序性
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   Key 编码保证有序性:                                       │
│                                                             │
│   ┌─────────────────────────────────────────────────────┐   │
│   │                                                     │   │
│   │   表数据连续存储:                                   │   │
│   │   t10_r1 → t10_r2 → t10_r3 → ... → t10_rn         │   │
│   │                                                     │   │
│   │   索引数据连续存储:                                 │   │
│   │   t10_i1'Alice' → t10_i1'Bob' → t10_i1'Carol'     │   │
│   │                                                     │   │
│   │   不同表数据分开:                                   │   │
│   │   t10_... (表10的数据)                             │   │
│   │   t11_... (表11的数据)                             │   │
│   │                                                     │   │
│   └─────────────────────────────────────────────────────┘   │
│                                                             │
│   优势:                                                     │
│   - 范围查询高效                                           │
│   - 顺序扫描高效                                           │
│   - 前缀匹配高效                                           │
│                                                             │
└─────────────────────────────────────────────────────────────┘

三、Region管理 #

3.1 Region概念 #

text
Region 分片机制
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   整个 Key 空间                                             │
│   ┌─────────────────────────────────────────────────────┐   │
│   │ [minKey .............................. maxKey]      │   │
│   └─────────────────────────────────────────────────────┘   │
│                          │                                  │
│                          ▼                                  │
│   按 Range 切分为多个 Region                                │
│   ┌──────────────────────────────────────────────────────┐  │
│   │                                                      │  │
│   │  Region 1    Region 2    Region 3    Region 4       │  │
│   │  [a, e)      [e, k)      [k, q)      [q, z]         │  │
│   │  96MB        96MB        96MB        96MB           │  │
│   │                                                      │  │
│   └──────────────────────────────────────────────────────┘  │
│                                                             │
│   Region 属性:                                              │
│   ├── Region ID: 全局唯一标识                              │
│   ├── Start Key: 起始 Key (包含)                           │
│   ├── End Key: 结束 Key (不包含)                           │
│   ├── Region Epoch: 版本号 (用于分裂/合并检测)             │
│   └── Peers: 副本列表                                      │
│                                                             │
└─────────────────────────────────────────────────────────────┘

3.2 Region分裂 #

text
Region 分裂过程
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   分裂前:                                                   │
│   ┌─────────────────────────────────────────────────────┐   │
│   │              Region 1                               │   │
│   │              [a, z]                                 │   │
│   │              大小: 200MB                            │   │
│   │              Leader: TiKV 1                         │   │
│   └─────────────────────────────────────────────────────┘   │
│                          │                                  │
│                          ▼                                  │
│   触发分裂 (大小超过阈值 144MB)                             │
│                          │                                  │
│                          ▼                                  │
│   分裂后:                                                   │
│   ┌─────────────────────┐   ┌─────────────────────┐       │
│   │     Region 1        │   │     Region 2        │       │
│   │     [a, m)          │   │     [m, z]          │       │
│   │     大小: 100MB     │   │     大小: 100MB     │       │
│   │     Leader: TiKV 1  │   │     Leader: TiKV 1  │       │
│   └─────────────────────┘   └─────────────────────┘       │
│                                                             │
│   分裂流程:                                                 │
│   1. PD 发起分裂命令或 TiKV 自动触发                       │
│   2. Leader 选择分裂点                                     │
│   3. 创建新 Region 元数据                                  │
│   4. 更新 PD 元数据                                        │
│   5. 后台异步迁移数据                                      │
│                                                             │
└─────────────────────────────────────────────────────────────┘

3.3 Region合并 #

text
Region 合并过程
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   合并前:                                                   │
│   ┌─────────────┐   ┌─────────────┐                        │
│   │  Region 1   │   │  Region 2   │                        │
│   │  [a, f)     │   │  [f, k)     │                        │
│   │  大小: 10MB │   │  大小: 15MB │                        │
│   └─────────────┘   └─────────────┘                        │
│                          │                                  │
│                          ▼                                  │
│   触发合并 (相邻 Region 都小于 20MB)                        │
│                          │                                  │
│                          ▼                                  │
│   合并后:                                                   │
│   ┌─────────────────────────────────────────────────────┐   │
│   │              Region 1                               │   │
│   │              [a, k)                                 │   │
│   │              大小: 25MB                             │   │
│   └─────────────────────────────────────────────────────┘   │
│                                                             │
│   合并条件:                                                 │
│   - 两个 Region 相邻                                       │
│   - 两个 Region 都小于阈值                                 │
│   - 没有进行中的分裂/合并                                  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

3.4 Region调度 #

text
Region 调度类型
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   1. Balance Leader                                         │
│   ┌─────────────────────────────────────────────────────┐   │
│   │                                                     │   │
│   │   目的: 均衡各节点的 Leader 数量                   │   │
│   │   方式: 转移 Leader 到其他副本                     │   │
│   │                                                     │   │
│   │   TiKV 1 (80 Leaders) ──转移──► TiKV 2 (40 Leaders)│   │
│   │                                                     │   │
│   └─────────────────────────────────────────────────────┘   │
│                                                             │
│   2. Balance Region                                         │
│   ┌─────────────────────────────────────────────────────┐   │
│   │                                                     │   │
│   │   目的: 均衡各节点的存储容量                       │   │
│   │   方式: 迁移 Region 副本                           │   │
│   │                                                     │   │
│   │   TiKV 1 (80% 容量) ──迁移──► TiKV 2 (40% 容量)    │   │
│   │                                                     │   │
│   └─────────────────────────────────────────────────────┘   │
│                                                             │
│   3. Hot Region                                             │
│   ┌─────────────────────────────────────────────────────┐   │
│   │                                                     │   │
│   │   目的: 分散热点 Region                            │   │
│   │   方式: 打散热点 Region 的副本                     │   │
│   │                                                     │   │
│   │   热点 TiKV 1 ──打散──► TiKV 2, TiKV 3             │   │
│   │                                                     │   │
│   └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

四、Raft一致性协议 #

4.1 Raft基础 #

text
Raft 共识算法
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   Raft 角色:                                                │
│                                                             │
│   ┌─────────────────────────────────────────────────────┐   │
│   │                                                     │   │
│   │   Leader:                                           │   │
│   │   ├── 处理所有客户端请求                           │   │
│   │   ├── 日志复制到 Follower                          │   │
│   │   └── 心跳维护领导权                               │   │
│   │                                                     │   │
│   │   Follower:                                         │   │
│   │   ├── 接收 Leader 日志                             │   │
│   │   ├── 响应心跳                                     │   │
│   │   └── 参与选举投票                                 │   │
│   │                                                     │   │
│   │   Candidate:                                        │   │
│   │   ├── 发起选举                                     │   │
│   │   └── 争取多数票                                   │   │
│   │                                                     │   │
│   └─────────────────────────────────────────────────────┘   │
│                                                             │
│   多数派原则:                                               │
│   - 写入需要多数派确认                                     │
│   - 选举需要多数派投票                                     │
│   - 容忍少数节点故障                                       │
│                                                             │
└─────────────────────────────────────────────────────────────┘

4.2 Multi-Raft #

text
Multi-Raft 架构
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   每个 Region 一个 Raft Group:                              │
│                                                             │
│   ┌─────────────────────────────────────────────────────┐   │
│   │                                                     │   │
│   │   Region 1 Raft Group                              │   │
│   │   ┌─────────┐  ┌─────────┐  ┌─────────┐           │   │
│   │   │ Leader  │  │Follower │  │Follower │           │   │
│   │   │ TiKV 1  │  │ TiKV 2  │  │ TiKV 3  │           │   │
│   │   └─────────┘  └─────────┘  └─────────┘           │   │
│   │                                                     │   │
│   └─────────────────────────────────────────────────────┘   │
│                                                             │
│   ┌─────────────────────────────────────────────────────┐   │
│   │                                                     │   │
│   │   Region 2 Raft Group                              │   │
│   │   ┌─────────┐  ┌─────────┐  ┌─────────┐           │   │
│   │   │Follower │  │ Leader  │  │Follower │           │   │
│   │   │ TiKV 1  │  │ TiKV 2  │  │ TiKV 3  │           │   │
│   │   └─────────┘  └─────────┘  └─────────┘           │   │
│   │                                                     │   │
│   └─────────────────────────────────────────────────────┘   │
│                                                             │
│   ┌─────────────────────────────────────────────────────┐   │
│   │                                                     │   │
│   │   Region 3 Raft Group                              │   │
│   │   ┌─────────┐  ┌─────────┐  ┌─────────┐           │   │
│   │   │Follower │  │Follower │  │ Leader  │           │   │
│   │   │ TiKV 1  │  │ TiKV 2  │  │ TiKV 3  │           │   │
│   │   └─────────┘  └─────────┘  └─────────┘           │   │
│   │                                                     │   │
│   └─────────────────────────────────────────────────────┘   │
│                                                             │
│   优势:                                                     │
│   - 每个 Region 独立 Raft                                  │
│   - 避免单 Raft 组性能瓶颈                                 │
│   - 支持大规模数据                                         │
│                                                             │
└─────────────────────────────────────────────────────────────┘

4.3 日志复制 #

text
Raft 日志复制流程
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   写入请求流程:                                             │
│                                                             │
│   Client                                                    │
│     │                                                       │
│     │ 1. 写请求                                             │
│     ▼                                                       │
│   ┌─────────────────────────────────────────────────────┐   │
│   │              Leader (TiKV 1)                        │   │
│   │                                                     │   │
│   │   2. 追加日志到本地                                 │   │
│   │   ┌─────────────────────────────────────────────┐   │   │
│   │   │ Index: 1  2  3  4  5                        │   │   │
│   │   │ Term:  1  1  1  1  1                        │   │   │
│   │   │ Log:   A  B  C  D  E (新日志)               │   │   │
│   │   └─────────────────────────────────────────────┘   │   │
│   │                                                     │   │
│   │   3. 并行发送 AppendEntries 到 Follower            │   │
│   │                                                     │   │
│   └─────────────────────────────────────────────────────┘   │
│     │                     │                                 │
│     │                     │                                 │
│     ▼                     ▼                                 │
│   ┌─────────────┐   ┌─────────────┐                        │
│   │  Follower   │   │  Follower   │                        │
│   │  (TiKV 2)   │   │  (TiKV 3)   │                        │
│   │             │   │             │                        │
│   │ 4. 追加日志 │   │ 4. 追加日志 │                        │
│   │ 5. 返回确认 │   │ 5. 返回确认 │                        │
│   └─────────────┘   └─────────────┘                        │
│     │                     │                                 │
│     └──────────┬──────────┘                                 │
│                │                                            │
│                ▼                                            │
│   ┌─────────────────────────────────────────────────────┐   │
│   │              Leader (TiKV 1)                        │   │
│   │                                                     │   │
│   │   6. 收到多数派确认 (2/3)                           │   │
│   │   7. 提交日志 (commit_index = 5)                    │   │
│   │   8. 应用到状态机                                   │   │
│   │   9. 返回客户端成功                                 │   │
│   │                                                     │   │
│   └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

4.4 Leader选举 #

text
Leader 选举过程
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   场景: Leader 故障                                         │
│                                                             │
│   1. Follower 超时未收到心跳                               │
│   ┌─────────────────────────────────────────────────────┐   │
│   │                                                     │   │
│   │   Follower (TiKV 2)                                 │   │
│   │   - election_timeout 到期                          │   │
│   │   - 转为 Candidate                                 │   │
│   │   - term++                                         │   │
│   │   - 投自己一票                                     │   │
│   │                                                     │   │
│   └─────────────────────────────────────────────────────┘   │
│                          │                                  │
│                          ▼                                  │
│   2. 发送 RequestVote 给其他节点                           │
│   ┌─────────────────────────────────────────────────────┐   │
│   │                                                     │   │
│   │   Candidate (TiKV 2)                                │   │
│   │        │                                            │   │
│   │        ├── RequestVote ──► TiKV 1                   │   │
│   │        │                                            │   │
│   │        └── RequestVote ──► TiKV 3                   │   │
│   │                                                     │   │
│   └─────────────────────────────────────────────────────┘   │
│                          │                                  │
│                          ▼                                  │
│   3. 收集投票                                               │
│   ┌─────────────────────────────────────────────────────┐   │
│   │                                                     │   │
│   │   TiKV 1: 投票给 TiKV 2                            │   │
│   │   TiKV 2: 投票给自己                               │   │
│   │   TiKV 3: 投票给 TiKV 2                            │   │
│   │                                                     │   │
│   │   结果: 3/3 票,多数派通过                         │   │
│   │                                                     │   │
│   └─────────────────────────────────────────────────────┘   │
│                          │                                  │
│                          ▼                                  │
│   4. 成为新 Leader                                         │
│   ┌─────────────────────────────────────────────────────┐   │
│   │                                                     │   │
│   │   TiKV 2 成为新 Leader                             │   │
│   │   - 立即发送心跳                                   │   │
│   │   - 开始处理请求                                   │   │
│   │                                                     │   │
│   └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

五、MVCC多版本控制 #

5.1 MVCC原理 #

text
MVCC 多版本并发控制
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   Key-Value 扩展为 Key-Version-Value:                      │
│                                                             │
│   ┌─────────────────────────────────────────────────────┐   │
│   │                                                     │   │
│   │   传统 KV:                                          │   │
│   │   Key → Value                                       │   │
│   │                                                     │   │
│   │   MVCC:                                             │   │
│   │   Key + commit_ts → Value                          │   │
│   │                                                     │   │
│   │   示例:                                             │   │
│   │   t10_r1_100 → [Alice, 25]    (ts=100 时写入)     │   │
│   │   t10_r1_200 → [Alice, 26]    (ts=200 时更新)     │   │
│   │   t10_r1_300 → [Bob, 26]      (ts=300 时更新)     │   │
│   │                                                     │   │
│   └─────────────────────────────────────────────────────┘   │
│                                                             │
│   版本可见性:                                               │
│   - 读取时指定 start_ts                                    │
│   - 只能看到 commit_ts < start_ts 的版本                   │
│   - 实现快照隔离                                           │
│                                                             │
└─────────────────────────────────────────────────────────────┘

5.2 数据版本示例 #

text
数据版本演变
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   操作序列:                                                 │
│                                                             │
│   T1 (ts=100): INSERT INTO users VALUES (1, 'Alice', 25)   │
│   T2 (ts=200): UPDATE users SET age=26 WHERE id=1          │
│   T3 (ts=300): UPDATE users SET name='Bob' WHERE id=1      │
│   T4 (ts=400): DELETE FROM users WHERE id=1                │
│                                                             │
│   存储结果:                                                 │
│   ┌─────────────────────────────────────────────────────┐   │
│   │                                                     │   │
│   │   Key              │ commit_ts │ Value   │ Type    │   │
│   │   ─────────────────┼───────────┼─────────┼─────────│   │
│   │   t10_r1_100       │ 100       │ [Alice, │ Put     │   │
│   │                    │           │  25]    │         │   │
│   │   t10_r1_200       │ 200       │ [Alice, │ Put     │   │
│   │                    │           │  26]    │         │   │
│   │   t10_r1_300       │ 300       │ [Bob,   │ Put     │   │
│   │                    │           │  26]    │         │   │
│   │   t10_r1_400       │ 400       │ -       │ Delete  │   │
│   │                                                     │   │
│   └─────────────────────────────────────────────────────┘   │
│                                                             │
│   读取示例:                                                 │
│   - ts=150 读取 → [Alice, 25]                              │
│   - ts=250 读取 → [Alice, 26]                              │
│   - ts=350 读取 → [Bob, 26]                                │
│   - ts=450 读取 → 空 (已删除)                              │
│                                                             │
└─────────────────────────────────────────────────────────────┘

5.3 版本回收 #

text
MVCC 垃圾回收
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   问题: 旧版本数据持续累积                                 │
│                                                             │
│   解决: GC (Garbage Collection)                            │
│                                                             │
│   ┌─────────────────────────────────────────────────────┐   │
│   │                                                     │   │
│   │   GC 流程:                                          │   │
│   │                                                     │   │
│   │   1. 确定 safe_point                                │   │
│   │      - safe_point 之前的版本可以删除               │   │
│   │      - 由 PD 计算                                   │   │
│   │                                                     │   │
│   │   2. 扫描所有 Key                                   │   │
│   │      - 找到 commit_ts < safe_point 的版本          │   │
│   │                                                     │   │
│   │   3. 删除旧版本                                     │   │
│   │      - 保留每个 Key 最新版本                       │   │
│   │      - 删除其他旧版本                               │   │
│   │                                                     │   │
│   └─────────────────────────────────────────────────────┘   │
│                                                             │
│   配置:                                                     │
│   tikv_gc_life_time = "10m"  # 保留10分钟内的版本          │
│                                                             │
└─────────────────────────────────────────────────────────────┘

六、事务模型 #

6.1 事务类型 #

text
TiKV 事务类型
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   1. 悲观事务                                               │
│   ┌─────────────────────────────────────────────────────┐   │
│   │                                                     │   │
│   │   特点:                                             │   │
│   │   - 修改前先加锁                                   │   │
│   │   - 避免写写冲突                                   │   │
│   │   - 适合冲突多的场景                               │   │
│   │                                                     │   │
│   │   流程:                                             │   │
│   │   BEGIN → SELECT FOR UPDATE → UPDATE → COMMIT      │   │
│   │          (加锁)                                    │   │
│   │                                                     │   │
│   └─────────────────────────────────────────────────────┘   │
│                                                             │
│   2. 乐观事务                                               │
│   ┌─────────────────────────────────────────────────────┐   │
│   │                                                     │   │
│   │   特点:                                             │   │
│   │   - 提交时检测冲突                                 │   │
│   │   - 冲突时回滚重试                                 │   │
│   │   - 适合冲突少的场景                               │   │
│   │                                                     │   │
│   │   流程:                                             │   │
│   │   BEGIN → SELECT → UPDATE → COMMIT                 │   │
│   │                              (检测冲突)            │   │
│   │                                                     │   │
│   └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

6.2 事务流程 #

text
乐观事务提交流程
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   阶段1: 获取 start_ts                                     │
│   ┌─────────────────────────────────────────────────────┐   │
│   │                                                     │   │
│   │   TiDB Server ──请求──► PD                         │   │
│   │                     ◄──start_ts=100──              │   │
│   │                                                     │   │
│   └─────────────────────────────────────────────────────┘   │
│                          │                                  │
│                          ▼                                  │
│   阶段2: 读取数据                                           │
│   ┌─────────────────────────────────────────────────────┐   │
│   │                                                     │   │
│   │   TiDB Server ──读取──► TiKV                       │   │
│   │   (start_ts=100)                                    │   │
│   │                                                     │   │
│   └─────────────────────────────────────────────────────┘   │
│                          │                                  │
│                          ▼                                  │
│   阶段3: 执行修改 (本地缓存)                               │
│   ┌─────────────────────────────────────────────────────┐   │
│   │                                                     │   │
│   │   TiDB Server 本地缓存修改                         │   │
│   │   不写入 TiKV                                      │   │
│   │                                                     │   │
│   └─────────────────────────────────────────────────────┘   │
│                          │                                  │
│                          ▼                                  │
│   阶段4: Prewrite (两阶段提交第一阶段)                     │
│   ┌─────────────────────────────────────────────────────┐   │
│   │                                                     │   │
│   │   对每个修改的 Key:                                 │   │
│   │   1. 检查是否有冲突 (其他事务已提交)               │   │
│   │   2. 写入锁 (primary lock 或 secondary lock)       │   │
│   │   3. 写入数据 (start_ts 版本)                      │   │
│   │                                                     │   │
│   └─────────────────────────────────────────────────────┘   │
│                          │                                  │
│                          ▼                                  │
│   阶段5: 获取 commit_ts                                    │
│   ┌─────────────────────────────────────────────────────┐   │
│   │                                                     │   │
│   │   TiDB Server ──请求──► PD                         │   │
│   │                     ◄──commit_ts=110──             │   │
│   │                                                     │   │
│   └─────────────────────────────────────────────────────┘   │
│                          │                                  │
│                          ▼                                  │
│   阶段6: Commit (两阶段提交第二阶段)                       │
│   ┌─────────────────────────────────────────────────────┐   │
│   │                                                     │   │
│   │   1. 提交 Primary Key                              │   │
│   │      - 写入 commit_ts                              │   │
│   │      - 清除锁                                      │   │
│   │                                                     │   │
│   │   2. 异步提交 Secondary Keys                       │   │
│   │      - 可以延迟处理                                │   │
│   │                                                     │   │
│   └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

七、RocksDB存储 #

7.1 RocksDB架构 #

text
RocksDB 存储架构
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   ┌─────────────────────────────────────────────────────┐   │
│   │                 RocksDB                             │   │
│   │                                                     │   │
│   │   写入流程:                                         │   │
│   │                                                     │   │
│   │   ┌─────────┐                                       │   │
│   │   │  Write  │  1. 写入 WAL                         │   │
│   │   │ Request │     (预写日志)                       │   │
│   │   └────┬────┘                                       │   │
│   │        │                                            │   │
│   │        ▼                                            │   │
│   │   ┌─────────┐                                       │   │
│   │   │ MemTable│  2. 写入内存表                       │   │
│   │   │ (活跃)  │     (跳表结构)                       │   │
│   │   └────┬────┘                                       │   │
│   │        │ 满                                         │   │
│   │        ▼                                            │   │
│   │   ┌─────────┐                                       │   │
│   │   │ MemTable│  3. 转为不可变                       │   │
│   │   │ (不可变)│                                       │   │
│   │   └────┬────┘                                       │   │
│   │        │                                            │   │
│   │        ▼                                            │   │
│   │   ┌─────────┐                                       │   │
│   │   │  Flush  │  4. 刷写到 SST 文件                  │   │
│   │   │ to Disk │                                       │   │
│   │   └────┬────┘                                       │   │
│   │        │                                            │   │
│   │        ▼                                            │   │
│   │   ┌─────────────────────────────────────────────┐   │   │
│   │   │              SST Files (LSM-Tree)           │   │   │
│   │   │                                             │   │   │
│   │   │   L0   L1   L2   L3   L4   L5   L6        │   │   │
│   │   │   ↓    ↓    ↓    ↓    ↓    ↓    ↓         │   │   │
│   │   │  [新] ─────────────────────────→ [旧]      │   │   │
│   │   │                                             │   │   │
│   │   │   Compaction: 后台压缩合并                 │   │   │
│   │   │                                             │   │   │
│   │   └─────────────────────────────────────────────┘   │   │
│   │                                                     │   │
│   └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

7.2 两个RocksDB实例 #

text
TiKV 双 RocksDB 架构
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   ┌─────────────────────────────────────────────────────┐   │
│   │                    TiKV                             │   │
│   │                                                     │   │
│   │   ┌─────────────────┐  ┌─────────────────┐         │   │
│   │   │   Raft DB       │  │   KV DB         │         │   │
│   │   │                 │  │                 │         │   │
│   │   │ 存储:           │  │ 存储:           │         │   │
│   │   │ - Raft Log      │  │ - 用户数据      │         │   │
│   │   │ - Raft 元数据   │  │ - MVCC 版本     │         │   │
│   │   │                 │  │ - 锁信息        │         │   │
│   │   │ 特点:           │  │                 │         │   │
│   │   │ - 写入频繁      │  │ 特点:           │         │   │
│   │   │ - 数据量小      │  │ - 数据量大      │         │   │
│   │   │ - 顺序写入      │  │ - 读写混合      │         │   │
│   │   │                 │  │                 │         │   │
│   │   └─────────────────┘  └─────────────────┘         │   │
│   │                                                     │   │
│   └─────────────────────────────────────────────────────┘   │
│                                                             │
│   分离优势:                                                 │
│   - Raft 日志顺序写入,优化配置                            │
│   - 用户数据随机读写,独立优化                              │
│   - 避免相互影响                                           │
│                                                             │
└─────────────────────────────────────────────────────────────┘

八、配置调优 #

8.1 关键配置 #

yaml
# TiKV 配置示例
[raftstore]
sync-log = true              # 同步刷盘,保证数据安全
capacity = "100GB"           # 存储容量限制

[rocksdb]
max-open-files = 4096        # 最大打开文件数
max-background-jobs = 8      # 后台线程数

[rocksdb.defaultcf]
block-size = "64KB"          # 块大小
write-buffer-size = "128MB"  # 写缓冲区大小
compression = "lz4"          # 压缩算法

[rocksdb.writecf]
block-size = "64KB"
write-buffer-size = "128MB"

[raftdb]
max-open-files = 4096

8.2 性能参数 #

sql
-- 查看配置
SHOW CONFIG WHERE TYPE = 'tikv' AND NAME LIKE '%raftstore%';

-- 动态修改配置
SET CONFIG tikv `raftstore.sync-log` = true;

九、总结 #

TiKV 核心要点:

模块 要点
Key-Value 有序编码、表数据索引分离
Region 数据分片、分裂合并、调度
Raft 多Raft组、日志复制、选举
MVCC 多版本、快照隔离、GC
事务 乐观/悲观、两阶段提交
RocksDB LSM-Tree、双实例

下一步,让我们学习 PD 调度器!

最后更新:2026-03-27