Redis和MySQL如何保持数据一致性

其实无论是先删除缓存还是后删除缓存都会造成数据不一致的情况。

1.原因

先删的情况

1.如果先删除Redis缓存数据,然而还没来得及写入MySQL,另一个线程来读取。

2.这个时候发现缓存为空,则去数据库中读取旧数据写入Redis,此时缓存为脏数据。

3.然后数据库更新后,发现Redis数据和MYSQL数据库数据不一致。

后删的情况:

1.如果先写了库,然后在读取缓存,但是如果写库的线程挂掉,导致了缓存没有删除。

2.这个时候就会读取旧缓存数据,最终也导致了数据不一致的情况。

2.解决办法

2.1缓存双删策略:

  1. 先删除缓存
  2. 再写入数据库
  3. 休眠xxx秒(休眠时间由业务情况而定)
  4. 再次删除缓存

2.1.1缺点

结合双删策略+缓存超时设置,这样最差的情况就是:

1、在缓存过期时间内发生数据存在不一致 2、同时又增加了写请求的耗时。

2.1.2问题

为什么要双删呢?

因为第一次删除是还没更新的数据,第二次删除是因为读取的并发性导致的缓存重新写入数据出现的垃圾数据、脏数据。

2.2删除缓存重试机制

缓存删除失败怎么办?比如延迟双删的第二次删除失败,说明脏数据无法删除。 使用重试机制保证缓存删除成功。 比如重试3次,失败3次,就会将日志记录到数据库中,并发出警告进行人工干预。 在高并发场景下,重试最好采用异步方式,比如向MQ中间件发送消息,实现异步解耦。

2.3读取 bin-log 异步删除

    更新数据库。 数据库会将操作信息记录在bin-log日志中。 使用 canal 订阅 bin-log 日志获取目标数据和密钥。 缓存删除系统获取canal数据,解析目标key,尝试删除缓存。 如果删除失败,将消息发送到消息队列。 缓存删除系统再次从消息队列中获取数据,再次执行删除操作。
经验分享 程序员 微信小程序 职场和发展