解决Redis数据存储不一致

什么是数据不一致,为什么会出现这种情况


  数据不一致是指缓存中的数据和数据库中的数据不一致导致的,这种情况的发生多是因为多线程造成的。因为正常操作是对于请求先查询缓存,如果缓存未命中再次查询数据库,如果数据库也没有这种情况可以说是缓存击穿,如果数据库有数据那么把数据缓存到redis中并把数据返回给请求者。但是假设我们更新完数据库,缓存并不知道数据更新了,假设有人访问,那么命中的就是redis中的旧数据。那么如何解决呢?一些常见的ttl,或者等待redis内存到达一定程度自己更新这种方式时效性不行。

目前主要的解决方案是靠我们自己编写程序去应对,就是说在更新数据库的时候我们去手动的更新redis。那么就有如下问题:

缓存是采用更改方式还是删除方式?是先更新数据库,再操作redis还是先对redis进行操作再进行数据库更新?

第一个问题


先说第一个问题,删除的操作底层没有更改那么复杂,而且如果多次修改数据库但是读取的次数很少的话那么每次更新redis就有点多余了,综上选择删除缓存比较好。

第二个问题


  由于这两个数据库的操作在多线程下不可能为了一致性采取上锁的方式那样的话会影响数据的吞吐量,常常会采用一种称为"最终一致性"的方法

(1)先操作缓存



假设线程1先删除缓存,由于网络原因导致未及时更新数据库,这时线程2先去redis查询数据,未命中,再去查询数据库的数据(此时线程1还未及时对数据库进行数据更新),这是查询到的数据是旧数据,并把旧数据放到缓存。然后等线程1更新完数据库后就造成了数据不一致。怎么解决呢,就只能说是尽可能减少这种情况的发生,那就是再更新完毕数据库后再次进行缓存的延迟删除,就是延迟双删。为什么要延迟删除呢?是因为假设线程2读取到数据后但是还没来得及更新缓存,这个时刻线程1完成了对数据库的更新并删除redis,如果不延迟的话,那么线程1更新redis后线程2有一次把旧的数据进行了覆盖这样就没解决数据不一致性。只能是延迟等线程2更新完后再由线程1进行删除。这样不可避免的线程2读取到了错误数据,但是避免了以后的线程读取到错误的数据。至于延迟的选择时长要根据程序而定。
 

(2)先操作数据库

线程1先更新数据库,还没来得及更新redis,此时线程2读取redis的数据并命中这时就会导致线程2读取到脏数据,然后线程1再完成redis的更新。但是这种方式也实现了最终一致性,而且流程简单。

极端情况

  假设数据库删除缓存删除失败怎么办

这时可以采用失败重试机制,如果解决不掉可以把错误写入到日志中由人工进行操作,比如采用MQ消息队列实现,如果删除失败就发送对应信息给MQ,由线程1进行监听并重新尝试删除。

但是这样的缺点是代码业务复杂,高耦合。

解决耦合方案 Canal读取binlog文件异步删除

阿里巴巴开源的 Canal 框架是一个用于 MySQL 数据库的开源数据同步工具。它可以捕获 MySQL 数据库中的数据变更,然后将这些变更传递给其他目标,通常是用于数据仓库、搜索引擎同步、缓存更新等数据同步场景。Canal 主要用于实时数据同步和数据变更监控,特别适用于大规模数据流处理。

Canal 的主要功能和特点包括:
实时数据捕获:Canal 可以实时捕获 MySQL 数据库中的数据变更,包括插入、更新和删除操作。

数据格式支持:它支持将数据变更以不同的格式输出,如 JSON、Avro 等,以便与不同的目标系统集成。

多种订阅方式:Canal 支持按照数据库、表或者特定的数据变更条件进行订阅,可以根据需要选择性地捕获数据变更。

高性能:Canal 采用了高性能的数据抓取和传输技术,可以处理大规模的数据变更。

数据过滤和变换:您可以配置 Canal 来过滤和变换捕获到的数据,以适应目标系统的需求。

数据安全性:Canal 支持数据的加密和认证,确保数据传输的安全性。

无论是先执行什么操作,只要更新数据库,通过binlog,canal检测到,就执行redis更新,如果更新失败,就发消息给MQ,由Canal的客户端再继续重新删除。这样就解决了代码的耦合。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值