众所周知,PD(github.com/pingcap/pd) 是整个 TiDB 集群的核心,负责全局元信息的存储以及 TiKV 集群负载均衡调度,本文将详细介绍 PD 调度系统的原理,并通过几个典型场景的分析和处理方式,分享调度策略的最佳实践和调优方法,帮助大家在使用过程中快速定位问题。本文内容基于 3.0 版本,更早的版本(2.x)缺少部分功能的支持,但是基本原理类似,也可以以本文作为参考。
PD 调度原理
概念
首先我们介绍一下调度系统涉及到的相关概念,理解这些概念以及它们相互之间的关系,有助于在实践中快速定位问题并通过配置进行调整。
Store
PD 中的 Store 指的是集群中的存储节点,也就是 tikv-server 实例。注意 Store 与 TiKV 实例是严格一一对应的,即使在同一主机甚至同一块磁盘部署多个 TiKV 实例,这些实例也会对应不同的 Store。 Region Peer Raft Group 每个 Region 负责维护集群的一段连续数据(默认配置下平均约 96 MiB),每份数据会在不同的 Store 存储多个副本(默认配置是 3 副本),每个副本称为 Peer。同一个 Region 的多个 Peer 通过 raft 协议进行数据同步,所以 Peer 也用来指代 raft 实例中的成员。TiKV 使用 multi-raft 模式来管理数据,即每个 Region 都对应一个独立运行的 raft 实例,我们也把这样的一个 raft 实例叫做一个 Raft Group。 Leader Follower Learner 它们分别对应 Peer 的三种角色。其中 Leader 负责响应客户端的读写请求;Follower 被动地从 Leader 同步数据,当 Leader 失效时会进行选举产生新的 Leader;Learner 是一种特殊的角色,它只参与同步 raft log 而不参与投票,在目前的实现中只短暂存在于添加副本的中间步骤。 Region Split TiKV 集群中的 Region 不是一开始就划分好的,而是随着数据写入逐渐分裂生成的,分裂的过程被称为 Region Split。 其机制是集群初始化时构建一个初始 Region 覆盖整个 key space,随后在运行过程中每当 Region 数据达到一定量之后就通过 Split 产生新的 Region。 Pending Down Pending 和 Down 是 Peer 可能出现的两种特殊状态。其中 Pending 表示 Follower 或 Learner 的 raft log 与 Leader 有较大差距,Pending 状态的 Follower 无法被选举成 Leader。Down 是指 Leader 长时间没有收到对应 Peer 的消息,通常意味着对应节点发生了宕机或者网络隔离。 Scheduler Scheduler(调度器)是 PD 中生成调度的组件。PD 中每个调度器是独立运行的,分别服务于不同的调度目的。常用的调度器及其调用目标有: balance-leader-scheduler
:保持不同节点的 Leader 均衡。balance-region-scheduler
:保持不同节点的 Peer 均衡。hot-region-scheduler
:保持不同节点的读写热点 Region 均衡。evict-leader-{store-id}
:驱逐某个节点的所有 Leader。(常用于滚动升级)Operator Operator 是应用于一个 Region 的,服务于某个调度目的的一系列操作的集合。例如“将 Region 2 的 Leader 迁移至 Store 5”,“将 Region 2 的副本迁移到 Store 1, 4, 5” 等。 Operator 可以是由 Scheduler 通过计算生成的,也可以是由外部 API 创建的。 Operator Step Operator Step 是 Operator 执行过程的一个步骤,一个 Operator 常常会包含多个 Operator Step。 目前 PD 可生成的 Step 包括: TransferLeader
:将 Region Leader 迁移至指定 PeerAddPeer
:在指定 Store 添加 FollowerRemovePeer
:删除一个 Region PeerAddLearner
:在指定 Store 添加 Region LearnerPromoteLearner
:将指定 Learner 提升为 FollowerSplitRegion
:将指定 Region 一分为二
调度流程
StoreHeartbeat和
RegionHeartbeat两种心跳消息。其中
StoreHeartbeat包含了 Store 的基本信息,容量,剩余空间,读写流量等数据,
RegionHeartbeat包含了 Region 的范围,副本分布,副本状态,数据量,读写流量等数据。PD 将这些信息梳理并转存供调度来决策。
不往断连中、下线中、繁忙、空间不足、在大量收发 snapshot 等各种异常状态的 Store 添加副本 Balance 时不选择状态异常的 Region 不尝试把 Leader 转移给 Pending Peer 不尝试直接移除 Leader 不破坏 Region 各种副本的物理隔离 不破坏 Label property 等约束
OperatorController管理的一个等待队列。
OperatorController会根据配置以一定的并发从等待队列中取出 Operator 进行执行,执行的过程就是依次把每个 Operator Step 下发给对应 Region 的 Leader。
Balance
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由于要考虑不同节点存储容量可能不一致的情况,会分三种情况,当空间富余时使用数据量计算得分(使不同节点数据量基本上均衡),当空间不足时由使用剩余空间计算得分(使不同节点剩余空间基本均衡),处于中间态时则同时考虑两个因素做加权和当作得分。
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,然后再用与 Balance 类似的方式把这些 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
mergeChecker负责,其过程与
replicaChecker类似,也是在后台遍历,发现连续的小 Region 后发起调度。
查询调度状态
Operator 状态
Schedule Operator Create
:展示 Operator 的创建情况,从名称可以知道 Operator 是哪个调度器创建的以及创建的原因。Operator finish duration
:展示了 Operator 执行耗时的情况Operator Step duration
:展示不同 Operator Step 执行耗时的情况
operator show
:查询当前调度生成的所有 Operatoroperator show [admin | leader | region]
:按照类型查询 Operator
Balance 状态
Store Leader/Region score
:展示每个 Store 的得分Store Leader/Region count
:展示每个 Store 的 Leader/Region 数量Store available
:展示每个 Store 的剩余空间
热点调度状态
Hot write Region’s leader/peer distribution
:展示了写热点 Region 的 Leader/Peer 分布情况Hot read Region’s leader distribution
:展示了读热点 Region 的 Leader 分布情况
hot read
:查询读热点 Region 信息hot write
:查询写热点 Region 信息hot store
:按 Store 统计热点分布情况region topread [limit]
:查询当前读流量最大的 Regionregion topwrite [limit]
:查询当前写流量最大的 Region
Region 健康度
region check miss-peer
:缺副本的 Regionregion check extra-peer
:多副本的 Regionregion check down-peer
:有副本状态为 Down 的 Regionregion check pending-peer
:有副本状态为 Pending 的 Region
调度策略控制
启停调度器
scheduler show
:显示当前系统中的 Schedulerscheduler remove balance-leader-scheduler
:删除(停用)balance leader 调度器scheduler add evict-leader-scheduler-1
:添加移除 Store 1 的所有 Leader 的调度器
手动添加 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
调度参数调整
config show命令可以查看所有的调度参数,执行
config set {key} {value}可以调整对应参数的值。这里举例说明常见的参数,更详情的说明请参考 PD 调度参数指南:
leader-schedule-limit
:控制 Transfer Leader 调度的并发数region-schedule-limit
:控制增删 Peer 调度的并发数disable-replace-offline-replica
:停止处理节点下线的调度disable-location-replacement
:停止处理调整 Region 隔离级别相关的调度max-snapshot-count
:每个 Store 允许的最大收发 Snapshot 的并发数
典型场景分析与处理
1. Leader Region 分布不均衡
存在热点导致负载不均衡。需要根据热点调度相关的信息进一步分析,可以参考下文热点调度的部分。 存在大量的空 Region 或小 Region,导致不同 Store 的 Leader 数量差别特别大,导致 raftstore 负担过重。需要开启 Region Merge 并尽可能加速合并,可以参考下文关于 Region Merge 的部分。 不同 Store 的软硬件环境存在差异。可以酌情调整 leader-weight
和region-weight
来控制 Leader Region 的分布。其他不明原因。也可以使用调整权重这个兜底的方法,通过调整 leader-weight 和 region-weight 来调整至用户觉得合理的分布。
调度速度受限于 limit 配置。PD 默认配置的 limit 比较保守,在不对正常业务造成显著影响的前提下,可以酌情将 leader-schedule-limit
或region-schedule-limit
调大一些,此外,max-pending-peer-count
以及max-snapshot-count
限制也可以放宽。系统中同时运行有其它的调度任务产生竞争,导致 balance 速度上不去。这种情况下如果 balance 调度的优先级更高,可以先停掉其他的调度或者限制其他调度的速度。例如 Region 没均衡的情况下做下线节点操作,下线的调度与 Region Balance 会抢占 region-schedule-limit
配额,此时我们可以把replica-schedule-limit
调小将下线调度的速度限制住,或者干脆设置disable-replace-offline-replica = true
来暂时关闭下线流程。调度执行得太慢。可以检查 Operator Step 的耗时来进行判断。通常不涉及到收发 Snapshot 的 Step(比如 TransferLeader
,RemovePeer
,PromoteLearner
等)的完成时间应该在毫秒级,涉及到 Snapshot 的 Step(如AddLearner
,AddPeer
等)的完成时间为数十秒。如果耗时明显过高,可能是 TiKV 压力过大或者网络等方面的瓶颈导致的,需要具体情况具体分析。
调度器被未启用。比如对应的 Scheduler 被删除了,或者 limit 被设置为 0
。由于其它约束无法进行调度。比如系统中有 evict-leader-scheduler
,此时无法把 Leader 迁移至对应的 Store。再比如设置了 Label property,也会导致部分 Store 不接受 Leader。集群拓扑的限制导致无法均衡。比如 3 副本 3 数据中心的集群,由于副本隔离的限制,每个 Region 的 3 个副本都分别分布在不同的数据中心,假如这 3 个数据中心的 Store 数不一样,最后调度就会收敛在每个数据中心均衡,但是全局不均衡的状态。
2. 节点下线速度慢
调度速度受限于 limit 配置。下线对应的 limit 参数是 replica-schedule-limit
,可以把它适当调大。与 Balance 类似,max-pending-peer-count
以及max-snapshot-count
限制同样也可以放宽。系统中同时运行有其它的调度任务产生竞争,或者调度执行得太慢了。处理方法在上一节已经介绍过了,不再赘述。 下线单个节点时,由于待操作的 Region 有很大一部分(3 副本配置下约 1/3)的 Leader 都集中在下线的节点上,下线速度会受限于这个单点生成 Snapshot 的速度。可以通过手动给这个节点添加一个 evict-leader
调度迁走 Leader 来加速。
下线调度被关闭,或者 replica-schedule-limit
被设为 0。找不到节点来转移 Region。例如相同 Label 的替代节点容量都大于 80%,PD 为了避免爆盘的风险会停止调度。这种情况需要添加更多节点,或者删除一些数据释放空间。
3. 节点上线速度慢
4. 热点分布不均匀
hot-region-schedule-limit,并减少其他调度器的 limit 配额,从而加快热点调度的速度。还有
hot-region-cache-hits-threshold调小一些可以使 PD 对流量的变化更快做出反应。
split-region调度将这样的 Region 拆开。
scatter-range-scheduler来使得这个 table 的所有 Region 均匀分布。TiDB 也在其 HTTP API 中提供了相关接口来简化这个操作,具体可以参考 TiDB HTTP API 文档。
5. Region Merge 速度慢
merge-schedule-limit及
region-schedule-limit),或者是与其他调度器产生了竞争,处理方法不再赘述了。
max-merge-region-size和
max-merge-region-keys调整为较小值来加快 Merge 速度。这是因为 Merge 的过程涉及到副本迁移,于是 Merge 的 Region 越小,速度就越快。如果 Merge Operator 生成的速度已经有几百 opm,想进一步加快,还可以把
patrol-region-interval调整为 "10ms" ,这个能加快巡检 Region 的速度,但是会消耗更多的 CPU。
TiKV split-region-on-table 设为 falsePD namespace-classifier 设为 “”
approximate_keys在特定情况下(大部分发生在 drop table 之后)统计不准确,造成 keys 的统计值很大,无法满足
max-merge-region-keys的约束,可以把
max-merge-region-keys这个条件放开,调成很大的值来绕过这个问题。
6. TiKV 节点故障处理策略
max-store-down-time配置调整),将此节点设置为
Down状态,并开始为涉及到的 Region 补充副本。
max-store-down-time临时调整为比较大的值,这样能避免超时之后产生不必要的补副本产生资源浪费。
总结





