{
    "componentChunkName": "component---src-templates-blog-blog-detail-tsx",
    "path": "/blog/best-practice-pd",
    "result": {"pageContext":{"blog":{"id":"Blogs_111","title":"TiDB 最佳实践系列（二）PD 调度策略最佳实践","tags":["PD","调度","最佳实践"],"category":{"name":"案例实践"},"summary":"本文将详细介绍 PD 调度系统的原理，并通过几个典型场景的分析和处理方式，分享调度策略的最佳实践和调优方法，帮助大家在使用过程中快速定位问题。","body":"众所周知，[PD](https://github.com/pingcap/pd) 是整个 TiDB 集群的核心，负责全局元信息的存储以及 TiKV 集群负载均衡调度，本文将详细介绍 PD 调度系统的原理，并通过几个典型场景的分析和处理方式，分享调度策略的最佳实践和调优方法，帮助大家在使用过程中快速定位问题。本文内容基于 3.0 版本，更早的版本（2.x）缺少部分功能的支持，但是基本原理类似，也可以以本文作为参考。\n\n## PD 调度原理\n\n### 概念\n\n首先我们介绍一下调度系统涉及到的相关概念，理解这些概念以及它们相互之间的关系，有助于在实践中快速定位问题并通过配置进行调整。\n\n* Store\n\t\n\tPD 中的 Store 指的是集群中的存储节点，也就是 tikv-server 实例。注意 Store 与 TiKV 实例是严格一一对应的，即使在同一主机甚至同一块磁盘部署多个 TiKV 实例，这些实例也会对应不同的 Store。\n\n* Region / Peer / Raft Group\n\n\t每个 Region 负责维护集群的一段连续数据（默认配置下平均约 96 MiB），每份数据会在不同的 Store 存储多个副本（默认配置是 3 副本），每个副本称为 Peer。同一个 Region 的多个 Peer 通过 raft 协议进行数据同步，所以 Peer 也用来指代 raft 实例中的成员。TiKV 使用 multi-raft 模式来管理数据，即每个 Region 都对应一个独立运行的 raft 实例，我们也把这样的一个 raft 实例叫做一个 Raft Group。\n\n* Leader / Follower / Learner\n\n\t它们分别对应 Peer 的三种角色。其中 Leader 负责响应客户端的读写请求；Follower 被动地从 Leader 同步数据，当 Leader 失效时会进行选举产生新的 Leader；Learner 是一种特殊的角色，它只参与同步 raft log 而不参与投票，在目前的实现中只短暂存在于添加副本的中间步骤。\n\n* Region Split\n\n\tTiKV 集群中的 Region 不是一开始就划分好的，而是随着数据写入逐渐分裂生成的，分裂的过程被称为 Region Split。\n\t\n\t其机制是集群初始化时构建一个初始 Region 覆盖整个 key space，随后在运行过程中每当 Region 数据达到一定量之后就通过 Split 产生新的 Region。\n\n* Pending / Down\n\n\tPending 和 Down 是 Peer 可能出现的两种特殊状态。其中 Pending 表示 Follower 或 Learner 的 raft log 与 Leader 有较大差距，Pending 状态的 Follower 无法被选举成 Leader。Down 是指 Leader 长时间没有收到对应 Peer 的消息，通常意味着对应节点发生了宕机或者网络隔离。\n\n* Scheduler\n\n\tScheduler（调度器）是 PD 中生成调度的组件。PD 中每个调度器是独立运行的，分别服务于不同的调度目的。常用的调度器及其调用目标有：\n\t  \n\t* `balance-leader-scheduler`：保持不同节点的 Leader 均衡。\n\t* `balance-region-scheduler`：保持不同节点的 Peer 均衡。\n\t* `hot-region-scheduler`：保持不同节点的读写热点 Region 均衡。\n\t* `evict-leader-{store-id}`：驱逐某个节点的所有 Leader。（常用于滚动升级）\n\n* Operator\n\n\tOperator 是应用于一个 Region 的，服务于某个调度目的的一系列操作的集合。例如“将 Region 2 的 Leader 迁移至 Store 5”，“将 Region 2 的副本迁移到 Store 1, 4, 5” 等。\n\t\n\tOperator 可以是由 Scheduler 通过计算生成的，也可以是由外部 API 创建的。\n\n* Operator Step\n\n\tOperator Step 是 Operator 执行过程的一个步骤，一个 Operator 常常会包含多个 Operator Step。\n\t\n\t目前 PD 可生成的 Step 包括：\n\t  \n\t* `TransferLeader`：将 Region Leader 迁移至指定 Peer\n\t* `AddPeer`：在指定 Store 添加 Follower\n\t* `RemovePeer`：删除一个 Region Peer\n\t* `AddLearner`：在指定 Store 添加 Region Learner\n\t* `PromoteLearner`：将指定 Learner 提升为 Follower\n\t* `SplitRegion`：将指定 Region 一分为二\n\n### 调度流程\n\n宏观上来看，调度流程大体可划分为 3 个部分：\n\n1\\. 信息收集\n\nTiKV 节点周期性地向 PD 上报 `StoreHeartbeat` 和 `RegionHeartbeat` 两种心跳消息。其中 `StoreHeartbeat` 包含了 Store 的基本信息，容量，剩余空间，读写流量等数据，`RegionHeartbeat` 包含了 Region 的范围，副本分布，副本状态，数据量，读写流量等数据。PD 将这些信息梳理并转存供调度来决策。\n\n2\\. 生成调度\n   \n不同的调度器从自身的逻辑和需求出发，考虑各种限制和约束后生成待执行的 Operator。这里所说的限制和约束包括但不限于：\n  \n  * 不往断连中、下线中、繁忙、空间不足、在大量收发 snapshot 等各种异常状态的 Store 添加副本\n  * Balance 时不选择状态异常的 Region\n  * 不尝试把 Leader 转移给 Pending Peer\n  * 不尝试直接移除 Leader\n  * 不破坏 Region 各种副本的物理隔离\n  * 不破坏 Label property 等约束\n\n3\\. 执行调度\n   \n生成的 Operator 不会立即开始执行，而是首先会进入一个由 `OperatorController` 管理的一个等待队列。`OperatorController` 会根据配置以一定的并发从等待队列中取出 Operator 进行执行，执行的过程就是依次把每个 Operator Step 下发给对应 Region 的 Leader。\n   \n最终 Operator 执行完毕会被标记为 finish 状态或者超时被标记为 timeout，并从执行列表中移除。\n\n### Balance\n\nRegion 负载均衡调度主要依赖 `balance-leader` 和 `balance-region` 这两个调度器，这二者的调度目标是将 Region 均匀地分散在集群中的所有 Store 上。它们的侧重点又有所不同：`balance-leader` 关注 Region 的 Leader，可以认为目的是分散处理客户端请求的压力；`balance-region` 关注 Region 的各个 Peer，目的是分散存储的压力，同时避免出现爆盘等状况。\n\n`balance-leader` 与 `balance-region` 有着类似的调度流程，首先根据不同 Store 的对应资源量的情况分别打一个分，然后不断从得分较高的 Store 选择 Leader 或 Peer 迁移到得分较低的 Store 上。\n\n这两者的分数计算上也有一定差异：`balance-leader` 比较简单，使用 Store 上所有 Leader 所对应的 Region Size 加和作为得分；`balance-region` 由于要考虑不同节点存储容量可能不一致的情况，会分三种情况，当空间富余时使用数据量计算得分（使不同节点数据量基本上均衡），当空间不足时由使用剩余空间计算得分（使不同节点剩余空间基本均衡），处于中间态时则同时考虑两个因素做加权和当作得分。\n\n此外，为了应对不同节点可能在性能等方面存在差异的问题，我们还支持为 Store 设置 balance 权重。`leader-weight` 和 `region-weight` 分别用于控制 leader 权重以及 region 权重，这两个配置的默认值都为 `1`。假如把某个 Store 的 `leader-weight` 设为 `2`，调度稳定后，则该节点的 leader 数量约为普通节点的 2 倍；假如把某个 Store 的 `region-weight` 设为 `0.5`，那么调度稳定后该节点的 region 数量约为其他节点的一半。\n\n### 热点调度\n\n热点调度对应的调度器是 `hot-region-scheduler`。目前 3.0 版本统计热点 Region 的方式比较单一，就是根据 Store 上报的信息，统计出持续一段时间读或写流量超过一定阈值的 Region，然后再用与 Balance 类似的方式把这些 Region 分散开来。\n\n对于写热点，热点调度会同时尝试打散热点 Region 的 Peer 和 Leader；对于读热点，由于只有 Leader 承载读压力，热点调度会尝试将热点 Region 的 Leader 打散。\n\n### 集群拓扑感知\n\n让 PD 感知不同节点分布的拓扑是为了通过调度使不同 Region 的各个副本尽可能分散，保证高可用和容灾。例如集群有 3 个数据中心，最安全的调度方式就是把 Region 的 3 个 Peer 分别放置在不同的数据中心，这样任意一个数据中心故障时，都能继续提供服务。\n\nPD 会在后台不断扫描所有 Region，当发现 Region 的分布不是当前的最优化状态时，会生成调度替换 Peer，将 Region 调整至最佳状态。\n\n负责这个检查的组件叫 `replicaChecker`（跟 Scheduler 类似，但是不可关闭），它依赖于 `location-labels` 这个配置来进行调度。比如配置 `[zone, rack, host]` 定义了三层的拓扑结构：集群分为多个 zone（可用区），每个 zone 下有多个 rack（机架），每个 rack 下有多个 host（主机）。PD 在调度时首先会尝试将 Region 的 Peer 放置在不同的 zone，假如无法满足（比如配置 3 副本但总共只有 2 个 zone）则退而求其次保证放置在不同的 rack，假如 rack 的数量也不足以保证隔离，那么再尝试 host 级别的隔离，以此类推。\n\n### 缩容及故障恢复\n\n缩容是指预备将某个 Store 下线，通过命令将该 Store 标记为 `Offline` 状态，此时 PD 通过调度将待下线节点上的 Region 迁移至其他节点。故障恢复是指当有 Store 发生故障且无法恢复时，有 Peer 分布在对应 Store 上的 Region 会产生缺少副本的状况，此时 PD 需要在其他节点上为这些 Region 补副本。\n\n这两种情况的处理过程基本上是一样的。由 `replicaChecker` 检查到 Region 存在异常状态的 Peer，然后生成调度在健康的 Store 创建新副本替换掉异常的。\n\n### Region merge\n\nRegion merge 指的是为了避免删除数据后大量小 Region 甚至空 Region 消耗系统资源，通过调度把相邻的小 Region 合并的过程。Region merge 由 `mergeChecker` 负责，其过程与 `replicaChecker` 类似，也是在后台遍历，发现连续的小 Region 后发起调度。\n\n## 查询调度状态\n\n查看调度系统的状态的手段主要包括：Metrics，pd-ctl，日志。本文简要介绍 Metrics 和 pd-ctl 两种方式，更具体的信息可以参考官方文档中 [PD 监控](https://pingcap.com/docs-cn/v3.0/reference/key-monitoring-metrics/pd-dashboard) 以及 [PD Control 使用](https://pingcap.com/docs-cn/dev/reference/tools/pd-control) 的章节。\n\n### Operator 状态\n\nGrafana PD / Operator 页面展示了 Operator 相关统计。其中比较重要的有：\n\n* `Schedule Operator Create`：展示 Operator 的创建情况，从名称可以知道 Operator 是哪个调度器创建的以及创建的原因。\n\n* `Operator finish duration`：展示了 Operator 执行耗时的情况\n\n* `Operator Step duration`：展示不同 Operator Step 执行耗时的情况\n\n查询 Operator 的 pd-ctl 命令有：\n\n* `operator show`：查询当前调度生成的所有 Operator\n\n* `operator show [admin | leader | region]`：按照类型查询 Operator\n\n### Balance 状态\n\nGrafana PD / Statistics - Balance 页面展示了负载均衡相关统计，其中比较重要的有：\n\n* `Store Leader/Region score`：展示每个 Store 的得分\n\n* `Store Leader/Region count`：展示每个 Store 的 Leader/Region 数量\n\n* `Store available`：展示每个 Store 的剩余空间\n\n使用 pd-ctl 的 store 命令可以查询 Store 的得分，数量，剩余空间，weight 等信息。\n\n### 热点调度状态\n\nGrafana PD / Statistics - hotspot 页面展示了热点 Region 的相关统计，其中比较重要的有：\n\n* `Hot write Region’s leader/peer distribution`：展示了写热点 Region 的 Leader/Peer 分布情况\n\n* `Hot read Region’s leader distribution`：展示了读热点 Region 的 Leader 分布情况\n\n使用 pd-ctl 同样可以查询上述信息，可以使用的命令有：\n\n* `hot read`：查询读热点 Region 信息\n\n* `hot write`：查询写热点 Region 信息\n\n* `hot store`：按 Store 统计热点分布情况\n\n* `region topread [limit]`：查询当前读流量最大的 Region\n\n* `region topwrite [limit]`：查询当前写流量最大的 Region\n\n### Region 健康度\n\nGrafana PD / Cluster / Region health 面板展示了异常状态 Region 数的统计，其中包括 Pending Peer，Down Peer，Offline Peer，以及副本数过多或过少的 Region。\n\n通过 pd-ctl 的 region check 命令可以查看具体异常的 Region 列表：\n\n* `region check miss-peer`：缺副本的 Region\n\n* `region check extra-peer`：多副本的 Region\n\n* `region check down-peer`：有副本状态为 Down 的 Region\n\n* `region check pending-peer`：有副本状态为 Pending 的 Region\n\n## 调度策略控制\n\n在线调整调度策略主要使用 pd-ctl 工具来完成，可以通过以下 3 个方面来控制 PD 的调度行为。本文做一些简要介绍，更具体的信息可以参考官方文档中 [PD Control 使用](https://pingcap.com/docs-cn/dev/reference/tools/pd-control) 的章节。\n\n### 启停调度器\n\npd-ctl 支持动态创建和删除 Scheduler 的功能，我们可以通过这些操作来控制 PD 的调度行为，如下所示：\n\n* `scheduler show`：显示当前系统中的 Scheduler\n\n* `scheduler remove balance-leader-scheduler`：删除（停用）balance leader 调度器\n\n* `scheduler add evict-leader-scheduler-1`：添加移除 Store 1 的所有 Leader 的调度器\n\n### 手动添加 Operator\n\nPD 还支持绕过调度器，直接通过 pd-ctl 来创建或删除 Operator，如下所示：\n\n* `operator add add-peer 2 5`：在 Store 5 上为 Region 2 添加 Peer\n\n* `operator add transfer-leader 2 5`：将 Region 2 的 Leader 迁移至 Store 5\n\n* `operator add split-region 2`：将 Region 2 拆分为 2 个大小相当的 Region\n\n* `operator remove 2`：取消 Region 2 当前待执行的 Operator\n\n### 调度参数调整\n\n使用 pd-ctl 执行 `config show` 命令可以查看所有的调度参数，执行 `config set {key} {value}` 可以调整对应参数的值。这里举例说明常见的参数，更详情的说明请参考 [PD 调度参数指南](https://docs.google.com/document/d/1GLyP9RR4hV7Tpy_xacMbcG0tMi4azh75pXocWKy06xo/edit?usp=sharing)：\n\n* `leader-schedule-limit`：控制 Transfer Leader 调度的并发数\n\n* `region-schedule-limit`：控制增删 Peer 调度的并发数\n\n* `disable-replace-offline-replica`：停止处理节点下线的调度\n\n* `disable-location-replacement`：停止处理调整 Region 隔离级别相关的调度\n\n* `max-snapshot-count`：每个 Store 允许的最大收发 Snapshot 的并发数\n\n## 典型场景分析与处理\n\n### 1. Leader / Region 分布不均衡\n\n**需要说明的是，PD 的打分机制决定了一般情况下，不同 Store 的 Leader Count 和 Region Count 不一样多并不代表负载是不均衡的。需要从 TiKV 的实际负载或者存储空间占用来判断是否有 Balance 不均衡的状况。**\n\n确认存在 Leader / Region 分布不均衡的现象后，首先要观察不同 Store 的打分情况。\n\n**如果不同 Store 的打分是接近的**，说明 PD 认为此时已经是均衡状态了，可能的原因有：\n\n* 存在热点导致负载不均衡。需要根据热点调度相关的信息进一步分析，可以参考下文热点调度的部分。\n\n* 存在大量的空 Region 或小 Region，导致不同 Store 的 Leader 数量差别特别大，导致 raftstore 负担过重。需要开启 Region Merge 并尽可能加速合并，可以参考下文关于 Region Merge 的部分。\n\n* 不同 Store 的软硬件环境存在差异。可以酌情调整 `leader-weight` 和 `region-weight` 来控制 Leader / Region 的分布。\n\n* 其他不明原因。也可以使用调整权重这个兜底的方法，通过调整 leader-weight 和 region-weight 来调整至用户觉得合理的分布。\n\n**如果不同 Store 的打分差异较大**，需要进一步检查 Operator 相关 Metrics，特别关注 Operator 的生成和执行情况，这时大体上又分两种情况。\n\n**一种情况是生成的调度是正常的，但是调度的速度很慢**。可能的原因有：\n\n* 调度速度受限于 limit 配置。PD 默认配置的 limit 比较保守，在不对正常业务造成显著影响的前提下，可以酌情将 `leader-schedule-limit` 或 `region-schedule-limit` 调大一些，此外， `max-pending-peer-count` 以及 `max-snapshot-count` 限制也可以放宽。\n\n* 系统中同时运行有其它的调度任务产生竞争，导致 balance 速度上不去。这种情况下如果 balance 调度的优先级更高，可以先停掉其他的调度或者限制其他调度的速度。例如 Region 没均衡的情况下做下线节点操作，下线的调度与 Region Balance 会抢占 `region-schedule-limit` 配额，此时我们可以把 `replica-schedule-limit` 调小将下线调度的速度限制住，或者干脆设置 `disable-replace-offline-replica = true` 来暂时关闭下线流程。\n\n* 调度执行得太慢。可以检查 Operator Step 的耗时来进行判断。通常不涉及到收发 Snapshot 的 Step（比如 `TransferLeader`，`RemovePeer`，`PromoteLearner` 等）的完成时间应该在毫秒级，涉及到 Snapshot 的 Step（如 `AddLearner`，`AddPeer` 等）的完成时间为数十秒。如果耗时明显过高，可能是 TiKV 压力过大或者网络等方面的瓶颈导致的，需要具体情况具体分析。\n\n**另一种情况是没能生成对应的 balance 调度**。可能的原因有：\n\n* 调度器未被启用。比如对应的 Scheduler 被删除了，或者 limit 被设置为 `0`。\n\n* 由于其它约束无法进行调度。比如系统中有 `evict-leader-scheduler`，此时无法把 Leader 迁移至对应的 Store。再比如设置了 Label property，也会导致部分 Store 不接受 Leader。\n\n* 集群拓扑的限制导致无法均衡。比如 3 副本 3 数据中心的集群，由于副本隔离的限制，每个 Region 的 3 个副本都分别分布在不同的数据中心，假如这 3 个数据中心的 Store 数不一样，最后调度就会收敛在每个数据中心均衡，但是全局不均衡的状态。\n\n### 2. 节点下线速度慢\n\n这个场景还是从 Operator 相关 Metrics 入手，分析 Operator 的生成执行情况。\n\n如果调度在正常生成，只是速度很慢。可能的原因有：\n\n* 调度速度受限于 limit 配置。下线对应的 limit 参数是 `replica-schedule-limit`，可以把它适当调大。与 Balance 类似，`max-pending-peer-count` 以及 `max-snapshot-count` 限制同样也可以放宽。\n\n* 系统中同时运行有其它的调度任务产生竞争，或者调度执行得太慢了。处理方法在上一节已经介绍过了，不再赘述。\n\n* 下线单个节点时，由于待操作的 Region 有很大一部分（3 副本配置下约 1/3）的 Leader 都集中在下线的节点上，下线速度会受限于这个单点生成 Snapshot 的速度。可以通过手动给这个节点添加一个 `evict-leader` 调度迁走 Leader 来加速。\n\n如果没有对应的 Operator 调度生成，可能的原因有：\n\n* 下线调度被关闭，或者 `replica-schedule-limit` 被设为 0。\n\n* 找不到节点来转移 Region。例如相同 Label 的替代节点容量都大于 80%，PD 为了避免爆盘的风险会停止调度。这种情况需要添加更多节点，或者删除一些数据释放空间。\n\n### 3. 节点上线速度慢\n\n目前 PD 没有对节点上线特殊处理，节点上线实际上就是依靠 balance region 机制来调度的，所以参考前面 Region 分布不均衡的排查步骤即可。\n\n### 4. 热点分布不均匀\n\n热点调度的问题大体上可以分为以下几种情况。\n\n**一种是从 PD 的 metrics 能看出来有不少 hot Region，但是调度速度跟不上，不能及时地把热点 Region 分散开来。**\n\n解决方法是加大 `hot-region-schedule-limit`，并减少其他调度器的 limit 配额，从而加快热点调度的速度。还有 `hot-region-cache-hits-threshold` 调小一些可以使 PD 对流量的变化更快做出反应。\n\n**第二种情况是单一 Region 形成热点的情况，比如大量请求频繁 scan 一个小表**。这个可以从业务角度或者 metrics 统计的热点信息看出来。由于单 Region 热点现阶段无法使用打散的手段来消除，需要确认热点 Region 后先手动添加 `split-region` 调度将这样的 Region 拆开。\n\n**还有一种情况是从 PD 的统计来看没有热点，但是从 TiKV 的相关 metrics 可以看出部分节点负载明显高于其他节点，成为整个系统的瓶颈。**\n\n这是因为目前 PD 统计热点 Region 的维度比较单一，仅针对流量进行分析，在某些场景下无法准备定位出热点。例如部分 Region 有大量的点查请求，从流量上来看并不显著，但是过高的 QPS 导致关键模块达到瓶颈。这个问题当前的处理方式是：首先从业务层面确定形成热点的 table，然后添加 `scatter-range-scheduler` 来使得这个 table 的所有 Region 均匀分布。TiDB 也在其 HTTP API 中提供了相关接口来简化这个操作，具体可以参考 [TiDB HTTP API 文档](https://github.com/pingcap/tidb/blob/master/docs/tidb_http_api.md)。\n\n### 5. Region Merge 速度慢\n\n与前面讨论过的所有调度慢的问题类似，Region Merge 速度慢也很有可能是受到 limit 限制（Region Merge 同时受限于 `merge-schedule-limit` 及 `region-schedule-limit`），或者是与其他调度器产生了竞争，处理方法不再赘述了。\n\n假如我们已经从统计得知系统中有大量的空 Region，这时可以通过把 `max-merge-region-size` 和 `max-merge-region-keys` 调整为较小值来加快 Merge 速度。这是因为 Merge 的过程涉及到副本迁移，于是 Merge 的 Region 越小，速度就越快。如果 Merge Operator 生成的速度已经有几百 opm，想进一步加快，还可以把 `patrol-region-interval` 调整为 \"10ms\" ，这个能加快巡检 Region 的速度，但是会消耗更多的 CPU。\n\n还有一种特殊情况：曾经创建过大量 Table 然后又清空了（truncate 操作也算创建 Table），此时如果开启了 split table 特性，这些空 Region 是无法合并的，此时需要调整以下参数关闭这个特性：\n\n* TiKV [`split-region-on-table`](https://pingcap.com/docs-cn/v3.0/reference/configuration/tikv-server/configuration-file/#split-region-on-table) 设为 `false`\n\n* PD [`namespace-classifier`](https://pingcap.com/docs-cn/v3.0/reference/configuration/pd-server/configuration/#--namespace-classifier) 设为 `“”`\n\n另外对于 3.0.4 和 2.1.16 以前的版本，Region 的统计 `approximate_keys` 在特定情况下（大部分发生在 drop table 之后）统计不准确，造成 keys 的统计值很大，无法满足 `max-merge-region-keys` 的约束，可以把 `max-merge-region-keys` 这个条件放开，调成很大的值来绕过这个问题。\n\n### 6. TiKV 节点故障处理策略\n\n没有人工介入时，PD 处理 TiKV 节点故障的默认行为是，等待半小时之后（可通过 `max-store-down-time` 配置调整），将此节点设置为 `Down` 状态，并开始为涉及到的 Region 补充副本。\n\n实践中，如果能确定这个节点的故障是不可恢复的，可以立即做下线处理，这样 PD 能尽快补齐副本，降低数据丢失的风险。与之相对，如果确定这个节点是能恢复的，但可能半小时之内来不及，则可以把 `max-store-down-time` 临时调整为比较大的值，这样能避免超时之后产生不必要的补副本产生资源浪费。\n\n## 总结\n\n本文介绍了 PD 调度的概念，原理以及常见问题的处理方法，希望读者可以在理解调度系统的基础上，参考本文按图索骥解决生产中遇到的调度相关的问题。PD 的调度策略还在不断的演进和完善中，也期待大家踊跃提出宝贵的改进意见。\n\n> 点击查看更多 [TiDB 最佳实践系列文章](https://pingcap.com/zh/blog/?tag=%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5)","date":"2019-10-11","author":"黄梦龙","fillInMethod":"writeDirectly","customUrl":"best-practice-pd","file":null,"relatedBlogs":[]}}},
    "staticQueryHashes": ["1327623483","1820662718","3081853212","3430003955","3649515864","4265596160","63159454"]}