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

本文涉及的产品
RDS AI 助手,专业版
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
RDS Agent(兼容OpenClaw),2核4GB
简介: 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 开发的欢迎私信我。


相关文章
|
安全 关系型数据库 MySQL
如何将数据从MySQL同步到其他系统
【10月更文挑战第17天】如何将数据从MySQL同步到其他系统
2111 0
|
8月前
|
缓存 并行计算 监控
vLLM 性能优化实战:批处理、量化与缓存配置方案
本文深入解析vLLM高性能部署实践,揭秘如何通过continuous batching、PagedAttention与前缀缓存提升吞吐;详解批处理、量化、并发参数调优,助力实现高TPS与低延迟平衡,真正发挥vLLM生产级潜力。
2152 0
vLLM 性能优化实战:批处理、量化与缓存配置方案
|
9月前
|
存储 缓存 NoSQL
Redis专题-实战篇二-商户查询缓存
本文介绍了缓存的基本概念、应用场景及实现方式,涵盖Redis缓存设计、缓存更新策略、缓存穿透问题及其解决方案。重点讲解了缓存空对象与布隆过滤器的使用,并通过代码示例演示了商铺查询的缓存优化实践。
376 1
Redis专题-实战篇二-商户查询缓存
|
8月前
|
NoSQL 算法 Redis
【Docker】(3)学习Docker中 镜像与容器数据卷、映射关系!手把手带你安装 MySql主从同步 和 Redis三主三从集群!并且进行主从切换与扩容操作,还有分析 哈希分区 等知识点!
Union文件系统(UnionFS)是一种**分层、轻量级并且高性能的文件系统**,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem) Union 文件系统是 Docker 镜像的基础。 镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
877 6
|
关系型数据库 MySQL Shell
MySQL 备份 Shell 脚本:支持远程同步与阿里云 OSS 备份
一款自动化 MySQL 备份 Shell 脚本,支持本地存储、远程服务器同步(SSH+rsync)、阿里云 OSS 备份,并自动清理过期备份。适用于数据库管理员和开发者,帮助确保数据安全。
|
11月前
|
存储 缓存 安全
Go语言实战案例-LRU缓存机制模拟
本文介绍了使用Go语言实现LRU缓存机制的方法。LRU(最近最少使用)是一种常见缓存淘汰策略,当缓存满时,优先删除最近最少使用的数据。实现中使用哈希表和双向链表结合的方式,确保Get和Put操作均在O(1)时间内完成。适用于Web缓存、数据库查询优化等场景。
|
存储 缓存 Java
Java中的分布式缓存与Memcached集成实战
通过在Java项目中集成Memcached,可以显著提升系统的性能和响应速度。合理的缓存策略、分布式架构设计和异常处理机制是实现高效缓存的关键。希望本文提供的实战示例和优化建议能够帮助开发者更好地应用Memcached,实现高性能的分布式缓存解决方案。
307 9
|
监控 关系型数据库 MySQL
Flink CDC MySQL同步MySQL错误记录
在使用Flink CDC同步MySQL数据时,常见的错误包括连接错误、权限错误、表结构变化、数据类型不匹配、主键冲突和
665 17
|
缓存 NoSQL 关系型数据库
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
|
8月前
|
缓存 负载均衡 监控
135_负载均衡:Redis缓存 - 提高缓存命中率的配置与最佳实践
在现代大型语言模型(LLM)部署架构中,缓存系统扮演着至关重要的角色。随着LLM应用规模的不断扩大和用户需求的持续增长,如何构建高效、可靠的缓存架构成为系统性能优化的核心挑战。Redis作为业界领先的内存数据库,因其高性能、丰富的数据结构和灵活的配置选项,已成为LLM部署中首选的缓存解决方案。
848 25

推荐镜像

更多