1 调度的意义
1. 如何保证同一个 Region 的多个 Replica 分布在不同的节点上
2. TiKV 集群进行跨机房部署用于容灾的时候,如何保证一个机房掉线,不会丢失 Raft Group 的多个 Replica
3. 添加一个节点进入 TiKV 集群之后,如何将集群中其他节点上的数据搬过来
4. 当一个节点掉线时,会出现什么问题?整个集群需要做什么事情?如果节点只是短暂掉线(重启服务),那么如何处理?如果节点是长时间掉线(磁盘故障,数据全部丢失),需要如何处理?
5. 假设集群需要每个 Raft Group 有 N 个副本,那么对于单个 Raft Group 来说,Replica 数量可能会不够多(例如节点掉线,失去副本),也可能会 过于多(例如掉线的节点又回复正常,自动加入集群)。那么如何调节 Replica 个数?
6. 读/写都是通过 Leader 进行,如果 Leader 只集中在少量节点上,会对集群有什么影响?
7. 并不是所有的 Region 都被频繁的访问,可能访问热点只在少数几个 Region,这个时候我们需要做什么?
8. 集群在做负载均衡的时候,往往需要搬迁数据,这种数据的迁移会不会占用大量的网络带宽、磁盘 IO 以及 CPU?进而影响在线服务?
基于以上问题,衍生了PD模块,即调度管理模块(Placement Driver)
2 PD模块设计关键点
围绕上述问题,有几个核心解决点如下
- 副本数量要合理
- 副本分布要均匀
- 新加节点后,可以将其他节点上的副本迁移过来
- 下线节点后,需要将该节点的数据进行迁移走
因此整体的优化原则:
- 维持整个集群的 Leader 分布均匀
- 维持每个节点的储存容量均匀
- 维持访问热点分布均匀
- 控制 Balance 的速度,避免影响在线服务
- 管理节点状态,包括手动上线/下线节点,以及自动下线失效节点
3 调度基本操作
- 增加一个Replica
- 删除一个Replica
- 变更Replica之间的leader
4 调度信息收集
4.1 TiKV节点状态
每个TiKV节点会通过心跳包定期向PD汇报节点整体信息,信息指标包括
- 总磁盘容量
- 可用磁盘容量
- 承载的Region数量
- 数据写入速度
- 是否过载
4.2 Region状态
每个 Raft Group 的 Leader 和 PD 之间存在心跳包,也是通过心跳包进行信息汇报,信息指标如下:
- Leader的位置
- Followers 的位置
- 掉线 Replica 的个数
- 数据写入/读取的速度
心跳包会设置超时时间,当超过一定时间无法接到心跳包时,PD也会做对应的下线转移处理
5 调度实现
PD 不断的通过 Store 或者 Leader 的心跳包收集信息,获得整个集群的详细数据,并且根据这些信息以及调度策略生成调度操作序列,每次收到 Region Leader 发来的心跳包时,PD 都会检查是否有对这个 Region 待进行的操作,通过心跳包的回复消息,将需要进行的操作返回给 Region Leader,并在后面的心跳包中监测执行结果。注意这里的操作只是给 Region Leader 的建议,并不保证一定能得到执行,具体是否会执行以及什么时候执行,由 Region Leader 自己根据当前自身状态来定。