Placement Rules 使用文档

    Placement Rules 是 PD 在 4.0 版本引入的试验特性,它是一套副本规则系统,用于指导 PD 针对不同类型的数据生成对应的调度。通过组合不同的调度规则,用户可以精细地控制任何一段连续数据的副本数量、存放位置、主机类型、是否参与 Raft 投票、是否可以担任 Raft leader 等属性。

    整个规则系统的配置由多条规则即 Rule 组成。每条 Rule 可以指定不同的副本数量、Raft 角色、放置位置等属性,以及这条规则生效的 key range。PD 在进行调度时,会先根据 Region 的 key range 在规则系统中查到该 Region 对应的规则,然后再生成对应的调度,来使得 Region 副本的分布情况符合 Rule。

    多条规则的 key range 可以有重叠部分的,即一个 Region 能匹配到多条规则。这种情况下 PD 根据 Rule 的属性来决定规则是相互覆盖还是同时生效。如果有多条规则同时生效,PD 会按照规则的堆叠次序依次去生成调度进行规则匹配。

    此外,为了满足不同来源的规则相互隔离的需求,还引入了分组(Group)的概念。如果某条规则不希望与系统中的其他规则相互影响(比如被覆盖),可以使用单独的分组。

    Placement Rules 示意图如下所示:

    以下是每条规则中各个字段的具体含义:

    LabelConstraint 与 Kubernetes 中的功能类似,支持通过 innotInexistsnotExists 四种原语来筛选 label。这四种原语的意义如下:

    • in:给定 key 的 label value 包含在给定列表中。
    • notIn:给定 key 的 label value 不包含在给定列表中。
    • exists:包含给定的 label key。
    • notExists:不包含给定的 label key。

    LocationLabels 的意义和作用与 PD v4.0 之前的版本相同。比如配置 [zone,rack,host] 定义了三层的拓扑结构:集群分为多个 zone(可用区),每个 zone 下有多个 rack(机架),每个 rack 下有多个 host(主机)。PD 在调度时首先会尝试将 Region 的 Peer 放置在不同的 zone,假如无法满足(比如配置 3 副本但总共只有 2 个 zone)则保证放置在不同的 rack;假如 rack 的数量也不足以保证隔离,那么再尝试 host 级别的隔离,以此类推。

    本节的操作步骤以使用 工具为例,涉及到的命令也支持通过 HTTP API 进行调用。

    开启 Placement Rules 特性

    默认情况下,Placement Rules 特性是关闭的。要开启这个特性,可以集群初始化以前设置 PD 配置文件:

    这样,PD 在初始化成功后会开启这个特性,并根据 max-replicaslocation-labels 配置生成对应的规则:

    1. {
    2. "group_id": "pd",
    3. "id": "default",
    4. "start_key": "",
    5. "end_key": "",
    6. "role": "voter",
    7. "count": 3,
    8. "location_labels": ["zone", "rack", "host"]
    9. }
    1. pd-ctl config placement-rules enable

    PD 同样将根据系统的 max-replicaslocation-labels 生成默认的规则。

    关闭 Placement Rules 特性

    使用 pd-ctl 可以关闭 Placement Rules 特性,切换为之前的调度策略。

    1. pd-ctl config placement-rules disable

    pd-ctl 支持使用多种方式查看系统中的 Rule,输出是 json 格式的 Rule 或 Rule 列表:

    • 查看所有规则列表

      1. pd-ctl config placement-rules show
    • 查看 PD Group 的所有规则列表

      1. pd-ctl config placement-rules show --group=pd
    • 查看对应 Group 和 ID 的某条规则

    • 查看 Region 所匹配的规则列表

      1. pd-ctl config placement-rules show --region=2

    新增和编辑规则是类似的,需要把对应的规则写进文件,然后使用 save 命令保存至 PD:

    1. cat > rules.json <<EOF
    2. [
    3. {
    4. "group_id": "pd",
    5. "id": "rule1",
    6. "role": "voter",
    7. "location_labels": ["zone", "rack", "host"]
    8. },
    9. {
    10. "group_id": "pd",
    11. "id": "rule2",
    12. "role": "voter",
    13. "count": 2,
    14. }
    15. ]
    16. EOF
    17. pd-ctl config placement save --in=rules.json

    以上操作会将 rule1、rule2 两条规则写入 PD,如果系统中已经存在 GroupID+ID 相同的规则,则会覆盖该规则。

    如果需要删除某条规则,只需要将规则的 count 置为 0 即可,对应 GroupID+ID 相同的规则会被删除。以下命令将删除 pd/rule2 这条规则:

    1. cat > rules.json <<EOF
    2. [
    3. {
    4. "group_id": "pd",
    5. "id": "rule2"
    6. }
    7. ]
    8. EOF
    9. pd-ctl config placement save --in=rules.json

    pd-ctl 还支持通过 load 命令将规则直接转存至文件以方便进行修改,只需要将查看命令的 show 改为 load

    1. pd-ctl config placement-rules load

    以上命令将所有规则转存至 rules.json 文件。

    1. pd-ctl config placement-rules load --group=pd --out=rule.txt

    以上命令将 PD Group 的规则转存至 rule.txt 文件。

    使用 tidb-ctl 查询表相关的 key range

    若需要针对元数据或某个特定的表进行特殊配置,可以通过 tidb-ctl 的 来查询相关的 key。注意要添加 --encode 返回 PD 中的表示形式。

    1. global ranges:
    2. meta: (6d00000000000000f8, 6e00000000000000f8)
    3. table: (7400000000000000f8, 7500000000000000f8)
    4. table ttt ranges: (NOTE: key range might be changed after DDL)
    5. table: (7480000000000000ff2d00000000000000f8, 7480000000000000ff2e00000000000000f8)
    6. table indexes: (7480000000000000ff2d5f690000000000fa, 7480000000000000ff2d5f720000000000fa)
    7. index c2: (7480000000000000ff2d5f698000000000ff0000010000000000fa, 7480000000000000ff2d5f698000000000ff0000020000000000fa)
    8. index c3: (7480000000000000ff2d5f698000000000ff0000020000000000fa, 7480000000000000ff2d5f698000000000ff0000030000000000fa)
    9. index c4: (7480000000000000ff2d5f698000000000ff0000030000000000fa, 7480000000000000ff2d5f698000000000ff0000040000000000fa)
    10. table rows: (7480000000000000ff2d5f720000000000fa, 7480000000000000ff2e00000000000000f8)

    本部分介绍 Placement Rules 的使用场景示例。

    场景一:普通的表使用 3 副本,元数据使用 5 副本提升集群容灾能力

    只需要增加一条规则,将 key range 限定在 meta 数据的范围,并把 count 值设为 5。添加规则示例如下:

    1. {
    2. "group_id": "pd",
    3. "id": "meta",
    4. "index": 1,
    5. "override": true,
    6. "start_key": "6d00000000000000f8",
    7. "end_key": "6e00000000000000f8",
    8. "role": "voter",
    9. "count": "5",
    10. "location_labels": ["zone", "rack", "host"]
    11. }

    创建三条规则,分别设置副本数为 2、2、1,并且在每个规则内通过 label_constraints 将副本限定在对应的数据中心内。另外,不需要 leader 的数据中心将 role 改为 follower

    1. [
    2. {
    3. "group_id": "pd",
    4. "id": "zone1",
    5. "end_key": "",
    6. "role": "voter",
    7. "count": 2,
    8. "label_constraints": [
    9. {"key": "zone", "op": "in", "values": ["zone1"]}
    10. ],
    11. "location_labels": ["rack", "host"]
    12. {
    13. "group_id": "pd",
    14. "id": "zone2",
    15. "start_key": "",
    16. "end_key": "",
    17. "role": "voter",
    18. "count": 2,
    19. "label_constraints": [
    20. {"key": "zone", "op": "in", "values": ["zone2"]}
    21. ],
    22. "location_labels": ["rack", "host"]
    23. },
    24. {
    25. "group_id": "pd",
    26. "id": "zone3",
    27. "start_key": "",
    28. "end_key": "",
    29. "role": "follower",
    30. "count": 1,
    31. "label_constraints": [
    32. {"key": "zone", "op": "in", "values": ["zone3"]}
    33. ],
    34. "location_labels": ["rack", "host"]
    35. }
    36. ]

    场景三:为某张表添加 2 个 TiFlash Learner 副本

    为表的 row key 单独添加一条规则,限定数量为 2,并且通过 label_constraints 保证副本产生在 engine=tiflash 的节点。注意这里使用了单独的 group_id,保证这条规则不会与系统中其他来源的规则互相覆盖或产生冲突。

    1. {
    2. "group_id": "tiflash",
    3. "id": "learner-replica-table-ttt",
    4. "start_key": "7480000000000000ff2d5f720000000000fa",
    5. "end_key": "7480000000000000ff2e00000000000000f8",
    6. "role": "learner",
    7. "count": 2,
    8. "label_constraints": [
    9. {"key": "engine", "op": "in", "values": ["tiflash"]}
    10. ],
    11. "location_labels": ["host"]
    12. }

    场景四:为某张表在有高性能磁盘的北京节点添加 2 个 Follower 副本

    1. {
    2. "group_id": "follower-read",
    3. "id": "follower-read-table-ttt",
    4. "start_key": "7480000000000000ff2d00000000000000f8",
    5. "end_key": "7480000000000000ff2e00000000000000f8",
    6. "role": "follower",
    7. "count": 2,
    8. "label_constraints": [
    9. {"key": "zone", "op": "in", "values": ["bj1", "bj2"]},
    10. {"key": "disk", "op": "notIn", "values": ["hdd"]}
    11. ],