canal可实现毫秒级mysql到redis缓存同步,无需业务层改动:需配置mysql开启row格式binlog、创建专用账号授权、启动canal server并配置实例、spring boot客户端通过@canaltable监听表变更写入redis。

直接用 Canal 监听 MySQL Binlog,解析后写入 Redis,不走业务层、不改原有代码,就能实现毫秒级缓存同步。
MySQL 必须提前配好 Binlog
Canal 依赖 MySQL 的增量日志,没开启或配置不对,它根本连不上:
- 编辑 my.cnf(或 my.ini),确保包含以下几项:
[mysqld]
log-bin=mysql-bin
binlog-format=ROW
binlog-row-image=FULL
server-id=1
- log-bin:必须启用,Canal 才能读取日志
- binlog-format=ROW:不能是 STATEMENT 或 MIXED,否则拿不到字段级变更
- binlog-row-image=FULL:保证 INSERT/UPDATE/DELETE 都能拿到完整前后镜像
- server-id:唯一值,避免和其它从库冲突
配完重启 MySQL,并执行 SHOW VARIABLES LIKE 'log_bin'; 和 SHOW VARIABLES LIKE 'binlog_format'; 确认生效。
创建专用账号并授权
Canal 连接 MySQL 不要用 root,按最小权限原则建账号:
- 登录 MySQL,执行:
CREATE USER 'canal'@'%' IDENTIFIED BY 'Canal@123';
GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%';
FLUSH PRIVILEGES;
- SELECT:读取表结构元数据
- REPLICATION SLAVE:允许拉取 Binlog(核心权限)
- REPLICATION CLIENT:查看主从状态(用于健康检查)
Canal Server 启动与实例配置
下载 Canal(推荐 1.1.7+),解压后重点改两个文件:
- 修改 conf/canal.properties 中的监听端口、zk 地址(如不用 zk 可忽略)
- 进入 conf/example/instance.properties,填入数据库连接信息:
canal.instance.master.address=192.168.1.100:3306
canal.instance.dbUsername=canal
canal.instance.dbPassword=Canal@123
canal.instance.defaultDatabaseName=test_db
canal.instance.connectionCharset=UTF-8
- 如果只同步某几张表,加一行:canal.instance.filter.regex=test_db\.(user|order)
- 启动:sh bin/startup.sh,查 logs/canal/canal.log 看是否 “start successful”
Spring Boot 客户端消费变更写 Redis
引入 starter,写监听器,自动处理增删改:
- Maven 加依赖:
- application.yml 配置 Canal 地址:
canal:
destination: example
server: 127.0.0.1:11111
- 写一个监听器类,标注表名,覆盖 insert/update/delete 方法:
@CanalTable("user")
@Component
public class UserHandler implements EntryHandler
@Resource private StringRedisTemplate redis;
@Override public void insert(User user) {
redis.opsForValue().set("user:" + user.getId(), JSON.toJSONString(user));
}
@Override public void update(User before, User after) {
redis.opsForValue().set("user:" + after.getId(), JSON.toJSONString(after));
}
@Override public void delete(User user) {
redis.delete("user:" + user.getId());
}
}
注意:EntryHandler 泛型类型需和数据库实体一致,字段名要严格匹配;update 方法里 before/after 是 Canal 自动映射出来的对象。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











