一、PD 架构演进
1.1 传统 PD 架构的局限
在 TiDB 8.x 之前,PD 是一个单体进程,同时承担三个职责:
传统 PD 单体架构:
┌─────────────────────────────────────────┐
│ PD Server (单体) │
│ │
│ ┌───────────┐ ┌───────────┐ ┌───────┐│
│ │ TSO 服务 │ │ Scheduling │ │ API ││
│ │ (时间戳) │ │ (调度决策) │ │ (元数据)││
│ └───────────┘ └───────────┘ └───────┘│
│ │
│ 三个模块共享: │
│ • 同一个 Raft Group (etcd) │
│ • 同一个进程资源 │
│ • 同一个存储空间 │
└──────────────────────────────────────────┘
局限性:
├── 无法独立扩展: TSO 需要低延迟,Scheduling 需要高吞吐
├── 资源竞争: TSO 请求和调度决策竞争 CPU 和存储
├── 升级影响大: 升级 PD 同时影响 TSO 和调度
└── 部署不灵活: 不同组件需要相同硬件配置
1.2 PD 微服务架构
TiDB 8.x 将 PD 拆分为两个独立服务:
PD 微服务架构:
┌───────────────────────┐ ┌───────────────────────┐
│ TSO Server │ │ Scheduling Server │
│ │ │ │
│ • 全局时间戳分配 │ │ • Region 调度决策 │
│ • 低延迟优化 │ │ • 元数据管理 │
│ • 可独立扩展 │ │ • 高吞吐优化 │
│ • 独立 Raft Group │ │ • 独立 Raft Group │
└───────────────────────┘ └───────────────────────┘
优势:
├── 独立扩展: TSO 和 Scheduling 可按需扩展
├── 资源隔离: 互不影响,各自优化
├── 独立升级: 升级 TSO 不影响调度,升级调度不影响 TSO
└── 灵活部署: 不同组件可部署在不同硬件上
二、TSO 服务
2.1 TSO 的作用
TSO(Time Stamp Oracle)是 TiDB 分布式事务的基石:
分布式事务中的 TSO:
事务 A (TiDB-1) 事务 B (TiDB-2)
│ │
│ 获取 start_ts │ 获取 start_ts
v v
├─── 向 TSO Server 请求 ───────>│
│ │
│ 返回: 428888888888888321 │ 返回: 428888888888888322
│ │
v v
开始事务 开始事务
(快照时间戳 = 321) (快照时间戳 = 322)
TSO 保证了:
1. 全局唯一递增: 每个事务的时间戳都不相同
2. 因果顺序: 后开始的事务时间戳一定更大
3. 快照隔离: 事务只能看到其 start_ts 之前的数据版本
2.2 TSO 分配机制
TSO 分配过程:
TiDB Server TSO Server
│ │
│ 请求: 批量获取 N 个时间戳 │
├────────────────────────────>│
│ │
│ │ 从 etcd 获取当前最大 TSO
│ │ 分配一段连续的时间戳范围
│ │ (如 428888888888888321 ~ 428888888888888420)
│ │
│ 返回: 基础 TSO + 范围大小 │
│<────────────────────────────┤
│ │
TiDB 本地缓存该范围,按需分配:
事务 1: 428888888888888321
事务 2: 428888888888888322
...
事务 N: 428888888888888420
用完后再向 TSO Server 申请下一个范围
这种"批量预分配 + 本地分配"的方式大幅减少了 TiDB 与 TSO Server 的通信开销。
2.3 TSO 部署拓扑
最小部署 (3 节点):
┌─────────┐ ┌─────────┐ ┌─────────┐
│ TSO-1 │◄──►│ TSO-2 │◄──►│ TSO-3 │
│(Leader) │ │(Follower)│ │(Follower)│
└─────────┘ └─────────┘ └─────────┘
▲ ▲ ▲
│ │ │
└──────────────┼──────────────┘
│
TiDB Server 请求
生产环境推荐 3 或 5 个 TSO 节点,保证高可用。
三、Scheduling 服务
3.1 调度职责
Scheduling 服务负责集群的数据分布决策:
Scheduling 核心功能:
┌─────────────────────────────────────────────────┐
│ Scheduling Server │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌─────────┐│
│ │ Region 调度 │ │ 负载均衡 │ │ 元数据 ││
│ │ • 分裂/合并 │ │ • Store 均衡 │ │ • Store ││
│ │ • 迁移/复制 │ │ • Region 分布 │ │ • Region││
│ └──────────────┘ └──────────────┘ └─────────┘│
│ │
│ 调度策略: │
│ • Balance Leader: 均衡 Leader 分布 │
│ • Balance Region: 均衡 Region 副本 │
│ • Hot Spot: 检测和处理热点 Region │
│ • Label: 基于标签的调度约束 │
└───────────────────────────────────────────────────┘
3.2 调度流程
Region 迁移调度流程:
1. Scheduling 检测到 Store A 负载过高
│
v
2. 选择 Store A 上的一个 Region (Region X)
│
v
3. 选择目标 Store B(负载较低)
│
v
4. 在 Store B 上创建 Region X 的新副本 (Learner)
│
v
5. Region X 的数据通过 Raft 复制到 Store B
│
v
6. Store B 的副本变为 Follower
│
v
7. 可能将 Region X 的 Leader 迁移到 Store B
│
v
8. 从 Store A 移除旧副本(如果副本数已满)
3.3 调度规则
# 调度配置示例 (通过 PD API 或 pd-ctl)
# 调度频率
schedule:
leader-schedule-limit: 4 # 每轮最多调度 4 个 Leader
region-schedule-limit: 2048 # 每轮最多调度 2048 个 Region
replica-schedule-limit: 64 # 每轮最多调度 64 个副本
# 调度策略
location-replacement: "true" # 启用位置替换(优化副本分布)
enable-one-way-merge: "false" # 双向合并
# 存储限制
store-limit:
- address: "10.0.1.21:20160"
remove-peer: 15 # 该节点每分钟最多移除 15 个 Peer
add-peer: 15 # 该节点每分钟最多添加 15 个 Peer
四、部署 PD 微服务
4.1 使用 TiUP 部署
# topology-pd-ms.yaml — PD 微服务拓扑
# 注意: tso_servers 和 scheduling_servers 是 TiUP 拓扑文件中的专用关键字
# 用于声明 TSO 和 Scheduling 服务的节点
---
# PD TSO 节点
tso_servers:
- host: 10.0.1.11
port: 2379
peer_port: 2380
deploy_dir: "/tidb-deploy/tso-2379"
data_dir: "/tidb-data/tso-2379"
log_dir: "/tidb-deploy/tso-2379/log"
config:
tso:
enable-local-tso: false # 是否启用本地 TSO
- host: 10.0.1.12
port: 2379
peer_port: 2380
deploy_dir: "/tidb-deploy/tso-2379"
data_dir: "/tidb-data/tso-2379"
log_dir: "/tidb-deploy/tso-2379/log"
- host: 10.0.1.13
port: 2379
peer_port: 2380
deploy_dir: "/tidb-deploy/tso-2379"
data_dir: "/tidb-data/tso-2379"
log_dir: "/tidb-deploy/tso-2379/log"
# PD Scheduling 节点
scheduling_servers:
- host: 10.0.1.14
port: 2379
peer_port: 2380
deploy_dir: "/tidb-deploy/scheduling-2379"
data_dir: "/tidb-data/scheduling-2379"
log_dir: "/tidb-deploy/scheduling-2379/log"
- host: 10.0.1.15
port: 2379
peer_port: 2380
deploy_dir: "/tidb-deploy/scheduling-2379"
data_dir: "/tidb-data/scheduling-2379"
log_dir: "/tidb-deploy/scheduling-2379/log"
- host: 10.0.1.16
port: 2379
peer_port: 2380
deploy_dir: "/tidb-deploy/scheduling-2379"
data_dir: "/tidb-data/scheduling-2379"
log_dir: "/tidb-deploy/scheduling-2379/log"
# TiDB、TiKV 节点
tidb_servers:
- host: 10.0.1.20
- host: 10.0.1.21
tikv_servers:
- host: 10.0.1.30
- host: 10.0.1.31
- host: 10.0.1.32
# 部署
tiup cluster deploy tidb-ms v8.5.0 topology-pd-ms.yaml --user root
# 启动
tiup cluster start tidb-ms
# 验证
tiup cluster display tidb-ms
4.2 在 K8s 上部署 PD 微服务
apiVersion: pingcap.com/v1alpha1
kind: TidbCluster
metadata:
name: basic
namespace: tidb-cluster
spec:
version: v8.5.0
# PD 微服务配置
pd:
# 使用微服务架构
microService:
enabled: true
# TSO 节点
tso:
replicas: 3
requests:
storage: "10Gi"
storageClassName: ebs-gp3
# Scheduling 节点
scheduling:
replicas: 3
requests:
storage: "10Gi"
storageClassName: ebs-gp3
tikv:
replicas: 3
requests:
storage: "100Gi"
storageClassName: ebs-io1
tidb:
replicas: 2
4.3 从传统 PD 迁移到微服务
# 1. 确认当前 PD 集群状态
tiup cluster display tidb-cluster
# 2. 部署新的 TSO 和 Scheduling 节点
tiup cluster scale-out tidb-cluster tso-scheduling-topology.yaml
# 3. 验证新节点正常
# 通过 pd-ctl 或 Dashboard 检查
# 4. 下线旧的 PD 节点
tiup cluster scale-in tidb-cluster --node 10.0.1.11:2379
tiup cluster scale-in tidb-cluster --node 10.0.1.12:2379
tiup cluster scale-in tidb-cluster --node 10.0.1.13:2379
迁移过程中,TiDB 集群无需停机,切换是渐进的。
五、配置与调优
5.1 TSO 配置
# TSO 配置文件
tso:
# 是否启用本地 TSO(减少跨机房延迟)
enable-local-tso: false
# TSO 批量大小(默认 10000)
tso-update-physical-interval: 50ms
# 保存 TSO 到 etcd 的间隔
save-interval: 3000
# 最大 TSO 范围(默认 100000)
max-reset-tso-gap: 87600h
5.2 Scheduling 配置
scheduling:
# Leader 调度限制
leader-schedule-limit: 4
# Region 调度限制
region-schedule-limit: 2048
# 副本调度限制
replica-schedule-limit: 64
# Region 合并限制
merge-schedule-limit: 8
# 热点调度限制
hot-region-schedule-limit: 4
# Region 分裂阈值 (bytes)
region-split-size: 96MB
# Region 分裂 Key 阈值
region-split-keys: 960000
# 最大存储可用率(低于此值停止调度到此 Store)
max-store-available-ratio: 0.85
# 高可用检查
isolation-level: "zone" # 副本分布在不同的 zone
5.3 Placement Rules 与调度
Placement Rules 是比配置更强大的调度控制方式:
# 定义 Placement Rule: 数据分布到 3 个机房
rule:
group_id: "pd"
id: "rule1"
start_key: ""
end_key: ""
role: voter
count: 5 # 5 个副本
location_labels: ["zone", "rack", "host"]
constraints:
- "+zone=zone-a:2" # zone-a 放 2 个副本
- "+zone=zone-b:2" # zone-b 放 2 个副本
- "+zone=zone-c:1" # zone-c 放 1 个副本
# 通过 pd-ctl 设置
echo '{
"group_id": "pd",
"id": "rule1",
"start_key": "",
"end_key": "",
"role": "voter",
"count": 5,
"location_labels": ["zone", "rack", "host"]
}' | pd-ctl config placement-rules save