TiDB中的Placement Driver(简称”PD”)是整个集群的大脑,它的能力包括:集群TiKV元数据存储、分配全局ID和事务ID、生成全局时间戳TSO、收集集群信息进行调度、提供Label标签等能力。在TiDB 4.0版本中,PD模块引入了一套副本规则系统-Placement Rules,它可以用来指导PD生成对应的调度。本文具体描述Placement Rules的概念及如何使用Placement Rules来进行副本的管理调度。
一.Placement Rules解决什么问题?
Placement Rules定义不同规则来指定不同数据范围(range)的副本数量、Raft角色、放置位置等属性,这些规则会在PD进行调度的时候使用以生成对应的调度,最终使Region副本的分布与规则定义一致。
二.规则有哪些属性?
为了满足不同来源的规则隔离的要求,TiDB对规则引入了组(group)的概念,也就是说我们可以定义某个规则是属于哪个group,不同的规则可以属于相同的group。
定义一个规则时,我们需要组合利用以下这些属性:
1. Group_id:规则所属组的id
2. Id:规则id
3. Group_index:组内堆叠次序
4. Group_override:是否覆盖 index 的更小 Rule
5. Start_key:规则适用的数据范围的start key
6. End_key:规则适用的数据范围的end key
7. Role:副本角色,如voter/leader/follower/learner
8. Count:副本数量
9. LabelConstraint:用于按Label筛选节点,支持in/notIn/exists/notExists
10. LocationLabels:用于物理隔离
11. IsolationLevel:用于设置最小强制物理隔离级别,默认为空
三.怎么查看一个集群当前的规则?
上面的描述还是太偏概念性,以一个实际的环境为例,我们怎么知道这个集群当前的Placement Rules是怎么设置的。由于Placement Rules是集成在PD中的功能,我们可以使用pd-ctl工具来查看,也可以使用tiup ctl:<version> pd命令来查看,具体语法可参考官网文档 PD Control 使用说明 | PingCAP 文档中心。下图展示某集群的规则信息:
通过config placement-rules show命令,查看到当前集群只有一个default规则,所有数据采用3副本且每个副本都是voter角色。config placement-rules rule-bundle命令可以方便地同时查看和修改规则分组及组内的所有规则。
四.怎么修改一个集群的规则?
集群的Placement Rules是可以新增或修改的,新增或修改规则是通过编辑规则文件并保存到pd中实现,规则也可以直接导出成json格式文件。
--导出规则,使--out 生成json文件
config placement-rules rule-bundle get pd --out="rules.json" |
---|
--修改规则,使--save载入json文件
示例rules.json文件 |
---|
{ "group_id": "pd", "group_index": 0, "group_override": false, "rules": [ { "group_id": "pd", "id": "dc1", "start_key": "", "end_key": "", "role": "leader", "is_witness": false, "count": 1, "label_constraints": [ {"key": "dc", "op": "in", "values": ["dc1"]} ], "location_labels": ["zone", "dc"] }, { "group_id": "pd", "id": "dc2", "start_key": "", "end_key": "", "role": "voter", "is_witness": false, "count": 1, "label_constraints": [ {"key": "dc", "op": "in", "values": ["dc2"]} ], "location_labels": ["zone", "dc"] }, { "group_id": "pd", "id": "dc3", "start_key": "", "end_key": "", "role": "follower", "is_witness": false, "count": 1, "label_constraints": [ {"key": "dc", "op": "in", "values": ["dc3"]} ], "location_labels": ["zone", "dc"] } ] } |
config placement-rules rule-bundle set pd --in="rules.json" |
---|
五.如何验证规则是否生效?
规则成功修改后,使用config placement-rules show便能看到修改后的规则。根据规则内容,我们的预期是三个副本分别放置于dc1、dc2和dc3,且Leader默认只放置于dc1之上。当dc1故障后,Leader会优先切换到dc2之上,因为dc2的role为voter。
通过Grafana中的leader图表,我们发现当应用了新的规则后,所有的Leader都迁移到dc1,验证了我们的猜想。
而当dc1故障时,所有的Leader切换到dc2上面,也符合我们的预期。
当dc1重新恢复后,Leader又会自动切换到dc1上面。
至此,我们通过一个简单的示例演示如何配置Placement Rules来模拟一个三数据中心三个副本的故障恢复场景。相信通过以上内容介绍,大家对使用Placement Rules来影响PD调度从而实现精细化调度副本以及进一步实现多地多中心有了进一步的认识。另外关于Placement Rules的具体使用文档,读者可以参考 Placement Rules 使用文档 | PingCAP 文档中心 章节获取详细内容。
六.加载规则遇到的问题?
首次加载rules.json时失败,报错为: [400] "[PD:placement:ErrRuleContent]invalid rule content, rule 'dc1' from rule group 'pd' can not match any store",这是因为我们虽然设置了每个规则的label_constraints及location_labels,但在此之前我们并没有给集群拓扑配置labels。因此,在配置Placement Rules之前,需要提前配置labels。关于根据集群拓扑配置labels,可参考官网 通过拓扑 label 进行副本调度 | PingCAP 文档中心。
之前我们了解过tiup工具可以使用edit-config来修改集群配置,这里我们便使用tiup cluster edit-config <cluster-name>的方式来增加PD/TiKV的labels并重新reload生效,主要配置PD和TiKV(如果有TiFlash的话也需要配置)。