最近不是正好在研究 canal 嘛,刚巧前两天看了一篇关于解决缓存与数据库一致性问题的文章,里边提到了一种解决方案是结合 canal 来操作的,所以就想趁热打铁,手动来实现一下。
架构
文中提到的思想是:
采用先更新数据库,后删除缓存的方式来解决并发引发的一致性问题;
采用异步重试的方式来保证“更新数据库、删除缓存”这两步都能执行成功;
可以采用订阅变更日志的方式来清除 Redis 中的缓存;
基于这种思想,阿Q脑海中搭建了以下架构
-
APP 从 Redis 中查询信息,将数据的更新写入 MySQL 数据库中;
-
Canal 向 MySQL 发送 dump 协议,接收 binlog 推送的数据;
-
Canal 将接收到的数据投递给 MQ 消息队列;
-
MQ 消息队列消费消息,同时删除 Redis 中对应数据的缓存;
环境准备
考虑到我们服务器之前安装过 RabbitMQ ,所以我们就用 RabbitMQ 来充当消息队列吧。
Canal 配置
修改 conf/canal.properties
配置
# 指定模式
canal.serverMode = rabbitMQ
# 指定实例,多个实例使用逗号分隔: canal.destinations = example1,example2
canal.destinations = example
# rabbitmq 服务端 ip
rabbitmq.host = 127.0.0.1
# rabbitmq 虚拟主机
rabbitmq.virtual.host = /
# rabbitmq 交换机
rabbitmq.exchange = xxx
# rabbitmq 用户名
rabbitmq.username = xxx
# rabbitmq 密码
rabbitmq.password = xxx
rabbitmq.deliveryMode =
修改实例配置文件 conf/example/instance.properties
#配置 slaveId,自定义,不等于 mysql 的 server Id 即可
canal.instance.mysql.slaveId=10
# 数据库地址:配置自己的ip和端口
canal.instance.master.address=ip:port
# 数据库用户名和密码
canal.instance.dbUsername=xxx
canal.instance.dbPassword=xxx
# 指定库和表
canal.instance.filter.regex=.*\\..* // 这里的 .* 表示 canal.instance.master.address 下面的所有数据库
# mq config
# rabbitmq 的 routing key
canal.mq.topic=xxx
然后重启 canal 服务。
这篇文章