Skip to content

TiDB 数据分布

TiDB 作为分布式数据库,采用了独特的数据分布机制,将数据分散存储在多个 TiKV 节点上,实现了数据的高可用性和水平扩展性。理解 TiDB 的数据分布机制对于优化 TiDB 集群性能和管理 TiDB 集群至关重要。

数据分布基础概念

1. Region

Region 是 TiDB 数据分布的基本单位,每个 Region 负责存储一段连续的数据。

Region 特点

  • 数据范围:每个 Region 包含一个左闭右开的数据范围 (StartKey, EndKey)
  • 大小限制:默认情况下,每个 Region 的大小限制为 96MB,可以通过配置调整
  • 自动分裂:当 Region 大小超过阈值时,会自动分裂为两个新的 Region
  • 自动合并:当相邻 Region 大小都小于阈值的一半时,会自动合并为一个 Region
  • 副本管理:每个 Region 有多个副本,默认情况下为 3 个副本,分布在不同的 TiKV 节点上

Region 数据结构

Region {
  RegionID: uint64,
  StartKey: []byte,
  EndKey: []byte,
  Peers: [Peer],
  Leader: Peer,
  ...
}

2. Key-Value 模型

TiDB 采用 Key-Value 模型存储数据,所有数据都被转换为 Key-Value 对存储在 TiKV 中。

Key 编码规则

TiDB 将表数据、索引数据等所有数据转换为 Key-Value 对,Key 的编码规则如下:

  • 表数据t8字节表ID_r8字节行ID_列名
  • 索引数据t8字节表ID_i8字节索引ID_索引值_行ID
  • 元数据m_元数据类型_元数据ID

Value 存储

Value 存储对应 Key 的实际数据内容,根据数据类型的不同,采用不同的编码方式。

3. 一致性哈希

TiDB 使用一致性哈希算法将 Region 映射到 TiKV 节点上,实现数据的均匀分布和负载均衡。

一致性哈希环

  • TiKV 节点:每个 TiKV 节点在哈希环上有多个虚拟节点
  • Region 分配:根据 Region 的 StartKey 计算哈希值,将 Region 分配到哈希环上对应的 TiKV 节点
  • 节点增减:当 TiKV 节点增减时,只有少量 Region 需要重新分配,减少了数据迁移量

数据分布架构

1. 分层架构

TiDB 的数据分布采用分层架构,包括:

  • TiDB 层:负责 SQL 解析、优化和执行
  • PD 层:负责管理 Region 分布和 TiKV 节点状态
  • TiKV 层:负责存储数据和处理 Region 请求

2. PD 的角色

PD(Placement Driver)是 TiDB 集群的大脑,负责管理 Region 分布和 TiKV 节点状态。

PD 的主要职责

  • Region 管理:管理 Region 的创建、分裂、合并和销毁
  • 节点管理:监控 TiKV 节点的状态,包括节点的存活状态、负载情况等
  • 负载均衡:根据 TiKV 节点的负载情况,调整 Region 的分布,实现负载均衡
  • 调度策略:制定 Region 调度策略,包括副本调度、负载均衡调度、热点调度等

PD 调度流程

  1. 收集信息:PD 定期收集 TiKV 节点和 Region 的状态信息
  2. 分析调度需求:根据收集到的信息,分析是否需要进行调度
  3. 生成调度计划:根据调度策略,生成具体的调度计划
  4. 执行调度计划:将调度计划发送给对应的 TiKV 节点执行
  5. 验证调度结果:验证调度计划的执行结果,确保调度成功

3. TiKV 的角色

TiKV 是 TiDB 集群的存储引擎,负责存储数据和处理 Region 请求。

TiKV 的主要职责

  • 数据存储:存储 Region 的数据副本
  • Region 服务:处理 Region 的读写请求
  • 副本管理:管理 Region 副本的复制和一致性
  • Region 分裂与合并:执行 Region 的分裂和合并操作
  • 数据迁移:执行 Region 数据的迁移操作

Region 管理

1. Region 分裂

当 Region 大小超过阈值时,会自动分裂为两个新的 Region。

分裂触发条件

  • 大小触发:Region 大小超过配置的阈值(默认 96MB)
  • 键数量触发:Region 中的键数量超过配置的阈值(默认 1440000)
  • 手动触发:通过 SQL 语句或 PD 命令手动触发

分裂过程

  1. 选择分裂点:根据 Region 中的数据分布,选择合适的分裂点
  2. 创建新 Region:创建一个新的 Region,包含分裂后的后半部分数据
  3. 更新元数据:更新 PD 中的 Region 元数据
  4. 同步数据:将新 Region 的数据同步到其他 TiKV 节点
  5. 更新路由:更新 TiDB 和 TiKV 中的 Region 路由信息

分裂配置参数

toml
# Region 大小阈值,单位为 MB
[raftstore]
region-max-size = 96

# Region 键数量阈值
[raftstore]
region-max-keys = 1440000

2. Region 合并

当相邻 Region 大小都小于阈值的一半时,会自动合并为一个 Region。

合并触发条件

  • 大小条件:相邻两个 Region 的大小都小于阈值的一半
  • 时间条件:Region 分裂后经过一定时间(默认 1h)才能合并
  • 手动触发:通过 PD 命令手动触发

合并过程

  1. 选择合并候选:PD 选择符合条件的相邻 Region 对
  2. 发送合并请求:PD 向 Region 发送合并请求
  3. 执行合并操作:TiKV 节点执行 Region 合并操作
  4. 更新元数据:更新 PD 中的 Region 元数据
  5. 更新路由:更新 TiDB 和 TiKV 中的 Region 路由信息

合并配置参数

toml
# Region 合并大小阈值,默认值为 region-max-size 的一半
[raftstore]
region-split-size = 48

# Region 分裂后多久可以合并,单位为秒
[pd]
region-merge-schedule-limit = 1

3. Region 副本管理

每个 Region 有多个副本,默认情况下为 3 个副本,分布在不同的 TiKV 节点上。

副本分布策略

  • 机架感知:副本分布在不同的机架上,提高可用性
  • 跨区域分布:副本分布在不同的区域,提高容灾能力
  • 负载均衡:副本分布考虑 TiKV 节点的负载情况

副本故障处理

当 Region 副本所在的 TiKV 节点发生故障时,PD 会自动调度新的副本,确保 Region 始终保持足够的副本数量。

数据分布优化

1. 表设计优化

合理的表设计可以优化数据分布,提高查询性能。

主键选择

  • 选择合适的主键:选择递增的主键可以减少 Region 热点问题
  • 避免使用随机主键:随机主键会导致大量的 Region 分裂和合并
  • 考虑业务访问模式:根据业务访问模式选择合适的主键

表分区

  • 范围分区:根据列值的范围将表分为多个分区
  • 哈希分区:根据列值的哈希值将表分为多个分区
  • 列表分区:根据列值的列表将表分为多个分区
  • 复合分区:结合多种分区方式

索引设计

  • 合理创建索引:只创建必要的索引,避免过多的索引
  • 考虑索引的选择性:选择选择性高的列作为索引
  • 避免创建过大的索引:过大的索引会增加存储空间和查询开销

2. Region 分裂优化

优化 Region 分裂策略可以提高集群性能和稳定性。

调整 Region 大小

根据业务需求和集群规模,调整 Region 的大小阈值:

toml
# 调整 Region 大小阈值为 128MB
[raftstore]
region-max-size = 128

预分裂 Region

对于新创建的表,可以预分裂 Region,避免后续频繁的 Region 分裂:

sql
-- 创建表时预分裂 32 个 Region
CREATE TABLE t (id INT PRIMARY KEY, name VARCHAR(20))
    PARTITION BY RANGE (id) (
        PARTITION p0 VALUES LESS THAN (100000),
        PARTITION p1 VALUES LESS THAN (200000),
        ...
        PARTITION p31 VALUES LESS THAN (3200000)
    );

-- 使用 pd-ctl 预分裂 Region
pd-ctl region split --pd="<pd-host>:2379" --ranges="start_key1-end_key1,start_key2-end_key2"

3. 负载均衡优化

优化负载均衡策略可以提高集群的整体性能。

调整调度策略

根据业务需求,调整 PD 的调度策略:

toml
# 调整副本调度速度
[pd]
replication-schedule-limit = 64

# 调整负载均衡调度速度
[pd]
balance-schedule-limit = 16

# 调整热点调度速度
[pd]
hot-region-schedule-limit = 16

热点处理

  • 识别热点:使用 TiDB Dashboard 或 Prometheus 监控热点 Region
  • 优化业务逻辑:调整业务逻辑,避免集中访问某些 Region
  • 使用分区表:将热点数据分散到多个分区
  • 调整 Region 分裂策略:调整 Region 分裂阈值,加速热点 Region 的分裂

数据分布监控与管理

1. 监控指标

  • Region 数量:监控集群中 Region 的总数量
  • Region 大小分布:监控不同大小 Region 的数量分布
  • Region 副本分布:监控 Region 副本在不同 TiKV 节点上的分布
  • Region 分裂与合并:监控 Region 分裂和合并的频率
  • Region 迁移:监控 Region 迁移的数量和速度
  • 热点 Region:监控热点 Region 的分布和访问情况

2. 监控工具

  • TiDB Dashboard:提供可视化的监控界面,包括 Region 分布、热点 Region、集群负载等
  • Prometheus + Grafana:提供更灵活的监控配置和告警功能
  • pd-ctl:PD 命令行工具,可以查看和管理 Region 分布
  • tikv-ctl:TiKV 命令行工具,可以查看和管理 TiKV 节点和 Region

3. 常用管理命令

pd-ctl 命令

bash
# 查看集群状态
pd-ctl -u http://<pd-host>:2379 cluster

# 查看 Region 分布
pd-ctl -u http://<pd-host>:2379 region分布

# 查看热点 Region
pd-ctl -u http://<pd-host>:2379 hot region

# 手动分裂 Region
pd-ctl -u http://<pd-host>:2379 region split --region=<region-id> --split-key=<split-key>

# 手动合并 Region
pd-ctl -u http://<pd-host>:2379 region merge --region1=<region-id1> --region2=<region-id2>

tikv-ctl 命令

bash
# 查看 TiKV 节点状态
tikv-ctl status --host=<tikv-host>:20160

# 查看 Region 信息
tikv-ctl region --host=<tikv-host>:20160 --region-id=<region-id>

# 查看 TiKV 节点上的 Region 列表
tikv-ctl region list --host=<tikv-host>:20160

数据分布常见问题处理

1. Region 热点问题

  • 问题:某些 Region 访问频率过高,导致 TiKV 节点负载不均衡 解决方法
    • 优化业务逻辑,避免集中访问某些 Region
    • 使用分区表,将热点数据分散到多个分区
    • 调整 Region 分裂阈值,加速热点 Region 的分裂
    • 使用 PD 的热点调度功能,自动将热点 Region 迁移到负载较低的 TiKV 节点

2. Region 数量过多

  • 问题:集群中 Region 数量过多,导致 PD 负载过高,集群性能下降 解决方法
    • 调整 Region 大小阈值,增加每个 Region 的大小
    • 优化表设计,避免过多的小表和小索引
    • 合并不必要的 Region
    • 考虑使用表分区,减少 Region 数量

3. Region 迁移频繁

  • 问题:Region 迁移频繁,导致集群性能下降 解决方法
    • 调整 PD 调度策略,降低调度速度
    • 检查 TiKV 节点的网络连接,确保网络稳定
    • 检查 TiKV 节点的磁盘性能,确保磁盘性能足够
    • 避免频繁添加或删除 TiKV 节点

4. Region 副本分布不均

  • 问题:Region 副本分布不均,某些 TiKV 节点上的副本数量过多 解决方法
    • 调整 PD 副本调度策略
    • 检查 TiKV 节点的状态,确保所有 TiKV 节点都正常运行
    • 考虑添加新的 TiKV 节点,平衡副本分布

数据分布最佳实践

1. 表设计最佳实践

  • 选择合适的主键:选择递增的主键,如自增 ID 或时间戳,避免使用随机主键
  • 合理设计表结构:避免使用过大的单行数据,控制单行数据大小在 1KB 以内
  • 合理使用分区表:对于大表,使用分区表将数据分散到多个分区
  • 合理创建索引:只创建必要的索引,避免过多的索引

2. 集群配置最佳实践

  • 调整 Region 大小:根据集群规模和业务需求,调整 Region 大小阈值,建议设置为 64MB-128MB
  • 调整副本数量:根据集群规模和容灾需求,调整副本数量,建议设置为 3-5 个副本
  • 配置机架感知:启用机架感知,确保 Region 副本分布在不同的机架上
  • 配置跨区域分布:对于跨区域部署的集群,配置跨区域副本分布策略

3. 监控与管理最佳实践

  • 建立完善的监控体系:监控 Region 分布、热点 Region、集群负载等指标
  • 定期巡检:定期巡检集群状态,发现和解决潜在问题
  • 定期调整:根据业务变化和集群状态,定期调整集群配置和调度策略
  • 记录变更:记录所有集群变更操作,便于后续分析和优化

4. 性能优化最佳实践

  • 避免全表扫描:使用索引避免全表扫描,减少 Region 访问数量
  • 优化查询条件:优化查询条件,减少需要访问的 Region 数量
  • 合理使用批量操作:使用批量操作减少网络开销和 Region 访问次数
  • 避免大事务:将大事务拆分为多个小事务,减少对单个 Region 的锁定时间

常见问题(FAQ)

Q1: TiDB 的 Region 大小默认是多少?

A1: TiDB 的 Region 大小默认是 96MB,可以通过配置 region-max-size 参数调整。

Q2: TiDB 的 Region 副本数量默认是多少?

A2: TiDB 的 Region 副本数量默认是 3 个,可以通过配置 max-replicas 参数调整。

Q3: 如何查看 TiDB 集群中的 Region 数量?

A3: 可以使用以下方法查看 TiDB 集群中的 Region 数量:

  • 使用 TiDB Dashboard,在 "集群信息" 页面查看
  • 使用 Prometheus + Grafana,查询 tidb_cluster_region_count 指标
  • 使用 pd-ctl 命令:pd-ctl -u http://pd-host:2379 region list | wc -l

Q4: 如何手动分裂 Region?

A4: 可以使用 pd-ctl 命令手动分裂 Region:

bash
pd-ctl -u http://<pd-host>:2379 region split --region=<region-id> --split-key=<split-key>

Q5: 如何手动合并 Region?

A5: 可以使用 pd-ctl 命令手动合并 Region:

bash
pd-ctl -u http://<pd-host>:2379 region merge --region1=<region-id1> --region2=<region-id2>

Q6: 如何处理 Region 热点问题?

A6: 处理 Region 热点问题的方法包括:

  • 优化业务逻辑,避免集中访问某些 Region
  • 使用分区表,将热点数据分散到多个分区
  • 调整 Region 分裂阈值,加速热点 Region 的分裂
  • 使用 PD 的热点调度功能,自动将热点 Region 迁移到负载较低的 TiKV 节点

Q7: 如何优化 TiDB 集群的 Region 分布?

A7: 优化 TiDB 集群的 Region 分布的方法包括:

  • 调整 Region 大小阈值,平衡 Region 数量和大小
  • 优化表设计,避免过多的小表和小索引
  • 配置合理的 PD 调度策略
  • 定期监控和调整 Region 分布

Q8: 如何监控 TiDB 集群的 Region 分布?

A8: 可以使用以下工具监控 TiDB 集群的 Region 分布:

  • TiDB Dashboard:提供可视化的 Region 分布监控
  • Prometheus + Grafana:可以配置自定义的 Region 分布监控面板
  • pd-ctl:可以查看详细的 Region 分布信息
  • tikv-ctl:可以查看 TiKV 节点上的 Region 分布