TIKV BatchSystem 概述
作者: ylldty 原文来源:https://tidb.net/blog/bdf740f2
前言
TIKV 的 BatchSystem 是实现 MultiRaft 的关键模块。在阅读本文章前,大家可以先参考一些官方博客:
TiKV 源码解析系列文章(二)raft-rs proposal 示例情景分析
TiKV 源码解析系列文章(十八)Raft Propose 的 Commit 和 Apply 情景分析
官方的文章基本已经把 RAFT 的使用和 RaftStore 原理讲的比较清晰了。
通过这些文章,大家应该比较了解 RaftStore 的大概流程。在此基础上,本系列文章将会进一步对其细节进行个人的分析。
同时个人认为这个文章对 BatchSystem 的架构图比较清晰明了。
下面我们将要详细说明这个模块各个组件的细节与作用。
BatchSystem 与邮政业务系统
对于之前接触过 RAFT 的同学来说,大家都比较了解整个 RAFT 几乎所有的流程都是以 Msg 来驱动的,可以参考:TiKV 源码解析系列文章(二)raft-rs proposal 示例情景分析
我们可以把整个 BatchSystem 当做一个全国范围的邮局业务系统,把 Msg 当做用户想要邮寄的信件。接下来我们大概描述一下邮局业务系统各个组件的作用。
由于特殊的原因,这个邮件系统做出了限制,同一个时间全国内发往一个省 (Region) 的信件,一次只能送一个:即前一个信件 (Msg) 没有处理完毕前,发往同一个省的信件只能排队等待。不同的省可以并发邮寄。
FSM
我们可以简单的把 Msg 当做一个信件,而把 FSM 当做信封。和现实世界有些不同,并不是每个信件都有一个信封供它使用。而是每个省只有一个信封可用,有几个省就有几个信封。
FSM 信封上面提前标明了目标省地址 (ReginID),不断重复使用。
其结构是这样的:
结构非常简单,receiver 仅仅是一个 channel,用于存放 Msg。
特别的,有一种信件 (ControlMsg) 比较特殊,它有专门的信封 (ControlFsm) 对其提供邮寄服务。
Mailbox
有了信件 (Msg) 与信封 (FSM),我们还需要邮箱 (Mailbox)。和信封类似,也是每个省 (Region) 仅有一个邮箱 (Mailbox) 可用。
每当邮箱 (Mailbox) 收到一个信件 (Msg),那么它负责找到对应省的信封 (FSM),把信件 (Msg) 放到信封 (FSM) 里面去,再将信封 (FSM) 投递到邮局的运转中心去。
当然我们前面也说过,可能对应省的信封 (FSM) 正在运送其他信件 (Msg),这个时候需要告知邮寄失败。
其结构为:
其 sender 对应上面 FSM的 receiver,负责把 Msg 传递给 FSM
state 可以看做 FSM 对象和 FSM 当前的状态(即是否正在运送其他 Msg),Msg 发送给 FSM 后,Mailbox 还需要将 FSM 发送给 运转中心。
特殊信件 (ControlMsg) 拥有特殊信封 (ControlFsm),自然也有特殊的 Mailbox 对应。
Scheduler
前一个小节里面 Mailbox 所说的运转中心指的就是 Scheduler。
Scheduler 的作用非常简单,它负责接收信封 FSM,然后再投递给多个 快递车。我们前面说过,信封FSM 的数量和省 Regions 的数量是一对一的,但是为了节约成本,快递车的数量可能是少于省 Regions 的数量的。Scheduler 收到信封 FSM 后,就负责找到空闲的快递车,然后将 FSM 投递到快递车,让它送到对应的省地址去。
因此,其结果也很简单:
无非就是一个用于发送 FSM 的 sender,其实就是一个 channel 的发送端。快递车哪个空闲了,就通过 channel 的接收端获取 FSM 来进行处理。
特别地,对于特殊信件 (ControlMsg) 特殊信封 (ControlFsm),自然有特殊的 Scheduler 对应:ControlScheduler
Poller
上面 Scheduler 所说的 快递车 就是这个 Poller,Poller 的数量是可配置的,如果系统负载量不大,快递车没有必要拥有那么多,平白造成空转系统消耗。
多个快递车 Poller 共享运转中心 Scheduler channel 的任务屏幕 (receiver)。只要 Scheduler 通过 sender 在任务屏幕 (receiver) 展示了信件 FSM 运送任务,多个 Poller 就需要通过任务屏幕 (receiver) 竞争获取。
同时 Poller 的 handle 成员变量需实现两个重要的接口:handle_normal 与 handle_control。这两个接口用于识别信封上面的省地址 (RegionID),进而向该省 (Region Raft ) 投递信件 (Msg)
因此,其结构为:
Router
目前好像邮局业务系统的整个流程都比较清晰了,用户将信件 (Msg) 投递给对应省 (Region) 的邮箱 Mailbox,Mailbox 将信件放入信封 FSM,然后把信封发送给邮局运转中心 Scheduler,运转中心 Scheduler 将 FSM 放到任务屏幕,多个快递车 (Poller) 竞争任务,然后使用自己的 handle 对 FSM 进行处理,最后将信件 (Msg) 成功运送到 Region 的 Raft 系统。
但是好像还有一个问题,用户手里只有信件,也知道想要投递到哪个省 Region,但是每次都要去找对应 Region 的邮箱 (Mailbox) 好像有点麻烦。
因此,组件 Router 专门负责路由 Mailbox 这一个环节,用户只需要将信件 (Msg) 交给 Router,Router 帮忙定位邮箱 (Mailbox) 的位置,对邮箱 (Mailbox) 进行投递操作。
其结构为:
可以看到,Router 基本包含了 Mailbox 和 scheduler 组件。
关键函数是 try_send,参数是 Msg 和 RegionID,该函数负责传递 RegionID 调用 check_do 获取具体某个 mailbox,然后向 mailbox 传递 Msg 和 scheduler 进行消息投递,完成整个 BatchSystem 对某个 Region Raft 的消息传达。
除此以外,对于特殊的 ControlMsg,Router 还有 send_control 接口。
BatchSystem
好了,讲到这里,BatchSystem 的整体架构已经比较清楚了:
Mailbox和FSM共用一套channel的sender和receiver,用于Msg的传递;scheduler和Poller共用一套channel的sender和receiver,用于FSM的传递Router包含Mailbox和scheduler组件
由于 Router 已经包含了 Mailbox 和 scheduler 组件,Mailbox 包含了 FSM 组件,因此 BatchSystem 的结构只需要 Router 和 Poller:
总结
TIKV 的 RaftStore 系统承担着 Multi Raft 模块多个 Region Msg 的流通与交互,是保证分布式数据库的强力保障。本文为了让大家更加直观的理解 RaftStore 系统,采用了邮政系统来类比。但是实际上,RaftStore 系统不止本文所描述的如此简单,还涉及到 RaftLogEngine、 RaftApplySystem 等等子功能。我们有机会会在接下来的系列文章继续详细展开描述。
版权声明: 本文为 InfoQ 作者【TiDB 社区干货传送门】的原创文章。
原文链接:【http://xie.infoq.cn/article/32d23cdf59142beb1fb8f5d80】。文章转载请联系作者。







评论