mysql binlog 轻量同步工具 binlog portal
使用 binlog 的原因
近期需要重构一个老系统,需要从几个服务中实时同步订单的修改到重构表里。
这里就面临两个选择,
在每个服务的 mysql 操作前埋点,发送修改信息到队列或服务上。这种方案需要修改多个服务的代码并且测试对原系统的影响,有额外开发和测试成本。
同步 mysql 的 binlog,根据表的 insert 和 update 更新新表。但是需要维护一个 binlog 同步的服务
本次选择了 binlog 同步的方式。搭建的 binlog 服务也可以用在之后新系统的缓存更新和同步 ES 索引上,相对于埋点这种只有一次性作用的方式,性价比较高。
工具调研:canal 和 mysql-binlog-connector-java
1.canal
要实现 binlog 同步服务,使用较多的开源方案是 canal,运行比较稳定,而且功能也很丰富。
但是在实际部署服务的时候,遇到了一些问题:
canal 采用了 client-server 的模式,至少需要部署两个集群。我们的项目都是使用私有云部署,为了稳定运行,就有额外的资源和维护开销。
- 后来发现 canal server 可以投递信息到 kafka。但是我们的消息队列是自研的,只能尝试去改源码。
canal 的 server 是完整独立的包,无法直接用 springboot 嵌套。而我们的基础组件都依赖于 springboot,比如监控,配置中心等。
canal 的 HA 部署使用的是 zookeeper,很可惜我们并没有可用的 zookeper 集群,也没有资源重新部署一个。
单机部署的时候,已经处理的 binlog postion 是保存在文件里面的,我们用的私有云 docker,重启后全丢失。
2.mysql-binlog-connector-java
调研同时也发现了另一个 binlog 同步工具,mysql-binlog-connector-java
。
这是一个开源的 binlog 同步工具,功能很简单,就是接收 binlog 信息。作为一个依赖 jar 可以很容易在 springboot 中使用。
但是没有对 binlog 的内容做格式化处理,使用很不方便。当然更没有保存信息和分布式部署功能。
自研工具包 binlogportal
基于这些问题,我们需要一个具有以下特性的 binlog 同步工具:
可以使用 springboot 加载运行,具有较好的扩展性
- 说白了就是作为一个 jar 包,开放出接口可以自定义处理 binlog 信息的方式
可以使用 redis 实现 binlog position 的保存和分布式部署
为了满足这些条件,通过对mysql-binlog-connector-java
封装后,实现了自研的工具 binlogportal。
提供了 binlogportal-spring-boot-starter 包,可使用 spring boot 快速部署
使用 redis 保存 binlog position 信息,重启后可从上次 position 位置开始
当前支持 insert 和 update 的结构化
提供默认的 http 事件处理器。可通过实现 IEventHandler 接口,自定义事件处理器
使用 redis 作为分布式协调器,可多机部署实现高可用
使用说明
Mysql 配置
Mysql 需要开启 binlog 并设置为 row 模式
同步 binlog 使用的 mysql 账号,需要添加 REPLICATION 权限,示例如下:
通过 spring boot 构建项目
直接依赖 binlogportal-spring-boot-starter
通过 spring boot 的 application.yml 配置启动器
Starter 启动
- spring boot autoconfig 启动成功后,会把 BinlogPortalStarter 的实例注入到 IOC 中
- 项目中通过注入的方式获取 binlogPortalStarter 使用
- binlogPortalStarter.start()会为每个 mysql 库创建一个线程处理 binlog
- 下面是使用 CommandLineRunner 启动 starter 的一个例子
非 spring boot 项目
非 spring boot 项目,可以使用基础包
依赖后实现配置类
BinlogPortalConfig
和SyncConfig
,传入 Starter 中运行即可
2.分布式部署实现
项目中高可用实现是基于 redis 的分布式锁。
每个实例都会加载全部数据库的配置,在创建 binlog 连接之前,先要获取 redis 锁,获取锁后会定时刷新锁的过期时间。所有实例会定时重新抢锁。
同一个 mysql 库的 binlog 文件和 position 会保存在 redis 里,如果一个实例宕机。新抢到锁的实例在初始化时,会使用上个实例已保存的 binlog 信息继续获取。
项目源码可在 Git 上查看。
项目的 Git 地址:https://github.com/dothetrick/binlogportal
点击 阅读原文 可跳转到 git 项目地址
以上内容属个人学习总结,如有不当之处,欢迎在评论中指正
版权声明: 本文为 InfoQ 作者【dothetrick】的原创文章。
原文链接:【http://xie.infoq.cn/article/d5a3ae0fa83ca39531b83ec29】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论