Spring Boot整合Canal实战:从零到互联网级同步方案
一、Canal是啥?能干啥?
Canal,名字听着像"管道",其实就是阿里开源的一个工具,专门盯着MySQL的增量日志(binlog)干活。通俗点讲,它把自己伪装成MySQL的从库,实时把主库的binlog抓过来,拆解成数据变更的事件(比如新增、修改、删除),然后推给下游系统用。这玩意儿就像是数据库和业务之间的"实时快递员",能帮你干不少事,比如更新缓存、算统计数据、发通知啥的。
Canal咋实现的?
说白了,它靠的是MySQL的binlog。要让Canal跑起来,MySQL得满足两个条件:
- binlog得开着,格式还得是
ROW
(记录最全的那种)。 - 得给Canal整一个专用账号,权限得有
REPLICATION SLAVE
和REPLICATION CLIENT
。
Linux上咋配MySQL?
直接上命令,别记错:
bash
# 编辑my.cnf
[mysqld]
log-bin=mysql-bin # 开binlog
binlog-format=ROW # 必须是ROW,别写错
server-id=1 # 随便填个独一无二的ID,别撞车就行
# 建个Canal用户
mysql> CREATE USER 'canal'@'%' IDENTIFIED BY 'canal';
mysql> GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%';
mysql> FLUSH PRIVILEGES;
二、Canal的两个主力:Deployer和Adapter
-
Deployer(服务端)
• 干啥的?连上MySQL,掏出binlog,解析完再丢给客户端。
• 配置在哪?
canal.properties
管全局,instance.properties
管具体实例(比如MySQL地址、账号)。 -
Adapter(适配器)
• 干啥的?把Deployer扔来的数据收拾收拾,变成业务能用的格式,比如塞进Kafka、更新Elasticsearch。
• 亮点?支持插拔式,想咋整就咋整。
三、Spring Boot咋接Canal?
第一步:加依赖
现在社区里挺火的Canal客户端是canal-spring-boot-starter
,直接用这个:
xml
<dependency>
<groupId>top.javatool</groupId>
<artifactId>canal-spring-boot-starter</artifactId>
<version>1.1.6</version>
</dependency>
第二步:配application.yml
简单点写,够用就行:
yaml
canal:
server: 192.168.1.100:11111 # Canal Deployer的地址
destination: example # 实例名,跟Deployer那边对上
filter: .*\\..* # 先监听所有表,后面再改细点
batch-size: 1000 # 一次拉多少条
retry: 3 # 拉失败再试几次
第三步:上代码
• 核心活儿:写个类实现EntryHandler<T>
,监听表的增删改。
• 注解:@CanalTable("user")
指定监听哪张表。
java
@CanalTable("user")
@Component
public class UserCanalHandler implements EntryHandler<User> {
// 新增
@Override
public void insert(User user) {
log.info("新增了个用户: {}", user);
// 比如更新缓存,或者发条消息
}
// 更新
@Override
public void update(User before, User after) {
log.info("用户数据变了: 之前={}, 现在={}", before, after);
}
// 删除
@Override
public void delete(User user) {
log.info("删了个用户: {}", user);
}
}
配置类咋弄?
• 加个@EnableCanalClient
开客户端。
• 想高级点,可以自己写个CanalConfig
,调调超时、线程啥的,看业务需要。
四、电商场景实战:订单状态同步
场景:用户下单后,订单状态从"待付款"变成"已支付",再到"已发货",得实时同步到:
- 前端页面进度条
- 库存系统解锁库存
- 风控盯着有没有猫腻
咋测?
- 本地起个Canal Deployer,连上测试库。
- Spring Boot盯着
order
表。 - 手动改数据库订单状态,看日志有没有动静。
- 再整条MQ消息打到控制台,假装通知下游。
五、从简单到牛逼:优化思路
简单方案的毛病 :
• 监听太粗 :filter: .*\\..*
啥都听,机器扛不住。
• 同步卡壳 :直接在insert/update
里干活,Canal消费慢得像乌龟。
• 挂了咋办:网络一抖,数据丢了咋整?
咋优化?
- 听重点 :改成只听关键表(比如
filter: db1.order,db2.inventory
)。 - 异步搞定:变更丢到MQ(比如Kafka),下游慢慢吃。
- 高可用 :
• Canal Server搞集群,Zookeeper管着谁干活。
• 客户端记个消费位点(Redis存binlog offset),别丢数据。
跟大厂学 :
• 数据管道 :Canal → Kafka → 业务服务,解耦还抗压。
• 分布式适配:Adapter也搞集群,负载均衡跑起来。
六、还能咋玩?
• 搭Elasticsearch :数据一变,搜索索引跟着动。
• 追数据血缘 :binlog还能看出字段咋变的。
• 灰度开关:监听配置表,动态切功能。