Canal 实战 | 第一篇:SpringBoot 整合 Canal + RabbitMQ 实现监听 MySQL 数据库同步更新 Redis 缓存

简介: Canal 实战 | 第一篇:SpringBoot 整合 Canal + RabbitMQ 实现监听 MySQL 数据库同步更新 Redis 缓存

一. Canal 简介

微信图片_20230710083040.png


canal [kə’næl],译意为水道/管道/沟渠,主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费


早期阿里巴巴因为杭州和美国双机房部署,存在跨机房同步的业务需求,实现方式主要是基于业务 trigger 获取增量变更。从 2010 年开始,业务逐步尝试数据库日志解析获取增量变更进行同步,由此衍生出了大量的数据库增量订阅和消费业务。


基于日志增量订阅和消费的业务包括


数据库镜像

数据库实时备份

索引构建和实时维护(拆分异构索引、倒排索引等)

业务 cache 刷新

带业务逻辑的增量数据处理

当前的 canal 支持源端 MySQL 版本包括 5.1.x , 5.5.x , 5.6.x , 5.7.x , 8.0.x


二. Canal 工作原理

1. MySQL主备复制原理

微信图片_20230710083044.jpg


MySQL master 将数据变更写入二进制日志( binary log, 其中记录叫做二进制日志事件binary log events,可以通过 show binlog events 进行查看)

MySQL slave 将 master 的 binary log events 拷贝到它的中继日志(relay log)

MySQL slave 重放 relay log 中事件,将数据变更反映它自己的数据

2. Canal 工作原理

Canal 模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,向 MySQL master 发送dump 协议


MySQL master 收到 dump 请求,开始推送 binary log 给 slave (即 canal )


Canal 解析 binary log 对象(原始为 byte 流)


三. Canal 实战

1. 需求分析

有来项目 youlai-mall 当前进度下使用Redis缓存MySQL数据库中的OAuth2客户端信息、角色权限映射关系、菜单路由,现在这样有两个很明显的问题:


在后台管理界面修改角色、菜单、权限和OAuth2客户端任何一方信息都需要让缓存失效或者更新缓存,代码耦合性高;

数据库直接修改上面相关信息,缓存无法失效或更新。

第一种情况至少有解决方案,无非就在代码层面上清缓存或者更新缓存,但是如果是直接修改数据库呢?实际工作可能经常会遇到直接修改数据库的场景,本篇通过SpringBoot 整合 Canal + RabbitMQ 实现对数据库的监听然后同步让缓存失效或者更新。当然有来项目引入 Canal 中间件刷新缓存只是个开始,接下来还会使用 Canal 同步商品表至 ElasticSearch。


2. MySQL开启 binlog 日志

MySQL 部署:https://www.cnblogs.com/haoxianrui/p/15488810.html


开启 biglog 日志


vim /etc/my.cnf

1

添加配置


[mysqld]

log-bin=mysql-bin # 开启binlog

binlog-format=ROW # 选择ROW模式

server_id=1 # 配置MySQL replaction需要定义,不和Canal的slaveId重复即可

重启MySQL ,查看配置是否生效


show variables like 'log_bin';

1

微信图片_20230710083110.png


3. RabbitMQ 队列创建

添加交换机 canal.exchange

微信图片_20230710083113.png


添加队列 canal.queue


微信图片_20230710083133.png

队列绑定交换机

微信图片_20230710083137.png

微信图片_20230710083153.png



4. Canal 配置和启动

Canal Server下载

官方文档:https://github.com/alibaba/canal/wiki

项目地址:https://github.com/alibaba/canal

下载地址:https://github.com/alibaba/canal/releases

进入下载地址,选择 canal.deployer-1.1.5.tar.gz


微信图片_20230710083205.png


将压缩包解压,我这里把最后解压出来的文件放入 有来项目 的middleware中间件文件,和之前的 nacos 和 sentinel 同一个套路。


微信图片_20230710083208.png


Canal Server配置

需要配置的东西就两项,一个是监听数据库配置,另一个是 RabbitMQ 连接配置。


改动的两个文件分别是 Canal 配置文件 canal.properties 和 实例配置文件 instance.properties


㊙️:一个 Server 可以配置多个实例监听 ,Canal 功能默认自带的有个 example 实例,本篇就用 example 实例 。如果增加实例,复制 example 文件夹内容到同级目录下,然后在 canal.properties 指定添加实例的名称。

微信图片_20230710083231.png



canal.properties


配置 Canal 服务方式为 RabbitMQ 和连接配置(🏷 只列出需要修改的地方)


# tcp, kafka, rocketMQ, rabbitMQ

canal.serverMode = rabbitMQ

##################################################

#########       RabbitMQ      #############

##################################################

rabbitmq.host = x.youlai.tech

rabbitmq.virtual.host =/

rabbitmq.exchange =canal.exchange

rabbitmq.username =guest

rabbitmq.password =guest

rabbitmq.deliveryMode =


instance.properties


监听数据库配置(🏷 只列出需要修改的地方)


# position info

canal.instance.master.address=x.youlai.tech:3306

# username/password

canal.instance.dbUsername=root

canal.instance.dbPassword=root

# mq config

canal.mq.topic=canal.routing.key



5. SpringBoot 整合 Canal + RabbitMQ

🏠 完整源码:https://gitee.com/youlaitech/youlai-mall


引入依赖

<dependency>

   <groupId>org.springframework.boot</groupId>

   <artifactId>spring-boot-starter-amqp</artifactId>

</dependency>


RabbitMQ连接配置

spring:

 rabbitmq:

   host: x.youlai.tech

   port: 5672

   username: guest

   password: guest


RabbitMQ 监听同步缓存

/**

* Canal + RabbitMQ 监听数据库数据变化

*

* @author <a href="mailto:xianrui0365@163.com">haoxr</a>

* @date 2021/11/4 23:14

*/

@Component

@Slf4j

@RequiredArgsConstructor

public class CanalListener {

   private final ISysPermissionService permissionService;

   private final ISysOauthClientService oauthClientService;

   private final ISysMenuService menuService;

   @RabbitListener(bindings = {

           @QueueBinding(

                   value = @Queue(value = "canal.queue", durable = "true"),

                   exchange = @Exchange(value = "canal.exchange"),

                   key = "canal.routing.key"

           )

   })

   public void handleDataChange(String message) {

       CanalMessage canalMessage = JSONUtil.toBean(message, CanalMessage.class);

       String tableName = canalMessage.getTable();

       log.info("Canal 监听 {} 发生变化;明细:{}", tableName, message);

       if ("sys_oauth_client".equals(tableName)) {

           log.info("======== 清除客户端信息缓存 ========");

           oauthClientService.cleanCache();

       } else if (Arrays.asList("sys_permission", "sys_role", "sys_role_permission").contains(tableName)) {

           log.info("======== 刷新角色权限缓存 ========");

           permissionService.refreshPermRolesRules();

       } else if (Arrays.asList("sys_menu", "sys_role", "sys_role_menu").contains(tableName)) {

           log.info("======== 清理菜单路由缓存 ========");

           menuService.cleanCache();

       }

   }

}


6. 实战测试

🏷 如果使用有来项目线上 RabbitMQ 测试,记得需要新建队列,否者多人消费同一队列会让你觉得 Canal 监听数据有丢失的现象。


接下来模拟测试,当直接在数据库修改菜单数据,能否让 Redis 的菜单路由缓存失效。


启动 Canal

切换到项目的 cd ./middleware/canal/deployer/bin 目录下,输入 startup 启动 Canal


微信图片_20230710083249.png


启动 youlai-admin 应用,测试效果如下,可见最后菜单路由缓存在直接在数据库修改菜单表数据时会失效,达到预期效果。

微信图片_20230710083251.gif



四. 总结

本篇通过 Canal + RabbitMQ 实现对 MySQL 数据变动监听,能够应对实际工作直接修改数据库数据后让缓存失效或者刷新的场景。有来项目引入 Canal 本篇只是个开始,因为 Canal 的应用场景太丰富了,接下来有来项目使用 Canal 同步 MySQL 数据库的商品数据至 ElasticSearch 索引库,个人感觉以后会越来越火,所以建议有必要深入了解这个 Canal 框架。


五. 联系信息

有兴趣进交流群的童鞋欢迎加群, 纯属学习交流群,无任何利益,二维码过期可加我微信备注“有来”即可,我拉你进群,另外如果有兴趣加入开源项目 youlai-mall 开发的欢迎私信我。


相关文章
|
12月前
|
缓存 NoSQL 关系型数据库
MySQL 与 Redis 如何保证双写一致性?
我是小假 期待与你的下一次相遇 ~
1238 7
|
缓存 NoSQL 关系型数据库
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
|
关系型数据库 应用服务中间件 nginx
Docker一键安装中间件(RocketMq、Nginx、MySql、Minio、Jenkins、Redis)
本系列脚本提供RocketMQ、Nginx、MySQL、MinIO、Jenkins和Redis的Docker一键安装与配置方案,适用于快速部署微服务基础环境。
|
存储 NoSQL Redis
阿里云高性能数据库Tair(兼容 Redis)收费价格,稳定可靠成本低
阿里云高性能云数据库Tair兼容Redis,提供Redis开源版和Tair企业版,支持多种存储介质与灵活扩展,适用于高并发场景。Tair具备亚毫秒级稳定延迟,保障业务连续性。价格方面,Redis开源版年费从72元起,Tair企业版年费从1224元起,具体费用根据配置不同有所变化。
|
人工智能 运维 Java
SpringBoot+MySQL实现动态定时任务
这是一个基于Spring Boot的动态定时任务Demo,利用spring-context模块实现任务调度功能。服务启动时会扫描数据库中的任务表,将任务添加到调度器中,并通过固定频率运行的ScheduleUpdater任务动态更新任务状态和Cron表达式。核心功能包括任务的新增、删除与Cron调整,支持通过ScheduledFuture对象控制任务执行。项目依赖Spring Boot 2.2.10.RELEASE,使用MySQL存储任务信息,包含任务基类ITask及具体实现(如FooTask),便于用户扩展运维界面以增强灵活性。
520 10
|
消息中间件 Java Kafka
消息队列比较:Spring 微服务中的 Kafka 与 RabbitMQ
本文深入解析了 Kafka 和 RabbitMQ 两大主流消息队列在 Spring 微服务中的应用与对比。内容涵盖消息队列的基本原理、Kafka 与 RabbitMQ 的核心概念、各自优势及典型用例,并结合 Spring 生态的集成方式,帮助开发者根据实际需求选择合适的消息中间件,提升系统解耦、可扩展性与可靠性。
832 1
消息队列比较:Spring 微服务中的 Kafka 与 RabbitMQ
|
消息中间件 存储 Java
RabbitMQ 和 Spring Cloud Stream 实现异步通信
本文介绍了在微服务架构中,如何利用 RabbitMQ 作为消息代理,并结合 Spring Cloud Stream 实现高效的异步通信。内容涵盖异步通信的优势、RabbitMQ 的核心概念与特性、Spring Cloud Stream 的功能及其与 RabbitMQ 的集成方式。通过这种组合,开发者可以构建出具备高可用性、可扩展性和弹性的分布式系统,满足现代应用对快速响应和可靠消息传递的需求。
689 2
RabbitMQ 和 Spring Cloud Stream 实现异步通信
|
NoSQL 算法 Redis
【Docker】(3)学习Docker中 镜像与容器数据卷、映射关系!手把手带你安装 MySql主从同步 和 Redis三主三从集群!并且进行主从切换与扩容操作,还有分析 哈希分区 等知识点!
Union文件系统(UnionFS)是一种**分层、轻量级并且高性能的文件系统**,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem) Union 文件系统是 Docker 镜像的基础。 镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
1084 6
|
消息中间件 缓存 NoSQL
基于Spring Data Redis与RabbitMQ实现字符串缓存和计数功能(数据同步)
总的来说,借助Spring Data Redis和RabbitMQ,我们可以轻松实现字符串缓存和计数的功能。而关键的部分不过是一些"厨房的套路",一旦你掌握了这些套路,那么你就像厨师一样可以准备出一道道饕餮美食了。通过这种方式促进数据处理效率无疑将大大提高我们的生产力。
475 32
|
监控 Java 关系型数据库
Spring Boot整合MySQL主从集群同步延迟解决方案
本文针对电商系统在Spring Boot+MyBatis架构下的典型问题(如大促时订单状态延迟、库存超卖误判及用户信息更新延迟)提出解决方案。核心内容包括动态数据源路由(强制读主库)、大事务拆分优化以及延迟感知补偿机制,配合MySQL参数调优和监控集成,有效将主从延迟控制在1秒内。实际测试表明,在10万QPS场景下,订单查询延迟显著降低,超卖误判率下降98%。
647 5

推荐镜像

更多