- 关于 TiDB
- 快速上手
- 部署集群
- 数据迁移
- 数据迁移概述
- 从 MySQL 迁移至 TiDB
- 从 CSV 文件迁移至 TiDB
- 运维操作
- 监控与告警
- 故障诊断
- 性能调优
- 系统调优
- 软件调优
- SQL 性能调优
- 教程
- TiDB 生态工具
- TiDB 生态工具功能概览
- TiDB 生态工具适用场景
- TiDB 工具下载
- Backup & Restore (BR)
- TiDB Binlog
- TiDB Lightning
- TiCDC 简介
- Dumpling 使用文档
- sync-diff-inspector
- Loader 使用文档
- Mydumper 使用文档
- Syncer 使用文档
- TiSpark
- 参考指南
- 架构
- 监控指标
- 安全加固
- 权限
- SQL
- SQL 语言结构和语法
- 属性
- 字面值
- Schema 对象名
- 关键字
- 用户自定义变量
- 表达式语法
- 注释语法
- SQL 语句
- ADD COLUMN
- ADD INDEX
- ADMIN
- ALTER DATABASE
- ALTER INSTANCE
- ALTER TABLE
- ALTER USER
- ANALYZE
- BACKUP
- BEGIN
- CHANGE COLUMN
- CHANGE DRAINER
- CHANGE PUMP
- COMMIT
- CREATE [GLOBAL|SESSION] BINDING
- CREATE DATABASE
- CREATE INDEX
- CREATE ROLE
- CREATE SEQUENCE
- CREATE TABLE LIKE
- CREATE TABLE
- CREATE USER
- CREATE VIEW
- DEALLOCATE
- DELETE
- DESC
- DESCRIBE
- DO
- DROP [GLOBAL|SESSION] BINDING
- DROP COLUMN
- DROP DATABASE
- DROP INDEX
- DROP ROLE
- DROP SEQUENCE
- DROP STATS
- DROP TABLE
- DROP USER
- DROP VIEW
- EXECUTE
- EXPLAIN ANALYZE
- EXPLAIN
- FLASHBACK TABLE
- FLUSH PRIVILEGES
- FLUSH STATUS
- FLUSH TABLES
- GRANT
- GRANT
- INSERT
- KILL [TIDB]
- LOAD STATS
- MODIFY COLUMN
- PREPARE
- RECOVER TABLE
- RENAME INDEX
- RENAME TABLE
- REPLACE
- RESTORE
- REVOKE
- REVOKE
- ROLLBACK
- SELECT
- SET DEFAULT ROLE
- SET [NAMES|CHARACTER SET]
- SET PASSWORD
- SET ROLE
- SET TRANSACTION
- SET [GLOBAL|SESSION]
- SHOW [BACKUPS|RESTORES]
- SHOW ANALYZE STATUS
- SHOW [GLOBAL|SESSION] BINDINGS
- SHOW BUILTINS
- SHOW CHARACTER SET
- SHOW COLLATION
- SHOW [FULL] COLUMNS FROM
- SHOW CONFIG
- SHOW CREATE SEQUENCE
- SHOW CREATE TABLE
- SHOW CREATE USER
- SHOW DATABASES
- SHOW DRAINER STATUS
- SHOW ENGINES
- SHOW ERRORS
- SHOW [FULL] FIELDS FROM
- SHOW GRANTS
- SHOW INDEX [FROM|IN]
- SHOW INDEXES [FROM|IN]
- SHOW KEYS [FROM|IN]
- SHOW MASTER STATUS
- SHOW PLUGINS
- SHOW PRIVILEGES
- SHOW [FULL] PROCESSLIST
- SHOW PROFILES
- SHOW PUMP STATUS
- SHOW SCHEMAS
- SHOW STATS_HEALTHY
- SHOW STATS_HISTOGRAMS
- SHOW STATS_META
- SHOW [GLOBAL|SESSION] STATUS
- SHOW TABLE NEXTROWID
- SHOW TABLE REGIONS
- SHOW TABLE STATUS
- SHOW [FULL] TABLES
- SHOW [GLOBAL|SESSION] VARIABLES
- SHOW WARNINGS
- SHUTDOWN
- Split Region 使用文档
- START TRANSACTION
- TRACE
- TRUNCATE
- UPDATE
- USE
- 数据类型
- 函数与操作符
- 约束
- 生成列
- SQL 模式
- 事务
- 垃圾回收 (GC)
- 视图
- 分区表
- 字符集和排序规则
- 系统表
- TiDB 系统表
- INFORMATION_SCHEMA
- TiDB 简介
- ANALYZE_STATUS
- CHARACTER_SETS
- CLUSTER_CONFIG
- CLUSTER_HARDWARE
- CLUSTER_INFO
- CLUSTER_LOAD
- CLUSTER_LOG
- CLUSTER_SYSTEMINFO
- COLLATIONS
- COLLATIONCHARACTERSET_APPLICABILITY
- COLUMNS
- DDL_JOBS
- ENGINES
- INSPECTION_RESULT
- INSPECTION_RULES
- INSPECTION_SUMMARY
- KEYCOLUMNUSAGE
- METRICS_SUMMARY
- METRICS_TABLES
- PARTITIONS
- PROCESSLIST
- SCHEMATA
- SEQUENCES
- SESSION_VARIABLES
- SLOW_QUERY
- STATISTICS
- TABLES
- TABLE_CONSTRAINTS
- TABLESTORAGESTATS
- TIDBHOTREGIONS
- TIDB_INDEXES
- TIDBSERVERSINFO
- TIFLASH_REPLICA
- TIKVREGIONPEERS
- TIKVREGIONSTATUS
- TIKVSTORESTATUS
- USER_PRIVILEGES
- VIEWS
- Metrics Schema
- SQL 语言结构和语法
- UI
- CLI
- 命令行参数
- 配置文件参数
- 系统变量
- 存储引擎
- TiUP
- 遥测
- 错误码与故障诊断
- TiCDC Open Protocol
- 通过拓扑 label 进行副本调度
- 常见问题解答 (FAQ)
- 术语表
PD 调度策略最佳实践
本文将详细介绍 PD 调度系统的原理,并通过几个典型场景的分析和处理方式,分享调度策略的最佳实践和调优方式,帮助大家在使用过程中快速定位问题。本文假定你对 TiDB,TiKV 以及 PD 已经有一定的了解,相关核心概念如下:
- Leader/Follower/Learner
- Operator
- Operator Step
- Pending/Down
- Region/Peer/Raft Group
- Region Split
- Scheduler
- Store
注意:
本文内容基于 TiDB 3.0 版本,更早的版本(2.x)缺少部分功能的支持,但是基本原理类似,也可以以本文作为参考。
PD 调度原理
该部分介绍调度系统涉及到的相关原理和流程。
调度流程
宏观上来看,调度流程大体可划分为 3 个部分:
信息收集
TiKV 节点周期性地向 PD 上报
StoreHeartbeat
和RegionHeartbeat
两种心跳消息:StoreHeartbeat
包含 Store 的基本信息、容量、剩余空间和读写流量等数据。RegionHeartbeat
包含 Region 的范围、副本分布、副本状态、数据量和读写流量等数据。
PD 梳理并转存这些信息供调度进行决策。
生成调度
不同的调度器从自身的逻辑和需求出发,考虑各种限制和约束后生成待执行的 Operator。这里所说的限制和约束包括但不限于:
- 不往处于异常状态中(如断连、下线、繁忙、空间不足或在大量收发 snapshot 等)的 Store 添加副本
- Balance 时不选择状态异常的 Region
- 不尝试把 Leader 转移给 Pending Peer
- 不尝试直接移除 Leader
- 不破坏 Region 各种副本的物理隔离
- 不破坏 Label property 等约束
执行调度
调度执行的步骤为:
a. Operator 先进入一个由
OperatorController
管理的等待队列。b.
OperatorController
会根据配置以一定的并发量从等待队列中取出 Operator 并执行。执行的过程就是依次把每个 Operator Step 下发给对应 Region 的 Leader。c. 标记 Operator 为 “finish” 或 “timeout” 状态,然后从执行列表中移除。
负载均衡
Region 负载均衡调度主要依赖 balance-leader
和 balance-region
两个调度器。二者的调度目标是将 Region 均匀地分散在集群中的所有 Store 上,但它们各有侧重:balance-leader
关注 Region 的 Leader,目的是分散处理客户端请求的压力;balance-region
关注 Region 的各个 Peer,目的是分散存储的压力,同时避免出现爆盘等状况。
balance-leader
与 balance-region
有着相似的调度流程:
- 根据不同 Store 的对应资源量的情况分别打分。
- 不断从得分较高的 Store 选择 Leader 或 Peer 迁移到得分较低的 Store 上。
两者的分数计算上也有一定差异:balance-leader
比较简单,使用 Store 上所有 Leader 所对应的 Region Size 加和作为得分。因为不同节点存储容量可能不一致,计算 balance-region
得分会分以下三种情况:
- 当空间富余时使用数据量计算得分(使不同节点数据量基本上均衡)
- 当空间不足时由使用剩余空间计算得分(使不同节点剩余空间基本均衡)
- 处于中间态时则同时考虑两个因素做加权和当作得分
此外,为了应对不同节点可能在性能等方面存在差异的问题,还可为 Store 设置负载均衡的权重。leader-weight
和 region-weight
分别用于控制 Leader 权重以及 Region 权重(默认值都为 “1”)。假如把某个 Store 的 leader-weight
设为 “2”,调度稳定后,则该节点的 Leader 数量约为普通节点的 2 倍;假如把某个 Store 的 region-weight
设为 “0.5”,那么调度稳定后该节点的 Region 数量约为其他节点的一半。
热点调度
热点调度对应的调度器是 hot-region-scheduler
。在 3.0 版本中,统计热点 Region 的方式为:
- 根据 Store 上报的信息,统计出持续一段时间读或写流量超过一定阈值的 Region。
- 用与负载均衡类似的方式把这些 Region 分散开来。
对于写热点,热点调度会同时尝试打散热点 Region 的 Peer 和 Leader;对于读热点,由于只有 Leader 承载读压力,热点调度会尝试将热点 Region 的 Leader 打散。
集群拓扑感知
让 PD 感知不同节点分布的拓扑是为了通过调度使不同 Region 的各个副本尽可能分散,保证高可用和容灾。PD 会在后台不断扫描所有 Region,当发现 Region 的分布不是当前的最优化状态时,会生成调度以替换 Peer,将 Region 调整至最佳状态。
负责这个检查的组件叫 replicaChecker
(跟 Scheduler 类似,但是不可关闭)。它依赖于 location-labels
配置项来进行调度。比如配置 [zone,rack,host]
定义了三层的拓扑结构:集群分为多个 zone(可用区),每个 zone 下有多个 rack(机架),每个 rack 下有多个 host(主机)。PD 在调度时首先会尝试将 Region 的 Peer 放置在不同的 zone,假如无法满足(比如配置 3 副本但总共只有 2 个 zone)则保证放置在不同的 rack;假如 rack 的数量也不足以保证隔离,那么再尝试 host 级别的隔离,以此类推。
缩容及故障恢复
缩容是指预备将某个 Store 下线,通过命令将该 Store 标记为 “Offline“ 状态,此时 PD 通过调度将待下线节点上的 Region 迁移至其他节点。
故障恢复是指当有 Store 发生故障且无法恢复时,有 Peer 分布在对应 Store 上的 Region 会产生缺少副本的状况,此时 PD 需要在其他节点上为这些 Region 补副本。
这两种情况的处理过程基本上是一样的。replicaChecker
检查到 Region 存在异常状态的 Peer后,生成调度在健康的 Store 上创建新副本替换异常的副本。
Region merge
Region merge 指的是为了避免删除数据后大量小甚至空的 Region 消耗系统资源,通过调度把相邻的小 Region 合并的过程。Region merge 由 mergeChecker
负责,其过程与 replicaChecker
类似:PD 在后台遍历,发现连续的小 Region 后发起调度。
查询调度状态
你可以通过观察 PD 相关的 Metrics 或使用 pd-ctl 工具等方式查看调度系统状态。更具体的信息可以参考 PD 监控和 PD Control。
Operator 状态
Grafana PD/Operator 页面展示了 Operator 的相关统计信息。其中比较重要的有:
- Schedule Operator Create:Operator 的创建情况
- Operator finish duration:Operator 执行耗时的情况
- Operator Step duration:不同 Operator Step 执行耗时的情况
查询 Operator 的 pd-ctl 命令有:
operator show
:查询当前调度生成的所有 Operatoroperator show [admin | leader | region]
:按照类型查询 Operator
Balance 状态
Grafana PD/Statistics - Balance 页面展示了负载均衡的相关统计信息,其中比较重要的有:
- Store Leader/Region score:每个 Store 的得分
- Store Leader/Region count:每个 Store 的 Leader/Region 数量
- Store available:每个 Store 的剩余空间
使用 pd-ctl 的 store
命令可以查询 Store 的得分、数量、剩余空间和 weight 等信息。
热点调度状态
Grafana PD/Statistics - hotspot 页面展示了热点 Region 的相关统计信息,其中比较重要的有:
- Hot write Region’s leader/peer distribution:写热点 Region 的 Leader/Peer 分布情况
- Hot read Region’s leader distribution:读热点 Region 的 Leader 分布情况
使用 pd-ctl 同样可以查询上述信息,可以使用的命令有:
hot read
:查询读热点 Region 信息hot write
:查询写热点 Region 信息hot store
:按 Store 统计热点分布情况region topread [limit]
:查询当前读流量最大的 Regionregion topwrite [limit]
:查询当前写流量最大的 Region
Region 健康度
Grafana PD/Cluster/Region health 面板展示了异常 Region 的相关统计信息,包括 Pending Peer、Down Peer、Offline Peer,以及副本数过多或过少的 Region。
通过 pd-ctl 的 region check
命令可以查看具体异常的 Region 列表:
region check miss-peer
:缺副本的 Regionregion check extra-peer
:多副本的 Regionregion check down-peer
:有副本状态为 Down 的 Regionregion check pending-peer
:有副本状态为 Pending 的 Region
调度策略控制
使用 pd-ctl 可以从以下三个方面来调整 PD 的调度策略。更具体的信息可以参考 PD Control。
启停调度器
pd-ctl 支持动态创建和删除 Scheduler,你可以通过这些操作来控制 PD 的调度行为,如:
scheduler show
:显示当前系统中的 Schedulerscheduler remove balance-leader-scheduler
:删除(停用)balance region 调度器scheduler add evict-leader-scheduler 1
:添加移除 Store 1 的所有 Leader 的调度器
手动添加 Operator
PD 支持直接通过 pd-ctl 来创建或删除 Operator,如:
operator add add-peer 2 5
:在 Store 5 上为 Region 2 添加 Peeroperator add transfer-leader 2 5
:将 Region 2 的 Leader 迁移至 Store 5operator add split-region 2
:将 Region 2 拆分为 2 个大小相当的 Regionoperator remove 2
:取消 Region 2 当前待执行的 Operator
调度参数调整
使用 pd-ctl 执行 config show
命令可以查看所有的调度参数,执行 config set {key} {value}
可以调整对应参数的值。常见调整如下:
leader-schedule-limit
:控制 Transfer Leader 调度的并发数region-schedule-limit
:控制增删 Peer 调度的并发数disable-replace-offline-replica
:停止处理节点下线的调度disable-location-replacement
:停止处理调整 Region 隔离级别相关的调度max-snapshot-count
:每个 Store 允许的最大收发 Snapshot 的并发数
典型场景分析与处理
该部分通过几个典型场景及其应对方式说明 PD 调度策略的最佳实践。
Leader/Region 分布不均衡
PD 的打分机制决定了一般情况下,不同 Store 的 Leader Count 和 Region Count 不能完全说明负载均衡状态,所以需要从 TiKV 的实际负载或者存储空间占用来判断是否有负载不均衡的状况。
确认 Leader/Region 分布不均衡后,首先观察不同 Store 的打分情况。
如果不同 Store 的打分是接近的,说明 PD 认为此时已经是均衡状态了,可能的原因有:
- 存在热点导致负载不均衡。可以参考节点下线速度慢
这个场景需要从 Operator 相关的 Metrics 入手,分析 Operator 的生成执行情况。
如果调度在正常生成,只是速度很慢,可能的原因有:
- 调度速度受限于 limit 配置。可以适当调大
replica-schedule-limit
,max-pending-peer-count
以及max-snapshot-count
限制也可以放宽。 - 系统中同时运行有其他的调度任务产生竞争。处理方法参考节点上线速度慢
目前 PD 没有对节点上线特殊处理。节点上线实际上是依靠 balance region 机制来调度的,所以参考热点分布不均匀
热点调度的问题大体上可以分为以下几种情况:
从 PD 的 Metrics 能看出来有不少 hot Region,但是调度速度跟不上,不能及时地把热点 Region 分散开来。
解决方法:调大
hot-region-schedule-limit
并减少其他调度器的 limit 配额,从而加快热点调度的速度。还可调小hot-region-cache-hits-threshold
使 PD 对更快响应流量的变化。单一 Region 形成热点,比如大量请求频繁 scan 一个小表,这个可以从业务角度或者 Metrics 统计的热点信息看出来。由于单 Region 热点现阶段无法使用打散的手段来消除,需要确认热点 Region 后手动添加
split-region
调度将这样的 Region 拆开。从 PD 的统计来看没有热点,但是从 TiKV 的相关 Metrics 可以看出部分节点负载明显高于其他节点,成为整个系统的瓶颈。这是因为目前 PD 统计热点 Region 的维度比较单一,仅针对流量进行分析,在某些场景下无法准确定位热点。例如部分 Region 有大量的点查请求,从流量上来看并不显著,但是过高的 QPS 导致关键模块达到瓶颈。
解决方法:首先从业务层面确定形成热点的 table,然后添加
scatter-range-scheduler
调度器使这个 table 的所有 Region 均匀分布。TiDB 也在其 HTTP API 中提供了相关接口来简化这个操作,具体可以参考 TiDB HTTP API 文档。
Region Merge 速度慢
Region Merge 速度慢也很有可能是受到 limit 配置的限制(
merge-schedule-limit
及region-schedule-limit
),或者是与其他调度器产生了竞争。具体来说,可有如下处理方式:假如已经从相关 Metrics 得知系统中有大量的空 Region,这时可以通过把
max-merge-region-size
和max-merge-region-keys
调整为较小值来加快 Merge 速度。这是因为 Merge 的过程涉及到副本迁移,所以 Merge 的 Region 越小,速度就越快。如果生成 Merge Operator 的速度很快,想进一步加快 Region Merge 过程,还可以把patrol-region-interval
调整为 "10ms" ,这个能加快巡检 Region 的速度,但是会消耗更多的 CPU 资源。创建过大量表后(包括执行
Truncate Table
操作)又清空了。此时如果开启了 split table 特性,这些空 Region 是无法合并的,此时需要调整以下参数关闭这个特性:- TiKV:
split-region-on-table
设为false
,该参数不支持动态修改。 - PD:
key-type
设为txn
或者raw
,该参数支持动态修改。key-type
保持table
,同时设置enable-cross-table-merge
为true
,该参数支持动态修改。注意:
在开启
placement-rules
后,请合理切换txn
和raw
,避免无法正常解码 key。
- TiKV:
对于 3.0.4 和 2.1.16 以前的版本,Region 中 Key 的个数(
approximate_keys
)在特定情况下(大部分发生在删表之后)统计不准确,造成 keys 的统计值很大,无法满足max-merge-region-keys
的约束。你可以通过调大max-merge-region-keys
来避免这个问题。
TiKV 节点故障处理策略
没有人工介入时,PD 处理 TiKV 节点故障的默认行为是,等待半小时之后(可通过
max-store-down-time
配置调整),将此节点设置为 Down 状态,并开始为涉及到的 Region 补充副本。实践中,如果能确定这个节点的故障是不可恢复的,可以立即做下线处理,这样 PD 能尽快补齐副本,降低数据丢失的风险。与之相对,如果确定这个节点是能恢复的,但可能半小时之内来不及,则可以把
max-store-down-time
临时调整为比较大的值,这样能避免超时之后产生不必要的副本补充,造成资源浪费。
- 调度速度受限于 limit 配置。可以适当调大
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论