- 一、缓存同步策略
- 1、基于MQ的异步通知
- 2、基于Canal的异步通知
- 二、Cannal
- 1、介绍
- 2、mysql的主从同步原理
- 3、Canal同步原理
- 三、实战
- 1、配置binlog主从同步
- 2、创建docker网络mynet
- 3、docker安装canal
- 拉去镜像
- 创建容器
- 查看运行日志
- 查看是否跟mysql连接成功
- 4、监听Canal
- 引入依赖
- 编写配置
- 监听表的binlog消息,更新redis
- 总结
- 五、代码
缓存数据同步的常见三种方式:
-
设置有效期:给缓存设置有效期,到期后自动删除。再次查询时更新
- 优势:简单,方便
- 缺点:时效性差,缓存过期之前可能不一致
- 场景:更新频率交底,时效性要求低的业务
-
同步双写:在修改数据库的同时,直接修改缓存
- 优势:时效性强,缓存与数据库强一致
- 缺点:有代码侵入,耦合度高
- 场景:对一致性,时效性要求较高的缓存数据
-
设置有效期:修改数据库时发送事件通知,相关服务监听到通知后修改缓存数据
- 优势:低耦合,可能同时通知多个缓存服务
- 缺点:时效性一般,可能存在中间不一致状态
- 场景:时效性要求一般,有多个服务需要同步
canal,译意为水道/管道/沟渠,是阿里巴巴旗下的一款开源项目,基于JAVA开发。主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费。
以下参考canal官网:https://github.com/alibaba/canal。
但是canal的数据同步不是全量的,而是增量。基于binary log增量订阅和消费,canal可以做:
- 数据库镜像
- 数据库实时备份
- 索引构建和实时维护
- 业务cache(缓存)刷新
- 带业务逻辑的增量数据处理
canel是基于mysql的主从同步来实现的,MySql主从同步的原理如下:
Canal就是把自己伪装成Mysql的一个slave节点,从而监听master的binary log变化。再把得到的变化信息通知给Canal的客户端,进而完成对其他数据库的同步。
参考:Mysql入门及高级用法
2、创建docker网络mynetdocker network create mynet # 让mysql加入mynet docker network connect mynet mysql3、docker安装canal 拉去镜像
docker pull canal/canal-server:v1.1.5创建容器
docker run -p 11111:11111 --name canal -e canal.destinations=heima -e canal.instance.master.address=mysql:3306 -e canal.instance.dbUsername=canal -e canal.instance.dbPassword=canal -e canal.instance.connectionCharset=UTF-8 -e canal.instance.tsdb.enable=true -e canal.instance.gtidon=false -e canal.instance.filter.regex=heima\..* --network mynet -d canal/canal-server:v1.1.5
-e canal.destinations=heima canal集群的名字
-e canal.instance.master.address mysql信息
-e canal.instance.filter.regex=heima…* 表示监听heima这个数据库下的所有表
查看运行日志表名称监听器支持的语法
filter.regexmysql 数据解析关注的表,Perl正则表达式.
多个正则之间以逗号(,)分隔,转义符需要双斜杠()
常见例子:
- 所有表:.* or .…
- canal schema下所有表: canal…*
- canal下的以canal打头的表:canal.canal.*
- canal schema下的一张表:canal.test1
- 多个规则组合使用然后以逗号隔开:canal…*,mysql.test1,mysql.test2
docker logs -f canal查看是否跟mysql连接成功
先进入容器
root@sony-HP-Notebook:/usr/local/mysql/conf# docker exec -it canal bash [root@8296a3ed2f83 admin]# ls app.sh bin canal-server health.sh node_exporter node_exporter-0.18.1.linux-arm64
查看cannel的运行日志
[root@8296a3ed2f83 admin]# tail -f canal-server/logs/canal/canal.log 2022-06-09 18:42:37.617 [main] INFO com.alibaba.otter.canal.deployer.CanalLauncher - ## set default uncaught exception handler 2022-06-09 18:42:37.684 [main] INFO com.alibaba.otter.canal.deployer.CanalLauncher - ## load canal configurations 2022-06-09 18:42:37.706 [main] INFO com.alibaba.otter.canal.deployer.CanalStarter - ## start the canal server. 2022-06-09 18:42:37.785 [main] INFO com.alibaba.otter.canal.deployer.CanalController - ## start the canal server[172.22.0.6(172.22.0.6):11111] 2022-06-09 18:42:40.519 [main] INFO com.alibaba.otter.canal.deployer.CanalStarter - ## the canal server is running now ......
查看heima库的连接日志
tail -f canal-server/logs/heima/heima.log4、监听Canal
Canal提供了各种语言的客户端,当Canal监听到binlog变化时,会通知Canal的客户端
第三方开源的canal-starter,地址:https://github.com/NormanGyllenhaal/canal-client
编写配置top.javatool canal-spring-boot-starter 1.2.1-RELEASE
destination要对应之前docker启动时候集群的名字
canal: destination: heima server: 127.0.0.1:11111监听表的binlog消息,更新redis
@CanalTable("tb_item")
@Component
public class ItemHandler implements EntryHandler- {
@Autowired
private RedisHandler redisHandler;
@Autowired
private Cache
itemCache;
@Override
public void insert(Item item) {
// 写数据到JVM进程缓存
itemCache.put(item.getId(), item);
// 写数据到redis
redisHandler.saveItem(item);
}
@Override
public void update(Item before, Item after) {
// 写数据到JVM进程缓存
itemCache.put(after.getId(), after);
// 写数据到redis
redisHandler.saveItem(after);
}
@Override
public void delete(Item item) {
// 删除数据到JVM进程缓存
itemCache.invalidate(item.getId());
// 删除数据到redis
redisHandler.deleteItemById(item.getId());
}
}
总结
五、代码
仓库:https://gitee.com/edevp/item-service



