From 5a50401fd6dc669bdcdb363663813bd3e6210a44 Mon Sep 17 00:00:00 2001 From: nolouch Date: Wed, 20 May 2020 21:13:03 +0800 Subject: [PATCH 1/7] add scheduling overview from tidb in action Signed-off-by: nolouch --- tidb-scheduling.md | 135 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) diff --git a/tidb-scheduling.md b/tidb-scheduling.md index e69de29bb2d1..fa37ced6551a 100644 --- a/tidb-scheduling.md +++ b/tidb-scheduling.md @@ -0,0 +1,135 @@ +--- +title: 调度 +category: reference +aliases: ['/docs-cn/dev/reference/architecture/scheduling-overview/'] +--- + +## 调度概述 +本文介绍一下 PD 这个神秘的模块。这部分比较复杂,很多东西大家平时不会想到,也很少在其他文章中见到类似东西的描述。我们还是按照前两篇的思路,先讲我们需要什么样的功能,再讲我们如何实现,大家带着需求去看实现,会更容易的理解我们做这些设计时背后的考量。 + +### 为什么要进行调度 +TiKV 集群是 TiDB 数据库的分布式 KV 存储引擎,数据以 Region 为单位进行复制和管理,每个 Region 会有多个 Replica(副本),这些 Replica 会分布在不同的 TiKV 节点上,其中 Leader 负责读/写,Follower 负责同步 Leader 发来的 raft log。了解了这些信息后,请思考下面这些问题: + +* 如何保证同一个 Region 的多个 Replica 分布在不同的节点上?更进一步,如果在一台机器上启动多个 TiKV 实例,会有什么问题? +* TiKV 集群进行跨机房部署的时候,如何保证一个机房掉线,不会丢失 Raft Group 的多个 Replica? +* 添加一个节点进入 TiKV 集群之后,如何将集群中其他节点上的数据搬过来? +* 当一个节点掉线时,会出现什么问题?整个集群需要做什么事情? + * 从节点的恢复时间来看 + * 如果节点只是短暂掉线(重启服务),如何处理? + * 如果节点是长时间掉线(磁盘故障,数据全部丢失),如何处理? + * 假设集群需要每个 Raft Group 有 N 个副本,从单个 Raft Group 的 Replica 个数来看 + * Replica 数量不够(例如节点掉线,失去副本),如何处理? + * Replica 数量过多(例如掉线的节点又恢复正常,自动加入集群),如何处理? +* 读/写都是通过 Leader 进行,如果 Leader 只集中在少量节点上,会对集群有什么影响? +* 并不是所有的 Region 都被频繁的访问,可能访问热点只在少数几个 Region,这个时候我们需要做什么? +* 集群在做负载均衡的时候,往往需要搬迁数据,这种数据的迁移会不会占用大量的网络带宽、磁盘 IO 以及 CPU,进而影响在线服务? + +这些问题单独拿出可能都能找到简单的解决方案,但是混杂在一起,就不太好解决。有的问题貌似只需要考虑单个 Raft Group 内部的情况,比如根据副本数量是否充足来决定是否需要添加副本,但是实际上这个副本添加在哪里,是需要考虑全局信息的。同时整个系统也是在动态变化,Region 分裂、节点加入、节点失效、访问热点变化等情况会不断发生,整个调度系统也需要在动态中不断向最优状态前进,如果没有一个掌握全局信息,可以对全局进行调度,并且可以配置的组件,就很难满足这些需求。因此我们需要一个中心节点,来对系统的整体状况进行把控和调整,所以有了 PD 这个模块。 + +### 调度的需求 +上面罗列了一大堆问题,我们先进行分类和整理。总体来看,问题有两大类: + +**作为一个分布式高可用存储系统,必须满足的需求,包括四种:** + +* 副本数量不能多也不能少 +* 副本需要分布在不同的机器上 +* 新加节点后,可以将其他节点上的副本迁移过来 +* 自动下线失效节点,同时将该节点的数据迁移走 + +**作为一个良好的分布式系统,需要优化的地方,包括:** + +* 维持整个集群的 Leader 分布均匀 +* 维持每个节点的储存容量均匀 +* 维持访问热点分布均匀 +* 控制负载均衡的速度,避免影响在线服务 +* 管理节点状态,包括手动上线/下线节点 + +满足第一类需求后,整个系统将具备强大的容灾功能。满足第二类需求后,可以使得系统整体的负载更加均匀,管理更加容易方便。 + +为了满足这些需求,首先我们需要收集足够的信息,比如每个节点的状态、每个 Raft Group 的信息、业务访问操作的统计等;其次需要设置一些策略,PD 根据这些信息以及调度的策略,制定出尽量满足前面所述需求的调度计划;最后需要一些基本的操作,来完成调度计划。 + +### 调度的基本操作 +调度的基本操作指的是为了满足调度的策略,我们有哪些功能可以用。这是整个调度的基础,了解了手里有什么样的锤子,才知道用什么样的姿势去砸钉子。 + +上述调度需求看似复杂,但是整理下来无非是下面三个操作: + +* 增加一个 Replica +* 删除一个 Replica +* 将 Leader 角色在一个 Raft Group 的不同 Replica 之间 transfer(迁移)。 + +刚好 Raft 协议通过 AddReplica、RemoveReplica、TransferLeader 这三个命令,可以支撑上述三种基本操作。 + +### 信息收集 +调度依赖于整个集群信息的收集,简单来说,我们需要知道每个 TiKV 节点的状态以及每个 Region 的状态。TiKV 集群会向 PD 汇报两类消息,TiKV 节点信息和 Region 信息: + +**每个 TiKV 节点会定期向 PD 汇报节点的状态信息** + +TiKV 节点(Store)与 PD 之间存在心跳包,一方面 PD 通过心跳包检测每个 Store 是否存活,以及是否有新加入的 Store;另一方面,心跳包中也会携带这个 [Store 的状态信息](https://github.com/pingcap/kvproto/blob/release-3.1/proto/pdpb.proto#L421),主要包括: + +* 总磁盘容量 +* 可用磁盘容量 +* 承载的 Region 数量 +* 数据写入/读取速度 +* 发送/接受的 Snapshot 数量(Replica 之间可能会通过 Snapshot 同步数据) +* 是否过载 +* labels 标签信息(标签是具备层级关系的一系列 Tag) + +**每个 Raft Group 的 Leader 会定期向 PD 汇报 Region 的状态信息** + +每个 Raft Group 的 Leader 和 PD 之间存在心跳包,用于汇报这个[ Region 的状态](https://github.com/pingcap/kvproto/blob/release-3.1/proto/pdpb.proto#L271),主要包括下面几点信息: + +* Leader 的位置 +* Followers 的位置 +* 掉线 Replica 的个数 +* 数据写入/读取的速度 + +PD 不断的通过这两类心跳消息收集整个集群的信息,再以这些信息作为决策的依据。除此之外,PD 还可以通过管理接口接受额外的信息,用来做更准确的决策。比如当某个 Store 的心跳包中断的时候,PD 并不能判断这个节点是临时失效还是永久失效,只能经过一段时间的等待(默认是 30 分钟),如果一直没有心跳包,就认为该 Store 已经下线,再决定需要将这个 Store 上面的 Region 都调度走。但是有的时候,是运维人员主动将某台机器下线,这个时候,可以通过 PD 的管理接口通知 PD 该 Store 不可用,PD 就可以马上判断需要将这个 Store 上面的 Region 都调度走。 + +### 调度的策略 +PD 收集了这些信息后,还需要一些策略来制定具体的调度计划。 + +**一个 Region 的 Replica 数量正确** + +当 PD 通过某个 Region Leader 的心跳包发现这个 Region 的 Replica 数量不满足要求时,需要通过 Add/Remove Replica 操作调整 Replica 数量。出现这种情况的可能原因是: + +* 某个节点掉线,上面的数据全部丢失,导致一些 Region 的 Replica 数量不足 +* 某个掉线节点又恢复服务,自动接入集群,这样之前已经补足了 Replica 的 Region 的 Replica 数量多过,需要删除某个 Replica +* 管理员调整了副本策略,修改了 [max-replicas](https://github.com/pingcap/pd/blob/v4.0.0-beta/conf/config.toml#L95) 的配置 + +**一个 Raft Group 中的多个 Replica 不在同一个位置** + +注意这里用的是『同一个位置』而不是『同一个节点』。在一般情况下,PD 只会保证多个 Replica 不落在一个节点上,以避免单个节点失效导致多个 Replica 丢失。在实际部署中,还可能出现下面这些需求: + +* 多个节点部署在同一台物理机器上 +* TiKV 节点分布在多个机架上,希望单个机架掉电时,也能保证系统可用性 +* TiKV 节点分布在多个 IDC 中,希望单个机房掉电时,也能保证系统可用性 + +这些需求本质上都是某一个节点具备共同的位置属性,构成一个最小的『容错单元』,我们希望这个单元内部不会存在一个 Region 的多个 Replica。这个时候,可以给节点配置 [labels](https://github.com/tikv/tikv/blob/v4.0.0-beta/etc/config-template.toml#L140) 并且通过在 PD 上配置 [location-labels](https://github.com/pingcap/pd/blob/v4.0.0-beta/conf/config.toml#L100) 来指名哪些 label 是位置标识,需要在 Replica 分配的时候尽量保证一个 Region 的多个 Replica 不会分布在具有相同的位置标识的节点上。 + +**副本在 Store 之间的分布均匀分配** + +由于每个region副本中存储的数据容量上限是固定的,所以我们通过维持每个节点上面副本数量的均衡,使得各节点间承载的数据更均衡。 + +**Leader 数量在 Store 之间均匀分配** + +Raft 协议要求读取和写入都通过 Leader 进行,所以计算的负载主要在 Leader 上面,PD 会尽可能将 Leader 在节点间分散开。 + +**访问热点数量在 Store 之间均匀分配** + +每个 Store 以及 Region Leader 在上报信息时携带了当前访问负载的信息,比如 Key 的读取/写入速度。PD 会检测出访问热点,且将其在节点之间分散开。 + +**各个 Store 的存储空间占用大致相等** + +每个 Store 启动的时候都会指定一个 Capacity 参数,表明这个 Store 的存储空间上限,PD 在做调度的时候,会考虑节点的存储空间剩余量。 + +**控制调度速度,避免影响在线服务** + +调度操作需要耗费 CPU、内存、磁盘 IO 以及网络带宽,我们需要避免对线上服务造成太大影响。PD 会对当前正在进行的操作数量进行控制,默认的速度控制是比较保守的,如果希望加快调度(比如停服务升级或者增加新节点,希望尽快调度),那么可以通过调节 PD 参数动加快调度速度。 + +### 调度的实现 +了解了上面这些信息后,接下来我们看一下整个调度的流程。 + +PD 不断的通过 Store 或者 Leader 的心跳包收集整个集群信息,并且根据这些信息以及调度策略生成调度操作序列。每次收到 Region Leader 发来的心跳包时,PD 都会检查这个 Region 是否有待进行的操作,然后通过心跳包的回复消息,将需要进行的操作返回给 Region Leader,并在后面的心跳包中监测执行结果。注意这里的操作只是给 Region Leader 的建议,并不保证一定能得到执行,具体是否会执行以及什么时候执行,由 Region Leader 根据当前自身状态来定。 + +### 总结 +本篇文章讲的东西,大家可能平时很少会在其他文章中看到,每一个设计都有背后的考量,希望大家能了解到一个分布式存储系统在做调度的时候,需要考虑哪些东西,如何将策略、实现进行解耦,更灵活的支持策略的扩展。 \ No newline at end of file From add7907444363741e4042778d97686edbf8edd6c Mon Sep 17 00:00:00 2001 From: nolouch Date: Thu, 21 May 2020 14:32:28 +0800 Subject: [PATCH 2/7] address comments Signed-off-by: nolouch --- ...heduling.md => tidb-scheduling-overview.md | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) rename tidb-scheduling.md => tidb-scheduling-overview.md (93%) diff --git a/tidb-scheduling.md b/tidb-scheduling-overview.md similarity index 93% rename from tidb-scheduling.md rename to tidb-scheduling-overview.md index fa37ced6551a..32ab548d9b5f 100644 --- a/tidb-scheduling.md +++ b/tidb-scheduling-overview.md @@ -1,25 +1,27 @@ --- -title: 调度 +title: 调度概述 category: reference aliases: ['/docs-cn/dev/reference/architecture/scheduling-overview/'] --- ## 调度概述 + 本文介绍一下 PD 这个神秘的模块。这部分比较复杂,很多东西大家平时不会想到,也很少在其他文章中见到类似东西的描述。我们还是按照前两篇的思路,先讲我们需要什么样的功能,再讲我们如何实现,大家带着需求去看实现,会更容易的理解我们做这些设计时背后的考量。 ### 为什么要进行调度 + TiKV 集群是 TiDB 数据库的分布式 KV 存储引擎,数据以 Region 为单位进行复制和管理,每个 Region 会有多个 Replica(副本),这些 Replica 会分布在不同的 TiKV 节点上,其中 Leader 负责读/写,Follower 负责同步 Leader 发来的 raft log。了解了这些信息后,请思考下面这些问题: * 如何保证同一个 Region 的多个 Replica 分布在不同的节点上?更进一步,如果在一台机器上启动多个 TiKV 实例,会有什么问题? * TiKV 集群进行跨机房部署的时候,如何保证一个机房掉线,不会丢失 Raft Group 的多个 Replica? * 添加一个节点进入 TiKV 集群之后,如何将集群中其他节点上的数据搬过来? * 当一个节点掉线时,会出现什么问题?整个集群需要做什么事情? - * 从节点的恢复时间来看 - * 如果节点只是短暂掉线(重启服务),如何处理? - * 如果节点是长时间掉线(磁盘故障,数据全部丢失),如何处理? - * 假设集群需要每个 Raft Group 有 N 个副本,从单个 Raft Group 的 Replica 个数来看 - * Replica 数量不够(例如节点掉线,失去副本),如何处理? - * Replica 数量过多(例如掉线的节点又恢复正常,自动加入集群),如何处理? + * 从节点的恢复时间来看 + * 如果节点只是短暂掉线(重启服务),如何处理? + * 如果节点是长时间掉线(磁盘故障,数据全部丢失),如何处理? + * 假设集群需要每个 Raft Group 有 N 个副本,从单个 Raft Group 的 Replica 个数来看 + * Replica 数量不够(例如节点掉线,失去副本),如何处理? + * Replica 数量过多(例如掉线的节点又恢复正常,自动加入集群),如何处理? * 读/写都是通过 Leader 进行,如果 Leader 只集中在少量节点上,会对集群有什么影响? * 并不是所有的 Region 都被频繁的访问,可能访问热点只在少数几个 Region,这个时候我们需要做什么? * 集群在做负载均衡的时候,往往需要搬迁数据,这种数据的迁移会不会占用大量的网络带宽、磁盘 IO 以及 CPU,进而影响在线服务? @@ -27,6 +29,7 @@ TiKV 集群是 TiDB 数据库的分布式 KV 存储引擎,数据以 Region 为 这些问题单独拿出可能都能找到简单的解决方案,但是混杂在一起,就不太好解决。有的问题貌似只需要考虑单个 Raft Group 内部的情况,比如根据副本数量是否充足来决定是否需要添加副本,但是实际上这个副本添加在哪里,是需要考虑全局信息的。同时整个系统也是在动态变化,Region 分裂、节点加入、节点失效、访问热点变化等情况会不断发生,整个调度系统也需要在动态中不断向最优状态前进,如果没有一个掌握全局信息,可以对全局进行调度,并且可以配置的组件,就很难满足这些需求。因此我们需要一个中心节点,来对系统的整体状况进行把控和调整,所以有了 PD 这个模块。 ### 调度的需求 + 上面罗列了一大堆问题,我们先进行分类和整理。总体来看,问题有两大类: **作为一个分布式高可用存储系统,必须满足的需求,包括四种:** @@ -49,6 +52,7 @@ TiKV 集群是 TiDB 数据库的分布式 KV 存储引擎,数据以 Region 为 为了满足这些需求,首先我们需要收集足够的信息,比如每个节点的状态、每个 Raft Group 的信息、业务访问操作的统计等;其次需要设置一些策略,PD 根据这些信息以及调度的策略,制定出尽量满足前面所述需求的调度计划;最后需要一些基本的操作,来完成调度计划。 ### 调度的基本操作 + 调度的基本操作指的是为了满足调度的策略,我们有哪些功能可以用。这是整个调度的基础,了解了手里有什么样的锤子,才知道用什么样的姿势去砸钉子。 上述调度需求看似复杂,但是整理下来无非是下面三个操作: @@ -60,6 +64,7 @@ TiKV 集群是 TiDB 数据库的分布式 KV 存储引擎,数据以 Region 为 刚好 Raft 协议通过 AddReplica、RemoveReplica、TransferLeader 这三个命令,可以支撑上述三种基本操作。 ### 信息收集 + 调度依赖于整个集群信息的收集,简单来说,我们需要知道每个 TiKV 节点的状态以及每个 Region 的状态。TiKV 集群会向 PD 汇报两类消息,TiKV 节点信息和 Region 信息: **每个 TiKV 节点会定期向 PD 汇报节点的状态信息** @@ -76,7 +81,7 @@ TiKV 节点(Store)与 PD 之间存在心跳包,一方面 PD 通过心跳 **每个 Raft Group 的 Leader 会定期向 PD 汇报 Region 的状态信息** -每个 Raft Group 的 Leader 和 PD 之间存在心跳包,用于汇报这个[ Region 的状态](https://github.com/pingcap/kvproto/blob/release-3.1/proto/pdpb.proto#L271),主要包括下面几点信息: +每个 Raft Group 的 Leader 和 PD 之间存在心跳包,用于汇报这个[Region 的状态](https://github.com/pingcap/kvproto/blob/release-3.1/proto/pdpb.proto#L271),主要包括下面几点信息: * Leader 的位置 * Followers 的位置 @@ -86,6 +91,7 @@ TiKV 节点(Store)与 PD 之间存在心跳包,一方面 PD 通过心跳 PD 不断的通过这两类心跳消息收集整个集群的信息,再以这些信息作为决策的依据。除此之外,PD 还可以通过管理接口接受额外的信息,用来做更准确的决策。比如当某个 Store 的心跳包中断的时候,PD 并不能判断这个节点是临时失效还是永久失效,只能经过一段时间的等待(默认是 30 分钟),如果一直没有心跳包,就认为该 Store 已经下线,再决定需要将这个 Store 上面的 Region 都调度走。但是有的时候,是运维人员主动将某台机器下线,这个时候,可以通过 PD 的管理接口通知 PD 该 Store 不可用,PD 就可以马上判断需要将这个 Store 上面的 Region 都调度走。 ### 调度的策略 + PD 收集了这些信息后,还需要一些策略来制定具体的调度计划。 **一个 Region 的 Replica 数量正确** @@ -127,9 +133,11 @@ Raft 协议要求读取和写入都通过 Leader 进行,所以计算的负载 调度操作需要耗费 CPU、内存、磁盘 IO 以及网络带宽,我们需要避免对线上服务造成太大影响。PD 会对当前正在进行的操作数量进行控制,默认的速度控制是比较保守的,如果希望加快调度(比如停服务升级或者增加新节点,希望尽快调度),那么可以通过调节 PD 参数动加快调度速度。 ### 调度的实现 + 了解了上面这些信息后,接下来我们看一下整个调度的流程。 PD 不断的通过 Store 或者 Leader 的心跳包收集整个集群信息,并且根据这些信息以及调度策略生成调度操作序列。每次收到 Region Leader 发来的心跳包时,PD 都会检查这个 Region 是否有待进行的操作,然后通过心跳包的回复消息,将需要进行的操作返回给 Region Leader,并在后面的心跳包中监测执行结果。注意这里的操作只是给 Region Leader 的建议,并不保证一定能得到执行,具体是否会执行以及什么时候执行,由 Region Leader 根据当前自身状态来定。 ### 总结 + 本篇文章讲的东西,大家可能平时很少会在其他文章中看到,每一个设计都有背后的考量,希望大家能了解到一个分布式存储系统在做调度的时候,需要考虑哪些东西,如何将策略、实现进行解耦,更灵活的支持策略的扩展。 \ No newline at end of file From c89d8d10aea212a874f207faabdacd5fd3cb8aed Mon Sep 17 00:00:00 2001 From: TomShawn <41534398+TomShawn@users.noreply.github.com> Date: Thu, 21 May 2020 14:44:12 +0800 Subject: [PATCH 3/7] change back file name to fix ci --- tidb-scheduling-overview.md => tidb-scheduling.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tidb-scheduling-overview.md => tidb-scheduling.md (100%) diff --git a/tidb-scheduling-overview.md b/tidb-scheduling.md similarity index 100% rename from tidb-scheduling-overview.md rename to tidb-scheduling.md From b2eb41a067d0579e25dcca803f84680e54586973 Mon Sep 17 00:00:00 2001 From: nolouch Date: Thu, 21 May 2020 15:54:21 +0800 Subject: [PATCH 4/7] remove alias Signed-off-by: nolouch --- tidb-scheduling.md | 1 - 1 file changed, 1 deletion(-) diff --git a/tidb-scheduling.md b/tidb-scheduling.md index 32ab548d9b5f..44edb0ccee96 100644 --- a/tidb-scheduling.md +++ b/tidb-scheduling.md @@ -1,7 +1,6 @@ --- title: 调度概述 category: reference -aliases: ['/docs-cn/dev/reference/architecture/scheduling-overview/'] --- ## 调度概述 From 019b4b5754e8aa5d5779854be9d67e7bba433194 Mon Sep 17 00:00:00 2001 From: nolouch Date: Tue, 26 May 2020 18:04:21 +0800 Subject: [PATCH 5/7] address comments Signed-off-by: nolouch --- tidb-scheduling.md | 58 +++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/tidb-scheduling.md b/tidb-scheduling.md index 44edb0ccee96..9ef9de3498f3 100644 --- a/tidb-scheduling.md +++ b/tidb-scheduling.md @@ -3,42 +3,42 @@ title: 调度概述 category: reference --- -## 调度概述 +## 说调度 -本文介绍一下 PD 这个神秘的模块。这部分比较复杂,很多东西大家平时不会想到,也很少在其他文章中见到类似东西的描述。我们还是按照前两篇的思路,先讲我们需要什么样的功能,再讲我们如何实现,大家带着需求去看实现,会更容易的理解我们做这些设计时背后的考量。 +在[TiDB 整体架构](/tidb-architecture.md)中,主要介绍了 TiDB 项目的几个主要的组成部分,其中PD 是 TiDB 集群的管理模块,同时也负责集群数据的实时调度。本节向大家介绍一下 PD 的一些设计思想和关键概念。 ### 为什么要进行调度 TiKV 集群是 TiDB 数据库的分布式 KV 存储引擎,数据以 Region 为单位进行复制和管理,每个 Region 会有多个 Replica(副本),这些 Replica 会分布在不同的 TiKV 节点上,其中 Leader 负责读/写,Follower 负责同步 Leader 发来的 raft log。了解了这些信息后,请思考下面这些问题: -* 如何保证同一个 Region 的多个 Replica 分布在不同的节点上?更进一步,如果在一台机器上启动多个 TiKV 实例,会有什么问题? -* TiKV 集群进行跨机房部署的时候,如何保证一个机房掉线,不会丢失 Raft Group 的多个 Replica? -* 添加一个节点进入 TiKV 集群之后,如何将集群中其他节点上的数据搬过来? -* 当一个节点掉线时,会出现什么问题?整个集群需要做什么事情? +* 为了保证集群提高集群的空间利用率,需要根据 Region 的空间占用对 Replica 进行合理的分布 +* 集群进行跨机房部署的时候,要保证一个机房掉线,不会丢失 Raft Group 的多个 Replica +* 添加一个节点进入 TiKV 集群之后,需要合理地将集群中其他节点上的数据搬过来 +* 当一个节点掉线时,需要考虑快速稳定的进行容灾 * 从节点的恢复时间来看 - * 如果节点只是短暂掉线(重启服务),如何处理? - * 如果节点是长时间掉线(磁盘故障,数据全部丢失),如何处理? + * 如果节点只是短暂掉线(重启服务),是否需要进行调度 + * 如果节点是长时间掉线(磁盘故障,数据全部丢失),怎么进行调度 * 假设集群需要每个 Raft Group 有 N 个副本,从单个 Raft Group 的 Replica 个数来看 - * Replica 数量不够(例如节点掉线,失去副本),如何处理? - * Replica 数量过多(例如掉线的节点又恢复正常,自动加入集群),如何处理? -* 读/写都是通过 Leader 进行,如果 Leader 只集中在少量节点上,会对集群有什么影响? -* 并不是所有的 Region 都被频繁的访问,可能访问热点只在少数几个 Region,这个时候我们需要做什么? -* 集群在做负载均衡的时候,往往需要搬迁数据,这种数据的迁移会不会占用大量的网络带宽、磁盘 IO 以及 CPU,进而影响在线服务? + * Replica 数量不够(例如节点掉线,失去副本),需要选择适当的机器的进行补充 + * Replica 数量过多(例如掉线的节点又恢复正常,自动加入集群),需要合理的删除多余的副本 +* 读/写通过 Leader 进行,Leader 的分布影响请求的分布只集中 +* 并不是所有的 Region 都被频繁的访问,可能访问热点只在少数几个 Region,需要通过调度进行负载均衡 +* 集群在做负载均衡的时候,往往需要搬迁数据,这种数据的迁移会不会占用大量的网络带宽、磁盘 IO 以及 CPU,进而影响在线服务 -这些问题单独拿出可能都能找到简单的解决方案,但是混杂在一起,就不太好解决。有的问题貌似只需要考虑单个 Raft Group 内部的情况,比如根据副本数量是否充足来决定是否需要添加副本,但是实际上这个副本添加在哪里,是需要考虑全局信息的。同时整个系统也是在动态变化,Region 分裂、节点加入、节点失效、访问热点变化等情况会不断发生,整个调度系统也需要在动态中不断向最优状态前进,如果没有一个掌握全局信息,可以对全局进行调度,并且可以配置的组件,就很难满足这些需求。因此我们需要一个中心节点,来对系统的整体状况进行把控和调整,所以有了 PD 这个模块。 +这些问题单独拿出可能都能找到简单的解决方案,但是混杂在一起,就不太好解决。有的问题貌似只需要考虑单个 Raft Group 内部的情况,比如根据副本数量是否充足来决定是否需要添加副本,但是实际上这个副本添加在哪里,是需要考虑全局信息的。 +同时整个系统也是在动态变化的,数据的写入会造成 Region 分裂、删除则需要合并 Region、节点加入、节点失效、访问热点变化等情况会不断发生,整个调度系统也需要在动态中不断向最优状态前进,如果没有一个掌握全局信息,可以对全局进行调度,并且可以配置的组件,就很难满足这些需求。因此需要一个中心节点,来对系统的整体状况进行把控和调整,所以有了 PD 这个模块。 ### 调度的需求 -上面罗列了一大堆问题,我们先进行分类和整理。总体来看,问题有两大类: +上面罗列了一大堆问题,通过进行分类和整理,总体来看,问题有两大类: -**作为一个分布式高可用存储系统,必须满足的需求,包括四种:** +**作为一个分布式高可用存储系统,必须满足的需求,包括几种:** * 副本数量不能多也不能少 -* 副本需要分布在不同的机器上 -* 新加节点后,可以将其他节点上的副本迁移过来 -* 自动下线失效节点,同时将该节点的数据迁移走 +* 副本需要根据拓扑结构分布在不同属性的机器上 +* 节点宕机或异常能够自动合理快速地进行容灾 -**作为一个良好的分布式系统,需要优化的地方,包括:** +**作为一个良好的分布式系统,需要考虑的地方包括:** * 维持整个集群的 Leader 分布均匀 * 维持每个节点的储存容量均匀 @@ -46,13 +46,13 @@ TiKV 集群是 TiDB 数据库的分布式 KV 存储引擎,数据以 Region 为 * 控制负载均衡的速度,避免影响在线服务 * 管理节点状态,包括手动上线/下线节点 -满足第一类需求后,整个系统将具备强大的容灾功能。满足第二类需求后,可以使得系统整体的负载更加均匀,管理更加容易方便。 +满足第一类需求后,整个系统将具备强大的容灾功能。满足第二类需求后,可以使得系统整体的资源利用率更高且合理,具备良好的扩展性。 -为了满足这些需求,首先我们需要收集足够的信息,比如每个节点的状态、每个 Raft Group 的信息、业务访问操作的统计等;其次需要设置一些策略,PD 根据这些信息以及调度的策略,制定出尽量满足前面所述需求的调度计划;最后需要一些基本的操作,来完成调度计划。 +为了满足这些需求,首先需要收集足够的信息,比如每个节点的状态、每个 Raft Group 的信息、业务访问操作的统计等;其次需要设置一些策略,PD 根据这些信息以及调度的策略,制定出尽量满足前面所述需求的调度计划;最后需要一些基本的操作,来完成调度计划。 ### 调度的基本操作 -调度的基本操作指的是为了满足调度的策略,我们有哪些功能可以用。这是整个调度的基础,了解了手里有什么样的锤子,才知道用什么样的姿势去砸钉子。 +调度的基本操作指的是为了满足调度的策略,有哪些功能可以用,这是整个调度的基础,了解了手里有什么样的锤子,才知道用什么样的姿势去砸钉子。 上述调度需求看似复杂,但是整理下来无非是下面三个操作: @@ -64,7 +64,7 @@ TiKV 集群是 TiDB 数据库的分布式 KV 存储引擎,数据以 Region 为 ### 信息收集 -调度依赖于整个集群信息的收集,简单来说,我们需要知道每个 TiKV 节点的状态以及每个 Region 的状态。TiKV 集群会向 PD 汇报两类消息,TiKV 节点信息和 Region 信息: +调度依赖于整个集群信息的收集,简单来说,调度需要知道每个 TiKV 节点的状态以及每个 Region 的状态。TiKV 集群会向 PD 汇报两类消息,TiKV 节点信息和 Region 信息: **每个 TiKV 节点会定期向 PD 汇报节点的状态信息** @@ -76,7 +76,7 @@ TiKV 节点(Store)与 PD 之间存在心跳包,一方面 PD 通过心跳 * 数据写入/读取速度 * 发送/接受的 Snapshot 数量(Replica 之间可能会通过 Snapshot 同步数据) * 是否过载 -* labels 标签信息(标签是具备层级关系的一系列 Tag) +* labels 标签信息(标签是具备层级关系的一系列 Tag,能够[感知拓扑信息](/location-awareness.md)) **每个 Raft Group 的 Leader 会定期向 PD 汇报 Region 的状态信息** @@ -109,11 +109,11 @@ PD 收集了这些信息后,还需要一些策略来制定具体的调度计 * TiKV 节点分布在多个机架上,希望单个机架掉电时,也能保证系统可用性 * TiKV 节点分布在多个 IDC 中,希望单个机房掉电时,也能保证系统可用性 -这些需求本质上都是某一个节点具备共同的位置属性,构成一个最小的『容错单元』,我们希望这个单元内部不会存在一个 Region 的多个 Replica。这个时候,可以给节点配置 [labels](https://github.com/tikv/tikv/blob/v4.0.0-beta/etc/config-template.toml#L140) 并且通过在 PD 上配置 [location-labels](https://github.com/pingcap/pd/blob/v4.0.0-beta/conf/config.toml#L100) 来指名哪些 label 是位置标识,需要在 Replica 分配的时候尽量保证一个 Region 的多个 Replica 不会分布在具有相同的位置标识的节点上。 +这些需求本质上都是某一个节点具备共同的位置属性,构成一个最小的『容错单元』,希望这个单元内部不会存在一个 Region 的多个 Replica。这个时候,可以给节点配置 [labels](https://github.com/tikv/tikv/blob/v4.0.0-beta/etc/config-template.toml#L140) 并且通过在 PD 上配置 [location-labels](https://github.com/pingcap/pd/blob/v4.0.0-beta/conf/config.toml#L100) 来指名哪些 label 是位置标识,需要在 Replica 分配的时候尽量保证一个 Region 的多个 Replica 不会分布在具有相同的位置标识的节点上。 **副本在 Store 之间的分布均匀分配** -由于每个region副本中存储的数据容量上限是固定的,所以我们通过维持每个节点上面副本数量的均衡,使得各节点间承载的数据更均衡。 +由于每个region副本中存储的数据容量上限是固定的,通过维持每个节点上面副本数量的均衡,使得各节点间承载的数据更均衡。 **Leader 数量在 Store 之间均匀分配** @@ -129,11 +129,11 @@ Raft 协议要求读取和写入都通过 Leader 进行,所以计算的负载 **控制调度速度,避免影响在线服务** -调度操作需要耗费 CPU、内存、磁盘 IO 以及网络带宽,我们需要避免对线上服务造成太大影响。PD 会对当前正在进行的操作数量进行控制,默认的速度控制是比较保守的,如果希望加快调度(比如停服务升级或者增加新节点,希望尽快调度),那么可以通过调节 PD 参数动加快调度速度。 +调度操作需要耗费 CPU、内存、磁盘 IO 以及网络带宽,需要避免对线上服务造成太大影响。PD 会对当前正在进行的操作数量进行控制,默认的速度控制是比较保守的,如果希望加快调度(比如停服务升级或者增加新节点,希望尽快调度),那么可以通过调节 PD 参数动加快调度速度。 ### 调度的实现 -了解了上面这些信息后,接下来我们看一下整个调度的流程。 +了解了上面这些信息后,接下来看一下整个调度的流程。 PD 不断的通过 Store 或者 Leader 的心跳包收集整个集群信息,并且根据这些信息以及调度策略生成调度操作序列。每次收到 Region Leader 发来的心跳包时,PD 都会检查这个 Region 是否有待进行的操作,然后通过心跳包的回复消息,将需要进行的操作返回给 Region Leader,并在后面的心跳包中监测执行结果。注意这里的操作只是给 Region Leader 的建议,并不保证一定能得到执行,具体是否会执行以及什么时候执行,由 Region Leader 根据当前自身状态来定。 From 82e057c3667993595f12b60ef98e071f72ad83da Mon Sep 17 00:00:00 2001 From: TomShawn <41534398+TomShawn@users.noreply.github.com> Date: Tue, 26 May 2020 18:53:40 +0800 Subject: [PATCH 6/7] refine language and heading --- tidb-scheduling.md | 75 +++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/tidb-scheduling.md b/tidb-scheduling.md index 9ef9de3498f3..154d3e49f954 100644 --- a/tidb-scheduling.md +++ b/tidb-scheduling.md @@ -3,42 +3,43 @@ title: 调度概述 category: reference --- -## 说调度 +# 调度概述 -在[TiDB 整体架构](/tidb-architecture.md)中,主要介绍了 TiDB 项目的几个主要的组成部分,其中PD 是 TiDB 集群的管理模块,同时也负责集群数据的实时调度。本节向大家介绍一下 PD 的一些设计思想和关键概念。 +PD 是 TiDB 集群的管理模块,同时也负责集群数据的实时调度。本文档介绍一下 PD 的设计思想和关键概念。 -### 为什么要进行调度 +## 场景描述 -TiKV 集群是 TiDB 数据库的分布式 KV 存储引擎,数据以 Region 为单位进行复制和管理,每个 Region 会有多个 Replica(副本),这些 Replica 会分布在不同的 TiKV 节点上,其中 Leader 负责读/写,Follower 负责同步 Leader 发来的 raft log。了解了这些信息后,请思考下面这些问题: +TiKV 集群是 TiDB 数据库的分布式 KV 存储引擎,数据以 Region 为单位进行复制和管理,每个 Region 会有多个 Replica(副本),这些 Replica 会分布在不同的 TiKV 节点上,其中 Leader 负责读/写,Follower 负责同步 Leader 发来的 Raft log。 -* 为了保证集群提高集群的空间利用率,需要根据 Region 的空间占用对 Replica 进行合理的分布 -* 集群进行跨机房部署的时候,要保证一个机房掉线,不会丢失 Raft Group 的多个 Replica -* 添加一个节点进入 TiKV 集群之后,需要合理地将集群中其他节点上的数据搬过来 -* 当一个节点掉线时,需要考虑快速稳定的进行容灾 +除此之外,还需要考虑以下场景: + +* 为了提高集群的空间利用率,需要根据 Region 的空间占用对 Replica 进行合理的分布。 +* 集群进行跨机房部署的时候,要保证一个机房掉线,不会丢失 Raft Group 的多个 Replica。 +* 添加一个节点进入 TiKV 集群之后,需要合理地将集群中其他节点上的数据搬到新增节点。 +* 当一个节点掉线时,需要考虑快速稳定地进行容灾。 * 从节点的恢复时间来看 - * 如果节点只是短暂掉线(重启服务),是否需要进行调度 - * 如果节点是长时间掉线(磁盘故障,数据全部丢失),怎么进行调度 + * 如果节点只是短暂掉线(重启服务),是否需要进行调度。 + * 如果节点是长时间掉线(磁盘故障,数据全部丢失),如何进行调度。 * 假设集群需要每个 Raft Group 有 N 个副本,从单个 Raft Group 的 Replica 个数来看 - * Replica 数量不够(例如节点掉线,失去副本),需要选择适当的机器的进行补充 - * Replica 数量过多(例如掉线的节点又恢复正常,自动加入集群),需要合理的删除多余的副本 -* 读/写通过 Leader 进行,Leader 的分布影响请求的分布只集中 -* 并不是所有的 Region 都被频繁的访问,可能访问热点只在少数几个 Region,需要通过调度进行负载均衡 -* 集群在做负载均衡的时候,往往需要搬迁数据,这种数据的迁移会不会占用大量的网络带宽、磁盘 IO 以及 CPU,进而影响在线服务 + * Replica 数量不够(例如节点掉线,失去副本),需要选择适当的机器的进行补充。 + * Replica 数量过多(例如掉线的节点又恢复正常,自动加入集群),需要合理的删除多余的副本。 +* 读/写通过 Leader 进行,Leader 的分布只集中在少量几个节点会对集群造成影响。 +* 并不是所有的 Region 都被频繁的访问,可能访问热点只在少数几个 Region,需要通过调度进行负载均衡。 +* 集群在做负载均衡的时候,往往需要搬迁数据,这种数据的迁移可能会占用大量的网络带宽、磁盘 IO 以及 CPU,进而影响在线服务。 -这些问题单独拿出可能都能找到简单的解决方案,但是混杂在一起,就不太好解决。有的问题貌似只需要考虑单个 Raft Group 内部的情况,比如根据副本数量是否充足来决定是否需要添加副本,但是实际上这个副本添加在哪里,是需要考虑全局信息的。 -同时整个系统也是在动态变化的,数据的写入会造成 Region 分裂、删除则需要合并 Region、节点加入、节点失效、访问热点变化等情况会不断发生,整个调度系统也需要在动态中不断向最优状态前进,如果没有一个掌握全局信息,可以对全局进行调度,并且可以配置的组件,就很难满足这些需求。因此需要一个中心节点,来对系统的整体状况进行把控和调整,所以有了 PD 这个模块。 +以上问题和场景如果多个同时出现,就不太容易解决,因为需要考虑全局信息。同时整个系统也是在动态变化的,因此需要一个中心节点,来对系统的整体状况进行把控和调整,所以有了 PD 这个模块。 -### 调度的需求 +## 调度的需求 -上面罗列了一大堆问题,通过进行分类和整理,总体来看,问题有两大类: +对以上的问题和场景进行分类和整理,可归为以下两类: -**作为一个分布式高可用存储系统,必须满足的需求,包括几种:** +**第一类:作为一个分布式高可用存储系统,必须满足的需求,包括几种:** * 副本数量不能多也不能少 * 副本需要根据拓扑结构分布在不同属性的机器上 * 节点宕机或异常能够自动合理快速地进行容灾 -**作为一个良好的分布式系统,需要考虑的地方包括:** +**第二类:作为一个良好的分布式系统,需要考虑的地方包括:** * 维持整个集群的 Leader 分布均匀 * 维持每个节点的储存容量均匀 @@ -50,19 +51,17 @@ TiKV 集群是 TiDB 数据库的分布式 KV 存储引擎,数据以 Region 为 为了满足这些需求,首先需要收集足够的信息,比如每个节点的状态、每个 Raft Group 的信息、业务访问操作的统计等;其次需要设置一些策略,PD 根据这些信息以及调度的策略,制定出尽量满足前面所述需求的调度计划;最后需要一些基本的操作,来完成调度计划。 -### 调度的基本操作 - -调度的基本操作指的是为了满足调度的策略,有哪些功能可以用,这是整个调度的基础,了解了手里有什么样的锤子,才知道用什么样的姿势去砸钉子。 +## 调度的基本操作 -上述调度需求看似复杂,但是整理下来无非是下面三个操作: +调度的基本操作指的是为了满足调度的策略。上述调度需求可整理为以下三个操作: * 增加一个 Replica * 删除一个 Replica * 将 Leader 角色在一个 Raft Group 的不同 Replica 之间 transfer(迁移)。 -刚好 Raft 协议通过 AddReplica、RemoveReplica、TransferLeader 这三个命令,可以支撑上述三种基本操作。 +刚好 Raft 协议通过 `AddReplica`、`RemoveReplica`、`TransferLeader` 这三个命令,可以支撑上述三种基本操作。 -### 信息收集 +## 信息收集 调度依赖于整个集群信息的收集,简单来说,调度需要知道每个 TiKV 节点的状态以及每个 Region 的状态。TiKV 集群会向 PD 汇报两类消息,TiKV 节点信息和 Region 信息: @@ -87,9 +86,13 @@ TiKV 节点(Store)与 PD 之间存在心跳包,一方面 PD 通过心跳 * 掉线 Replica 的个数 * 数据写入/读取的速度 -PD 不断的通过这两类心跳消息收集整个集群的信息,再以这些信息作为决策的依据。除此之外,PD 还可以通过管理接口接受额外的信息,用来做更准确的决策。比如当某个 Store 的心跳包中断的时候,PD 并不能判断这个节点是临时失效还是永久失效,只能经过一段时间的等待(默认是 30 分钟),如果一直没有心跳包,就认为该 Store 已经下线,再决定需要将这个 Store 上面的 Region 都调度走。但是有的时候,是运维人员主动将某台机器下线,这个时候,可以通过 PD 的管理接口通知 PD 该 Store 不可用,PD 就可以马上判断需要将这个 Store 上面的 Region 都调度走。 +PD 不断的通过这两类心跳消息收集整个集群的信息,再以这些信息作为决策的依据。 + +除此之外,PD 还可以通过管理接口接受额外的信息,用来做更准确的决策。比如当某个 Store 的心跳包中断的时候,PD 并不能判断这个节点是临时失效还是永久失效,只能经过一段时间的等待(默认是 30 分钟),如果一直没有心跳包,就认为该 Store 已经下线,再决定需要将这个 Store 上面的 Region 都调度走。 -### 调度的策略 +但是有的时候,是运维人员主动将某台机器下线,这个时候,可以通过 PD 的管理接口通知 PD 该 Store 不可用,PD 就可以马上判断需要将这个 Store 上面的 Region 都调度走。 + +## 调度的策略 PD 收集了这些信息后,还需要一些策略来制定具体的调度计划。 @@ -113,7 +116,7 @@ PD 收集了这些信息后,还需要一些策略来制定具体的调度计 **副本在 Store 之间的分布均匀分配** -由于每个region副本中存储的数据容量上限是固定的,通过维持每个节点上面副本数量的均衡,使得各节点间承载的数据更均衡。 +由于每个 Region 副本中存储的数据容量上限是固定的,通过维持每个节点上面副本数量的均衡,使得各节点间承载的数据更均衡。 **Leader 数量在 Store 之间均匀分配** @@ -125,18 +128,16 @@ Raft 协议要求读取和写入都通过 Leader 进行,所以计算的负载 **各个 Store 的存储空间占用大致相等** -每个 Store 启动的时候都会指定一个 Capacity 参数,表明这个 Store 的存储空间上限,PD 在做调度的时候,会考虑节点的存储空间剩余量。 +每个 Store 启动的时候都会指定一个 `Capacity` 参数,表明这个 Store 的存储空间上限,PD 在做调度的时候,会考虑节点的存储空间剩余量。 **控制调度速度,避免影响在线服务** 调度操作需要耗费 CPU、内存、磁盘 IO 以及网络带宽,需要避免对线上服务造成太大影响。PD 会对当前正在进行的操作数量进行控制,默认的速度控制是比较保守的,如果希望加快调度(比如停服务升级或者增加新节点,希望尽快调度),那么可以通过调节 PD 参数动加快调度速度。 -### 调度的实现 - -了解了上面这些信息后,接下来看一下整个调度的流程。 +## 调度的实现 -PD 不断的通过 Store 或者 Leader 的心跳包收集整个集群信息,并且根据这些信息以及调度策略生成调度操作序列。每次收到 Region Leader 发来的心跳包时,PD 都会检查这个 Region 是否有待进行的操作,然后通过心跳包的回复消息,将需要进行的操作返回给 Region Leader,并在后面的心跳包中监测执行结果。注意这里的操作只是给 Region Leader 的建议,并不保证一定能得到执行,具体是否会执行以及什么时候执行,由 Region Leader 根据当前自身状态来定。 +本节介绍调度的实现 -### 总结 +PD 不断的通过 Store 或者 Leader 的心跳包收集整个集群信息,并且根据这些信息以及调度策略生成调度操作序列。每次收到 Region Leader 发来的心跳包时,PD 都会检查这个 Region 是否有待进行的操作,然后通过心跳包的回复消息,将需要进行的操作返回给 Region Leader,并在后面的心跳包中监测执行结果。 -本篇文章讲的东西,大家可能平时很少会在其他文章中看到,每一个设计都有背后的考量,希望大家能了解到一个分布式存储系统在做调度的时候,需要考虑哪些东西,如何将策略、实现进行解耦,更灵活的支持策略的扩展。 \ No newline at end of file +注意这里的操作只是给 Region Leader 的建议,并不保证一定能得到执行,具体是否会执行以及什么时候执行,由 Region Leader 根据当前自身状态来定。 From 813f20abf00e1bbc1eb1ef2009d9749557468a6e Mon Sep 17 00:00:00 2001 From: nolouch Date: Tue, 26 May 2020 19:27:27 +0800 Subject: [PATCH 7/7] address comments Signed-off-by: nolouch --- tidb-scheduling.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tidb-scheduling.md b/tidb-scheduling.md index 154d3e49f954..d3f874c356e1 100644 --- a/tidb-scheduling.md +++ b/tidb-scheduling.md @@ -11,7 +11,7 @@ PD 是 TiDB 集群的管理模块,同时也负责集群数据的实时调度 TiKV 集群是 TiDB 数据库的分布式 KV 存储引擎,数据以 Region 为单位进行复制和管理,每个 Region 会有多个 Replica(副本),这些 Replica 会分布在不同的 TiKV 节点上,其中 Leader 负责读/写,Follower 负责同步 Leader 发来的 Raft log。 -除此之外,还需要考虑以下场景: +需要考虑以下场景: * 为了提高集群的空间利用率,需要根据 Region 的空间占用对 Replica 进行合理的分布。 * 集群进行跨机房部署的时候,要保证一个机房掉线,不会丢失 Raft Group 的多个 Replica。 @@ -88,7 +88,7 @@ TiKV 节点(Store)与 PD 之间存在心跳包,一方面 PD 通过心跳 PD 不断的通过这两类心跳消息收集整个集群的信息,再以这些信息作为决策的依据。 -除此之外,PD 还可以通过管理接口接受额外的信息,用来做更准确的决策。比如当某个 Store 的心跳包中断的时候,PD 并不能判断这个节点是临时失效还是永久失效,只能经过一段时间的等待(默认是 30 分钟),如果一直没有心跳包,就认为该 Store 已经下线,再决定需要将这个 Store 上面的 Region 都调度走。 +除此之外,PD 还可以通过扩展的接口接受额外的信息,用来做更准确的决策。比如当某个 Store 的心跳包中断的时候,PD 并不能判断这个节点是临时失效还是永久失效,只能经过一段时间的等待(默认是 30 分钟),如果一直没有心跳包,就认为该 Store 已经下线,再决定需要将这个 Store 上面的 Region 都调度走。 但是有的时候,是运维人员主动将某台机器下线,这个时候,可以通过 PD 的管理接口通知 PD 该 Store 不可用,PD 就可以马上判断需要将这个 Store 上面的 Region 都调度走。 @@ -138,6 +138,6 @@ Raft 协议要求读取和写入都通过 Leader 进行,所以计算的负载 本节介绍调度的实现 -PD 不断的通过 Store 或者 Leader 的心跳包收集整个集群信息,并且根据这些信息以及调度策略生成调度操作序列。每次收到 Region Leader 发来的心跳包时,PD 都会检查这个 Region 是否有待进行的操作,然后通过心跳包的回复消息,将需要进行的操作返回给 Region Leader,并在后面的心跳包中监测执行结果。 +PD 不断地通过 Store 或者 Leader 的心跳包收集整个集群信息,并且根据这些信息以及调度策略生成调度操作序列。每次收到 Region Leader 发来的心跳包时,PD 都会检查这个 Region 是否有待进行的操作,然后通过心跳包的回复消息,将需要进行的操作返回给 Region Leader,并在后面的心跳包中监测执行结果。 注意这里的操作只是给 Region Leader 的建议,并不保证一定能得到执行,具体是否会执行以及什么时候执行,由 Region Leader 根据当前自身状态来定。