Mysql数据库,Redis 缓存一致性

1.先更新数据库,再更新缓存

2.先删除缓存,再更新数据库

3.延迟双扇

4cannal ---异步

 

使用过缓存的人都应该知道,在实际应用场景中,要想实时刻保证缓存和数据库中的数据一样,很难做到。

基本上都是尽可能让他们的数据在绝大部分时间内保持一致,并保证最终是一致的。

 

1、为什么用redis?

redis是用来实现应用与数据库之间读操作的缓存层,目的是减少数据库的IO,还可以提升数据的IO性能

2、为什么会出现数据一致性问题?

同一份数据同时保存在redis和MySQL,那么数据发生变化的时候就需要同时更新这两个存储,但是更新会有前后且不具有原子性,就会出现数据一致性问题

 

3. 不推荐先更新缓存,在更新数据库

更新缓存成功,更新数据库失败,数据库回滚,还得回滚缓存,而且缓存不是简单的数据,还可能经过复杂的计算结果缓存到redis中。数据库回滚,前面的计算白算啦。此外持久化方面,数据库的持久化做的比缓存好些,而且存储以数据库为中心,先更新数据库,在怎样怎样…

如果更新reids成功,更新数据库失败,那么同样会造成数据不一致

4.不推荐先更新数据库,在更新缓存

这种方案,应该没人采用。

如果先更新数据库成功,接着更新redis失败,那么会造成数据不一致,所以这种方法舍弃

 

 两个操作的原子性被打破了:也就是第一步成功,第二步失败,会发生什么?

5.不推荐先删除缓存,在更新数据库(这种方法在并发下最容易出现长时间的脏数据,不可取)

 

这种方案,同样存在一定几率的不一致现象,但是已经接近最优了。

如果线程A删除了redis,正准备更新数据库。线程B查询了redis没有之后,查询了数据库的旧数据,并且把它写到redis。之后线程A才更新数据成功,会出现数据库和redis的数据不一致

解决方案:延迟双删

线程A在删除redis以及更新数据库后,睡眠一段时间后,再次删除reids中的数据。这个睡眠时间得大于一次查询的时间。

 

 

6.先更新数据库,再删除redis

这种方案,同样会造成数据不一致的问题,但是相比上两个方案,如果他设置key的过期时间,那么保证了数据的最终一致性。如果在更新数据库后删除redis失败,又未设置redis过期时间。那么会造成数据不一致。

如果线程A更新数据库,正准备更新redis时。线程B在更新线程A更新redis前获取了redis中的数据,那么其他数据拿到的数据还是旧数据,如果删除redis失败也会造成数据不一致

解决方案:
1.mysql和redis设置事务,在发生异常时回滚数据
2.redis设置重试机制,在删除失败后进入重试模式


一致性解决方案(读写过程

1.缓存延迟双删 (Cache delay double deletion)

  • 先删除缓存

  • 写数据库

  • 休眠 500 毫秒,然后删除缓存

这样,读取脏数据的时间最多只有500毫秒。关键是如何确定睡眠时间? 延迟时间的目的是为了保证读请求结束,写请求可以删除读请求引起的缓存脏数据。 因此,我们需要自己评估项目的数据读取业务逻辑的耗时,在读取时间的基础上加上几百毫秒的延迟时间。

2. 读取 bin-log 异步删除

  • 更新数据库。

  • 数据库会将操作信息记录在bin-log日志中。

  • 使用 canal 订阅 bin-log 日志获取目标数据和密钥。

  • 缓存删除系统获取canal数据,解析目标key,尝试删除缓存。

  • 如果删除失败,将消息发送到消息队列。

  • 缓存删除系统再次从消息队列中获取数据,再次执行删除操作。

 

保证了数据的最终一致性,但是不保证短时间内数据一致

 

 

参考:

Mysql和Redis如何保证数据一致性

 redis和mysql缓存一致性
如何保持MySQL和redis中数据的一致性?

Redis 与 Mysql 的数据一致性

Mysql和Redis数据如何保持一致

【面试】【3】redis和MySQL如何保证数据的一致性

 

posted @   BBS_自律  阅读(101)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 上周热点回顾(2.17-2.23)
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· spring官宣接入deepseek,真的太香了~
点击右上角即可分享
微信分享提示