TiDB 6.0 体验:TiKV 重启后 leader 均衡加速
本文作者:h5n1,TiDB 爱好者,目前就职于联通软件研究院。
1. 前言
为了均衡资源使用 TiDB 初始化后默认会创建 region-scheduler、leader-scheduler、hot-region-scheduler 三个调度器分别用于磁盘容量、计算和访问热点的均衡调度,TiDB 会根据计算的分值,将 region follower 或 leader 从高分值 TiKV 调度到低分值 TiKV,使各节点尽量达到均衡状态,以充分利用各节点资源。
2. region 调度和限制
region 的调度是由 PD 根据 TiKV 上报的信息产生 operator 下发到 TiKV 去执行,Operator 是一组用于某个调度的操作集合,比如将 region 2 的 leader 由 store 5 转移到 store 3。operator 调度是针对 region 的,实际上就是对 raft 成员的管理。
region 调度的基本过程如下:
- TiKV 通过 StoreHeartbeat 和 RegionHeartbeat 两种心跳消息周期性的向 PD 报告 store 和 region 状态信息。如容量、流量、region 范围、副本状态等信息。
- Scheduler 每隔一定时间会根据 TiKV 上报的信息生成 operator,每种调度会考虑不同调度逻辑和限制约束等。
- Scheduler 产生 operator 会放到等待队列中,随机选择或根据优先级将等待队列中的 operator 加入到 notifyqueue 中等待下发,同时会将 operator 转移到运行队列中从等待队列中删除。
- 之后等到 TiKV 发送心跳时,将相应的 operator 通过心跳处理信息发送给 Region Leader 去处理。
- leader 根据 operator step 完成调度处理,处理完成后或超时后,pd 从运行队列中移除相关 operator。
为控制调度速度,PD 提供了相关参数进行限制,balance-leader 的调度速度由 leader-schedule-limit 参数限制(默认值 4),调度执行时会首先判断是否允创建 operator,当前 runningOperator 队列中相应类型的 operator 数量小于 limit 参数限制时才允许调度产生 operator,之后将产生的 Operator 加入到等待队列。
另外 scheduler-max-waiting-operator 参数限制 waitingOperator 队列中每类调度最大的 operator 数量(4.0 版本后默认为 5),当 operator 数量达到参数值时则也不允许添加 operator,从而也会影响 operator 产生速度。在 6.0 版本中该参数被设置为了隐藏参数,通过 pd-ctl config show all 命令才能看到,可使用 pd-ctl config set 修改。
$ pd-ctl -u 10.125.144.18:23791 config show | grep scheduler-max-waiting-operator
$pd-ctl -u 10.125.144.18:23791 config show all | grep scheduler-max-waiting-operator
"scheduler-max-waiting-operator": 5
3. leader 调度加速实现
leader 的均衡由 balance-leader-scheduler 调度器控制,每隔一定时间会进行一次调度,间隔的最小时间是 10ms(MinScheduleInterval),当调度失败次数达到 10 次后,会调整间隔时间,最大间隔时间不超 5 秒。
理想情况下 balance-leader-scheduler 每隔 10ms 完成一次调度,1 秒内最多产 100 个 operator,处理 100 个 region leader 的转移,当集群数据量很大时,当 TiKV 重启后,由于 operator 产生速度的影响导致 leader 调度速度,较长时间的不均衡容易引发性能问题。比如当有 10 万个 region leader 需要调度时完成 operator 的创建就得需要 17 分钟。
一种优化方式就是在不减少调度间隔增加压力的情况下,通过每次调度产生多个 operator 以提升 operator 的产生速度,为此 6.0 版本中为 balance-leader-scheduler 添加了 batch 选项,通过 pd-ctl 工具修改,默认值为 4(受 leader-schedule-limit、scheduler-max-waiting-operator 限制),可选范围值为 1-10,这样在每次 sheduler 调度时产生多个 operator,从而提升 transfer leader 速度。
$ pd-ctl -u pd-address:pd_port scheduler config balance-leader-scheduler set batch 6
$ pd-ctl -u pd-address:pd_port scheduler config balance-leader-scheduler
{
"ranges": [
{
"start-key": "",
"end-key": ""
}
],
"batch": 6
}
4. 测试
4.1 测试环境
3 个 TiKV,每 TiKV 约 3.5 万个 region,总存储大小 13.2 TB。
4.2 测试方式
每次测试前 stop tikv 然后修改相关参数后启动 TiKV,观察 TiKV 监控的 leader 均衡时间。
4.3 测试结果
不同参数值下 TiKV 重启后 leader 均衡时间
schedule-limit | max-waiting-operator | batch | leader 均衡时间 | |
默认值 | 4 | 5 | 4 | 2 分钟 |
旧版本 | 4 | 5 | 1 | 7 分钟 |
较高值 | 10 | 10 | 10 | 1 分钟 |
最低值 | 1 | 1 | 1 | 无法均衡 |
不同参数值下 TiKV 重启后 leader 监控
- 默认值
旧版本
6.0 版本前 leader-scheduler 没有 batch 选项,通过设置选项值为 1 模拟。
- 较高值
- 最低值:
12:40 启动 TiKV 后一直未发生调度,12:46 调整 leader-schedule-limit=2 仍未发生调度,12:50 调整 schedule-limit=1、max-waiting-operator=2 后开始调度。
当 max-waiting-operator=1 时有大量的 transfer leader 请求被 cancel 而不能完成调度,经确认此为 bug。
[2022/05/12 12:45:38.419 +08:00] [INFO] [operator_controller.go:597] ["operator canceled"] [region-id=28977] [takes=0s] [operator="\"balance-leader {transfer leader: store 2 to 1} (kind:leader, region:28977(365, 35), createAt:2022-05-12 12:45:38.419949916 +0800 CST m=+418435.703819099, startAt:0001-01-01 00:00:00 +0000 UTC, currentStep:0, size:95, steps:[transfer leader from store 2 to store 1])\""]
该问题原因是由于在 operator 加入到 waiting 队列后会进行一次检查,之后 wopStatus 会+1,当从 waiting 队列取出后会再次检查,导致 operator 被 cancel。对于生产系统保持默认即可。
5. 总结
由于早期版本中对 balance-leader 的 operator 产生速度有限制,而 transfer leader 操作本身比较快,造成了整体 leader 均衡速度较慢,TiDB 6.0 版本通过增加 balance-leader-scheduler 每次调度时产生的 operator 数量,极大的缩短了 TiKV 重启后 leader 的整体迁移速度,降低因为长时间不均衡带来的性能影响,对于大集群的快速恢复提供了保障。