1.Kingbus介绍1.1什么是Kingbus?kingbus是一个基于raft强共识协议的分布式MySQLbinlog存储系统。它可以作为MySQLSlave从真正的Master同步binglog并存储在分布式集群中。同时作为MySQLMaster将集群中的binlog同步给其他Slave。Kingbus具有以下特点:兼容MySQL复制协议,通过Gtid同步Master上的binlog,支持slave通过Gtid从Kingbus拉取binlog。跨区域数据复制,kingbus通过Raft协议支持跨区域数据复制。写入集群的binlog数据在多个节点间强一致,binlog顺序与master上完全一致。高可用,由于Kingbus是建立在Raft强共识协议之上的,当集群中超过半数节点存活时,可以实现整个binlogpull和push服务的高可用。1.2kingbus可以解决什么问题?Kingbus可以减少Master的网络传输流量。在一主多从的复制拓扑中,主服务器需要向每个从服务器发送二进制日志。如果slave过多,网络流量可能会达到master网卡的上限。例如在master上删除大表或在线DDL等操作,可能会导致瞬间产生大量的binlogevent。如果10个slave连到master上,master上的网卡流量就会放大10倍。如果master使用的是千兆网卡,超过10MB/S的流量可能会导致其网卡跑满。通过kingbus连接master,slave可以分布到多台机器上,平衡传输流量。为了简化MasterFailover的过程,只需要将一个连接到kingbus的Slave提升为Master,并将kingbus重定向到新的Master。其他slave仍然连接在kingbus上,复制拓扑保持不变。为Master节省空间存放binlog文件。一般MySQL都会配备比较昂贵的SSD。如果binlog文件占用空间很大,那么MySQL中存储的数据就不得不减少。可以通过将binlog存放在kingbus中来减少Master上存放的binlog文件数量。支持异构复制。通过阿里巴巴开源的Canal对接Kingbus,Kingbus持续推送binlog到Canal。Canal收到binlog后,将其推送到Kafka消息队列中,最后存储到HBase中。业务部门直接通过Hive编写SQL,实现实时业务分析。.2.kingbus整体架构kingbus整体架构如下图所示:storage负责存储raftlogentry和Metadata。kingbus中将raftlog和mysqlbinlog融合在一起,通过不同的header信息来区分raftlog的数据部分。就是binlogevent,这样就不用把两类日志分开存放,节省存储空间。因为kingbus需要存储一些元信息,比如raft节点投票信息,以及一些特殊的binlog事件(FORMAT_DESCRIPTION_EVENT)的具体内容。Raft复制kingbus集群的leaderelection和logreplication等功能,使用etcdraft库。binlogsyncer只运行在Raft集群的lead节点上,整个集群只有一个syncer。syncer伪装成slave,与master建立主从复制连接。master会根据syncer发送的executed_gtid_set过滤syncer已经接受的binlogevents,只发送syncer没有收到的binlogevents。这种复制协议完全兼容MySQL的主从复制机制。syncer收到binlog事件后,会根据binlog事件类型做一些处理,然后将binlog事件封装成消息提交给raft集群。通过raft算法,这个binlogevent可以存储在多个节点上,实现强一致性。binlogserver是一个Master,实现了复制协议。真正的slave可以连接到binlogserver监听的端口。binlogserver会将binlogevent发送给slave。整个发送binlogevent的过程是参考MySQL复制协议实现的。当没有binlog事件发送给slave时,binlogserver会周期性的向slave发送一个心跳事件来保持复制连接的存活。apiserver负责整个kingbus集群的管理,包括:raftclustermembership操作,查看集群状态,添加节点,移除节点,更新节点信息等binlogsyncer相关操作,启动一个binlogsyncer,停止binlogsyncer,查看binlogsyncer状态。对于binlogserver相关的操作,启动一个binlogserver,停止binlogserver,查看binlogserver的状态。server层的各种异常不会影响raft层。服务器可以理解为一个插件,可以按需启动和停止。以后扩展kingbus时,只需要实现相关的logicserver即可。比如你实现了一个Kafka协议服务器,你可以通过Kafka客户端在Kingbus中消费消息。3.Kingbus核心实现3.1Storage核心实现存储中有两种日志形式,一种是raft日志(以下简称raft日志),由raft算法生成并使用,另一种是用户形式日志(即,mysql二进制日志事件)。在Storage的设计中,两种Log形式合并为一个LogEntry。只是通过不同的头部信息来区分。存储由数据文件和索引文件组成,如下图所示:一个段的大小是固定的(1GB),只能追加。名称为first_raft_index-last_raft_index,表示该段的raft索引范围。只能写入最后一段,其文件名为first_raft_index-inprogress,其他段为只读。只读段和对应的索引文件都是通过mmap进行读写的。***一个段的索引内容同时存在于磁盘和内存中。读取索引只需要读入内存即可。3.2etcdraft库的使用etcdraft库在处理应用日志、提交条目等时是单线程的,具体功能见链接。该功能的处理时间应尽可能短。如果处理时间超过了raft选举时间,会导致集群重新选举。这一点需要特别注意。3.3binlogsyncer的核心实现binlogsyncer的主要工作是:拉取binlog事件,解析处理binlog事件,提交binlog事件到raft集群。显然,可以利用流水线机制来提高整个流程的处理速度。kingbus的每个stage都由一个单独的goroutine处理,不同的stage之间通过pipeline连接。由于binlogsyncer是一个一个接收binlogevents,所以syncer无法保证事务的完整性。有可能syncer挂掉后,需要重新连接Master。这时候最后一个事务可能是不完整的,binlogsyncer需要找出事务完整性的能力,kingbus实现了事务完整性分析的功能,完全参考了MySQL的源码。3.4binlogserver的核心实现binlogserver实现了master的功能。当slave与binlogserver建立复制连接时,slave会发送相关命令,binlogserver需要响应这些命令。最后将binlog事件发送给slave。对于每一个slave,binlogserver都会启动一个goroutine不断的读取raftlog,并去掉相关的header信息成为一个binlogevent,然后发送给slave。4.总结本文简要介绍了Kingbus的总体架构、核心组件和流程。通过本文,希望读者对Kingbus有一个更全面的了解。
