通过拓扑 label 进行副本调度

    注意

    TiDB 在 v5.3.0 中引入了 Placement Rules in SQL。使用该功能,你可以更方便地配置表和分区的位置。在未来版本中,Placement Rules in SQL 可能取代通过 PD 配置放置规则的功能。

    为了提升 TiDB 集群的高可用性和数据容灾能力,我们推荐让 TiKV 节点尽可能在物理层面上分散,例如让 TiKV 节点分布在不同的机架甚至不同的机房。PD 调度器根据 TiKV 的拓扑信息,会自动在后台通过调度使得 Region 的各个副本尽可能隔离,从而使得数据容灾能力最大化。

    要让这个机制生效,需要在部署时进行合理配置,把集群的拓扑信息(特别是 TiKV 的位置)上报给 PD。阅读本章前,请先确保阅读 。

    TiKV 和 TiFlash 支持在命令行参数或者配置文件中以键值对的形式绑定一些属性,我们把这些属性叫做标签 (label)。TiKV 和 TiFlash 在启动后,会将自身的标签上报给 PD,因此可以使用标签来标识 TiKV 和 TiFlash 节点的地理位置。

    比如集群的拓扑结构分成四层:机房 (zone) -> 数据中心 (dc) -> 机架 (rack) -> 主机 (host),就可以使用这 4 个标签来设置 TiKV 和 TiFlash 的位置。

    使用命令行参数的方式启动一个 TiKV 实例:

    使用配置文件的方式:

    1. [server]
    2. [server.labels]
    3. zone = "<zone>"
    4. dc = "<dc>"
    5. rack = "<rack>"
    6. host = "<host>"

    TiFlash 支持通过 tiflash-learner.toml (tiflash-proxy 的配置文件)的方式设置 labels:

    1. [server]
    2. [server.labels]
    3. zone = "<zone>"
    4. dc = "<dc>"
    5. rack = "<rack>"
    6. host = "<host>"

    如果需要使用 的优先读同一区域副本的功能,需要为 TiDB 节点配置相关的 labels

    TiDB 支持使用配置文件的方式设置 labels

    注意

    根据前面的描述,标签可以是用来描述 TiKV 属性的任意键值对,但 PD 无从得知哪些标签是用来标识地理位置的,而且也无从得知这些标签的层次关系。因此,PD 也需要一些配置来使得 PD 理解 TiKV 节点拓扑。

    PD 上的配置叫做 location-labels,是一个字符串数组。该配置的每一项与 TiKV labels 的 key 是对应的,而且其中每个 key 的顺序代表不同标签的级别关系(从左到右,隔离级别依次递减)。

    location-labels 没有默认值,你可以根据具体需求来设置该值,包括 zonerackhost 等等。同时,location-labels 对标签级别的数量也没有限制(即不限定于 3 个),只要其级别与 TiKV 服务器的标签匹配,则可以配置成功。

    通过拓扑 label 进行副本调度 - 图3

    注意

    • 必须同时配置 PD 的 location-labels 和 TiKV 的 labels 参数,否则 PD 不会根据拓扑结构进行调度。
    • 如果你使用 Placement Rules in SQL,只需要配置 TiKV 的 labels 即可。Placement Rules in SQL 目前不兼容 PD location-labels 设置,会忽略该设置。不建议 location-labels 与 Placement Rules in SQL 混用,否则可能产生非预期的结果。

    你可以根据集群状态来选择不同的配置方式:

    • 在集群初始化之前,可以通过 PD 的配置文件进行配置:

      1. [replication]
      2. location-labels = ["zone", "rack", "host"]
    • 如果需要在 PD 集群初始化完成后进行配置,则需要使用 pd-ctl 工具进行在线更改:

      1. pd-ctl config set location-labels zone,rack,host

    在配置了 location-labels 的前提下,用户可以还通过 isolation-level 配置来进一步加强对 TiKV 集群的拓扑隔离要求。假设按照上面的说明通过 location-labels 将集群的拓扑结构分成三层:机房 (zone) -> 机架 (rack) -> 主机 (host),并对 isolation-level 作如下配置:

    当 PD 集群初始化完成后,需要使用 pd-ctl 工具进行在线更改:

    1. pd-ctl config set isolation-level zone

    其中,isolation-level 配置是一个字符串,需要与 location-labels 的其中一个 key 对应。该参数限制 TiKV 拓扑集群的最小且强制隔离级别要求。

    注意

    如果使用 TiUP 部署集群,可以在中统一进行 location 相关配置。TiUP 会负责在部署时生成对应的 TiKV、PD 和 TiFlash 配置文件。

    下面的例子定义了 zonehost 两层拓扑结构。集群的 TiKV 和 TiFlash 分布在三个 zone,z1、z2 和 z3。每个 zone 内有四台主机,z1 两台主机分别部署两个 TiKV 实例,另外两台分别部署一个 TiFlash 实例,z2 和 z3 其中两台主机分别部署一个 TiKV 实例,另外两台分别部署一个 TiFlash 实例。以下例子中 tikv-n 代表第 n 个 TiKV 节点的 IP 地址,tiflash-n 代表第 n 个 TiFlash 节点的 IP 地址。

    1. server_configs:
    2. pd:
    3. replication.location-labels: ["zone", "host"]
    4. tikv_servers:
    5. # z1
    6. - host: tikv-1
    7. config:
    8. server.labels:
    9. host: h1
    10. - host: tikv-2
    11. config:
    12. server.labels:
    13. zone: z1
    14. host: h1
    15. - host: tikv-3
    16. config:
    17. server.labels:
    18. zone: z1
    19. host: h2
    20. - host: tikv-4
    21. config:
    22. server.labels:
    23. zone: z1
    24. host: h2
    25. # z2
    26. - host: tikv-5
    27. config:
    28. server.labels:
    29. zone: z2
    30. host: h1
    31. - host: tikv-6
    32. config:
    33. server.labels:
    34. zone: z2
    35. host: h2
    36. # z3
    37. - host: tikv-7
    38. config:
    39. server.labels:
    40. zone: z3
    41. host: h1
    42. - host: tikv-8
    43. config:
    44. host: h2
    45. tiflash_servers:
    46. # z1
    47. - host: tiflash-1
    48. learner_config:
    49. server.labels:
    50. zone: z1
    51. host: h3
    52. - host: tiflash-2
    53. learner_config:
    54. server.labels:
    55. zone: z1
    56. host: h4
    57. # z2
    58. - host: tiflash-3
    59. learner_config:
    60. server.labels:
    61. zone: z2
    62. host: h3
    63. - host: tiflash-4
    64. learner_config:
    65. server.labels:
    66. zone: z2
    67. host: h4
    68. # z3
    69. - host: tiflash-5
    70. learner_config:
    71. server.labels:
    72. zone: z3
    73. host: h3
    74. - host: tiflash-6
    75. learner_config:
    76. server.labels:
    77. zone: z3
    78. host: h4

    详情参阅 TiUP 跨数据中心部署拓扑

    通过拓扑 label 进行副本调度 - 图5

    注意

    如果你未在配置文件中配置 replication.location-labels 项,使用该拓扑配置文件部署集群时可能会报错。建议在部署集群前,确认 replication.location-labels 已配置。

    基于拓扑 label 的 PD 调度策略

    PD 在副本调度时,会按照 label 层级,保证同一份数据的不同副本尽可能分散。

    下面以上一节的拓扑结构为例分析。

    假设集群副本数设置为 3 (max-replicas=3),因为总共有 3 个 zone,PD 会保证每个 Region 的 3 个副本分别放置在 z1/z2/z3,这样当任何一个数据中心发生故障时,TiDB 集群依然是可用的。

    假如集群副本数设置为 5 (max-replicas=5),因为总共只有 3 个 zone,在这一层级 PD 无法保证各个副本的隔离,此时 PD 调度器会退而求其次,保证在 host 这一层的隔离。也就是说,会出现一个 Region 的多个副本分布在同一个 zone 的情况,但是不会出现多个副本分布在同一台主机。

    在 5 副本配置的前提下,如果 z3 出现了整体故障或隔离,并且 z3 在一段时间后仍然不能恢复(由 max-store-down-time 控制),PD 会通过调度补齐 5 副本,此时可用的主机只有 4 个了,故而无法保证 host 级别的隔离,于是可能出现多个副本被调度到同一台主机的情况。

    但假如 isolation-level 设置不为空,值为 zone,这样就规定了 Region 副本在物理层面上的最低隔离要求,也就是说 PD 一定会保证同一 Region 的副本分散于不同的 zone 之上。即便遵循此隔离限制会无法满足 max-replicas 的多副本要求,PD 也不会进行相应的调度。例如,当前存在 TiKV 集群的三个机房 z1/z2/z3,在三副本的设置下,PD 会将同一 Region 的三个副本分别分散调度至这三个机房。若此时 z1 整个机房发生了停电事故并在一段时间后(由 max-store-down-time 控制,默认为 30 分钟)仍然不能恢复,PD 会认为 z1 上的 Region 副本不再可用。但由于 isolation-level 设置为了 zone,PD 需要严格保证不同的 Region 副本不会落到同一 zone 上。此时的 z2 和 z3 均已存在副本,则 PD 在 isolation-level 的最小强制隔离级别限制下便不会进行任何调度,即使此时仅存在两个副本。

    类似地,isolation-levelrack 时,最小隔离级别便为同一机房的不同 rack。在此设置下,如果能在 zone 级别保证隔离,会首先保证 zone 级别的隔离。只有在 zone 级别隔离无法完成时,才会考虑避免出现在同一 zone 同一 rack 的调度,并以此类推。