TiDB PD 微服务架构详解

一、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
1 个赞

PD 微服务 了解一下

这个架构演进总结得挺到位的。补充几点实战经验:

  1. 拆分后 TSO 节点建议用高主频 CPU + 低延迟网络(万兆起步),调度节点反而吃 CPU 核数和内存,硬件选型确实能分开了。

  2. 部署时注意 pd-ctl 的 endpoint 要指向 API 节点,别搞混了。TSO 和 Scheduling 通过 gRPC 通信,跨机房部署要留意延迟。

  3. 升级可以灰度了,先升 Scheduling 再升 TSO,业务基本无感,这点比单体 PD 强太多。

不错,学习了。

总结不错,微架构也可以说是TiDB一大亮点

谢谢分享,学习

TiDB PD微服务架构值得详细学习,谢谢分享