Springboot-mysqlbinlog 日志监听实践

鸡声茅店月,人迹板桥霜。

1 前言

关于 mysql 的数据同步,一般都是读取 mysql 的 binlog 日志文件,来获取数据的变更进行同步。在开源项目中,监听 mysql binlog 的工具有很多, 比如 mysql-binlog-connector-java、cannal 、flink-cdc , 在本文中会介绍第一个工具 mysql-binlog-connector-java 的用法。它是 github上的一个开源项目, 是二进制日志监听d的利器。

在介绍之前,我们需要先复习一下 mysql 数据同步的知识,如下图所示,mysql 的 master 节点在数据产生变动时,会生成一个 binarylog, slave 节点通过监听来读取 mysql 的日志,通过 io thread 来将读取到的信息转换成 relay log 中继日志,最后通过 sql thread 的操作在 slave 数据库中恢复数据,这就是数据同步的主要流程。

2 mysql 开启 binlog

在使用之前 mysqlbinlog 之前,需要先开启 mysql binlog , 通过命令 show variables like 'log_bin'; 可以查询数据是否已经开启 binlog 日志,在没有开启的情况下,是不能监听数据变动的。

ini 复制代码
mysql 配置文件 my.cnf 中添加以下配置即可开启 binlog
log_bin=mysql-bin
binlog-format=ROW
server-id=1
  • 开启 mysql binlog 时,需要配置 binlog 的日志格式和 server-id, 日志格式分为三种类型,分别是 STATEMENT、ROW、MIXED,在这里需要采用 ROW 模式。
  • server-id 用于标识 sql 语句是来自哪个 server,如果要正常监听事件就需要在配置文件中进行设置 server-id。

3 mysql-binlog 介绍

mysql-binlog 主要是通过监听并解析 mysql binlog,转换成对应的事件来提供给开发者来操作,主要的事件如下所示:

sql 复制代码
RotateEventData  当MySql的binlog 文件发生滚动的时候会发生此事件
FormatDescriptionEventData  格式化显示事件信息,包括 binlog 版本,mysql 版本,事件时间戳,数据长度以及检验方式
QueryEventData   当binlog格式设置的是statement|mixed且做DB有了更新、插入或删除操作的时候会发生改(例如修改Row,alter表等)
TableMapEventData   表映射关系事件, 标识数据库以及数据库表的变动信息。
WriteRowsEventData  表新增数据事件,记录数据库表的新增行信息,可能是多行信息。
UpdateRowsEventData 表更新数据事件,记录数据库表的行更新,可能涉及多个行变动。
DeleteRowsEventData 表删除数据事件,记录数据库表的行删除,删除行的完整信息,会有多行记录。

当有一个变更事件时,首先是 RotateEventData 进行响应,然后是 TableMapEventDataFormatDescriptionEventData 事件,最后才是具体的增删改查事件。一个事件包含有事件头和事件体, 事件头是事件的通用信息,包括事件类型、事件时间、数据长度以及 serverId。事件体即事件的数据信息,不同的事件类型,数据的格式不尽相同。

bash 复制代码
作为 mysql binlog 的日志同步,有下面的优点:
支持解析binlog文件、解析GTID(全局事务id)
支持重连
支持设置故障转移策略
TLS协议安全使用
JMX-friendly
实时监控状态
无第三方依赖

4 环境准备

在开始编码之前,需要引入对应的依赖,

xml 复制代码
<dependency>
    <groupId>com.zendesk</groupId>
    <artifactId>mysql-binlog-connector-java</artifactId>
    <version>0.27.1</version>
</dependency>

另外,在这个过程中,会涉及到数据库表的操作,由于 mysql-binlog 没有展示对应的表字段,所以开发了一个能查询数据库表字段、注释的方法,这里用到了 hutool 工具类,真心很好用,借助这个机会展示一下如何在非web 环境下操作数据库,在操作之前,需要先引入 hutool的依赖和数据库连接驱动的依赖,这两个比较基础,就不在这里贴了。

初始化一个 DruidDataSource, 使用 Db.use 方法即可获取到一个数据库连接。 查询数据库表结构的sql 如下所示:

mysql 复制代码
-- 查询数据库表字段 传入数据库库名和表名即可查询
SELECT COLUMN_NAME as 'name', DATA_TYPE as 'type' , COLUMN_COMMENT as 'comment', ordinal_position as 'srt' 
FROM information_schema.`COLUMNS` 
WHERE TABLE_SCHEMA = 'table_name'  AND TABLE_NAME = 'database_name' order by ordinal_position ;

执行 query 方法,可以查询到一个数据列表,每个实体都对应着一行数据,只需要 get 对应的字段名,即可获取到对应的内容。 最终展示的效果如下图所示:

5 mysql-binlog 实践

终于到了重点部分,首先需要创建一个 BinaryLogClient,需要传入数据库地址,端口账号和密码。

注册监听事件,这里监听的是三个通用的事件,即 RotateEventDataTableMapEventDataFormatDescriptionEventData 事件。

当有数据新增时,会执行数据新增的时间,这里会打印对应的数据库表,以及新增的数据行信息,这里可能会存在多行的数据。

当有数据更新事件时,这里会打印数据变更前后的信息,可以对比比较数据的变动。

当有数据删除时,这里会打印对应的删除信息。

结果展示

sql 复制代码
数据库表信息  103	account	user
插入数据 insert columns {0, 1, 2, 3, 4, 5}
data [12008, 34, 34, 34, null, null]

更新数据 update columns {0, 1, 2, 3, 4, 5}
before -->
[12008, 34, 34, 34, null, null]
after  -->
[12008, 344444, 34, 34, null, null]

删除数据 delete columns {0, 1, 2, 3, 4, 5}
data [12008, 344444, 34, 34, null, null]

6 使用总结

通过以上的演示和总结,了解了 mysql-binlog 的使用方法,并且也介绍了其原理,数据库的变更信息,一直是非常重要的存在,可以结果 hutool 工具类,通过监听数据库表的方式来实现日志信息的记录,这样相比注解的方式更为简单且高效,不影响业务的响应时间。本文中所涉及的代码均已上传至 Git仓库,欢迎大家 stars, 项目 github 地址 springboot-auth

相关推荐
小坏讲微服务2 小时前
Docker-compose 搭建Maven私服部署
java·spring boot·后端·docker·微服务·容器·maven
suuijbd2 小时前
SpringCloud+Netty集群即时通讯项目
spring boot·分布式·spring cloud·java-rabbitmq·java-zookeeper
陈果然DeepVersion3 小时前
Java大厂面试真题:Spring Boot+Kafka+AI智能客服场景全流程解析(十)
java·spring boot·ai·kafka·面试题·向量数据库·rag
摇滚侠4 小时前
Spring Boot3零基础教程,Reactive-Stream 四大核心组件,笔记106
java·spring boot·笔记
陈果然DeepVersion5 小时前
Java大厂面试真题:Spring Boot+微服务+AI智能客服三轮技术拷问实录(六)
java·spring boot·redis·微服务·面试题·rag·ai智能客服
熙客6 小时前
Kubernetes是如何保证有状态应用数据安全和快速恢复的
mysql·云原生·容器·kubernetes
爱宇阳6 小时前
从容器化到自动化:Spring Boot 项目 Docker 部署与 GitLab CI/CD 集成 Harbor 全流程
spring boot·docker·自动化
倔强的石头1067 小时前
KingbaseES:从兼容到超越,详解超越MySQL的权限隔离与安全增强
数据库·mysql·安全·金仓数据库
小鸡毛程序员7 小时前
我在CSDN学MYSQL之----数据库基本概念和基本知识(下)
数据库·mysql
米花町的小侦探7 小时前
解决 GORM + MySQL 5.7 报错:Error 1067: Invalid default value for ‘updated_at‘
mysql