当前位置: 代码迷 >> 综合 >> 如何实现数据库DB与其他中间件(redis/elastic search/mongoDB)的双写一致性?
  详细解决方案

如何实现数据库DB与其他中间件(redis/elastic search/mongoDB)的双写一致性?

热度:33   发布时间:2023-12-15 06:44:24.0

前言

在工作中,总会存在多个组件配合使用,而多个组件一起使用必然会出现双写(同时写入数据到两个组件)的情况,而这两个写入操作单独各自是原子性的,但对于整个事务的话,控制两者一致就值得说道说道了;

以redis为例

以redis为例,如何实现redis和数据库mysql的数据一致性呢?

1. 先删除缓存再插入到DB (低并发也许可以)

在这里插入图片描述
这种情况表面似乎没什么问题,但一旦并发高了,其他线程将脏数据写入缓存,就会出现不一致的情况;

2. 延时双删

public void doubleWrite(String key,Object data){
    redis.delKey(key);db.updateData(data);Thread.sleep(300);redis.delKey(key);
}

这么做是为了确保读请求结束,写请求可以删除读请求造成的缓存脏数据。当然这种策略还要考虑redis和数据库主从同步的耗时,这个时间不是特别好确定

这里的延时可以采用rabbitmq的延时队列实现

该方案的弊端

最差的情况就是在超时时间内数据存在不一致,而且又增加了写请求的耗时。

3. 基于订阅binlog的同步机制

在这里插入图片描述
众所周知,mysql有基于binlog的主从复制来同步数据库数据,根据这个原理,阿里设计并开源了一款叫作canal的中间件;

##canal

可查看我另一篇文章 具体介绍了 canal安装和使用

canal实际是模仿mysql slave节点向master节点发送一个同步指令,此时master节点会把所有非查询的操作(ddl,dml)以二进制形式存储为binlog文件,slave拿到binlog之后解析,根据master的各种操作,或者说是事件,可以配合消息中间件mq(rabbitmq,kafka之类)通知其他组件,其他组件消费后进行同步写入;

mysql的主从复制原理如下:
在这里插入图片描述

MySQL master 将数据变更写入二进制日志( binary log, 其中记录叫做二进制日志事件binary log events,可以通过 show binlog events 进行查看)
MySQL slave 将 master 的 binary log events 拷贝到它的中继日志(relay log)
MySQL slave 重放 relay log 中事件,将数据变更反映它自己的数据

canal 工作原理:

canal 模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,向 MySQL master 发送dump 协议
MySQL master 收到 dump 请求,开始推送 binary log 给 slave (即 canal ) canal 解析
binary log 对象(原始为 byte 流)

总结

canal + mq 通过最终一致性来解决异构系统的同步,而且这种解决方案已经被很多企业采用;
可能又有人会想,只有mysql才有binlog,那要是是oracle数据库呢???
针对这个问题,有一款叫作databus的产品可以解决;

在此,只大致介绍了一下双写一致性的解决方案,后续会详细介绍一下canal的安装和操作~~

最后,如果看完对你有所帮助,不要吝啬关注 / 点赞 / 收藏哟,感谢感谢~

  相关解决方案