实现缓存和数据库一致性方案:mysql+canal+rabbitmq+redis

本文介绍了如何利用MySQL的Canal,结合RabbitMQ和Redis实现数据更新时的缓存一致性。文章详细阐述了架构设计、环境准备、Canal配置、RabbitMQ配置以及实战过程中遇到的问题与解决方法,强调了手动ACK在确保消息可靠传递中的作用。

最近不是正好在研究 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 服务。

这篇文章中有 RabbitMQ 的安装教程:

### 确保 MySQL Redis 缓存一致性策略及方案 #### 一、基于 Binlog 的监听机制 为了维持 MySQL Redis 之间的数据同步,在高并发环境中可以采用监听 MySQL 的二进制日志 (Binlog),并通过异步方式将变更应用到 Redis 中[^2]。这种方式能够有效减少数据库的压力,同时确保缓存中的数据尽可能接近最新状态。 ```php // 假设有一个函数用于处理来自 binlog 的事件并更新 redis function handle_binlog_event($event_data){ $redis_key = "user:" . $event_data['id']; switch ($event_data['type']){ case 'insert': // 插入新记录至 Redis set_redis_value($redis_key, $event_data); break; case 'update': // 更新现有记录于 Redis update_redis_value($redis_key, $event_data); break; case 'delete': // 删除对应键值对自 Redis delete_from_redis($redis_key); break; default: throw new Exception('Unknown event type'); } } ``` #### 二、消息队列配合 Canal 或者 MQ+Canal 组合模式 当面临更高的可靠性需求以及更严格的实时性约束时,可以选择引入消息中间件如 RabbitMQ 或 Kafka 来传输由 Canal 捕获的变化信息给负责维护缓存的服务端程序[^3]。此方法不仅提高了系统的解耦程度,还允许开发者更容易实现错误重试逻辑服务限流等功能。 然而值得注意的是,无论采取哪种技术手段来保障两者间的一致性,都需要充分考虑到可能出现的各种异常状况及其应对措施,比如网络分区期间的消息丢失或是延迟等问题所带来的影响。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值