当前位置:网站首页>如何保证缓存和数据库的双写一致性?
如何保证缓存和数据库的双写一致性?
2022-07-26 07:20:00 【李小恩恩子】
目前大部分高并发系统都是使用redis+mysql数据库来保证高性能,那么更新缓存和更新数据库的流程到底是怎么实现的呢?
目录
类别
实现缓存与数据库的双写一致性大致有四个类别,分别是:
①先更新缓存,再更新数据库
②先更新数据库,再更新缓存
③先删除缓存,再更新数据库
④先更新数据库,再删除缓存
分析
需要考虑两个问题:①更新缓存与删除缓存哪个更合适?②应该先操作数据库还是先操作缓存?
- 更新缓存和删除缓存哪一个更合适?
更新缓存的优点:每一次的数据变化都更新到缓存里面,所以查询命中率较高。
更新缓存的缺点:更新缓存的消耗比较大。频繁的更新缓存,就会影响数据库性能,如果是写频繁的业务场景,那么可能是频繁的更新缓存但是不怎么读取缓存,那更新缓存并没有什么实际意义。
删除缓存的优点:操作简单,直接将缓存的数据删除即可。
删除缓存的缺点:删除缓存,下一次查询会出现未命中的情况,需要从数据库读入到缓存。
综上,删除缓存会更优。
- 应该先操作数据库还是先操作缓存?
首先对比一下先删除缓存和先删除数据库的失败的情况:
①先删除缓存,再更新数据库

- 进程A删除缓存 - 成功
- 进程A更新数据库 - 失败
- 进程B查询缓存,发现没有,要去查询数据库
- 进程B查询数据库 - 成功
- 进程B更新缓存 - 成功
可以看出,最终缓存和数据库的数据是一致的,但是数据是原来的数据,不是新的。
②先更新数据库,再删除缓存

- 进程A更新数据库 - 成功
- 进程A删除数据库 - 失败
- 进程B查询缓存 - 成功 由于删除缓存失败,得到的数据是旧的数据
可以看出,最终的数据库和缓存数据是不一致的。
因为它们失败的时候都存在着问题,不知道哪一个会更好,但是出现第二步失败的情况下,我们都会进行重试机制解决操作失败的问题。重试机制一般会将操作加入消息队列,然后进行异步更新。
采取重试机制后,然后我们再来对比一下它们没有出现失败的情况下可能出现的问题:
①先删除缓存,再更新数据库

- 进程A删除缓存 - 成功
- 进程B查询缓存,发现没有,要去数据库查询
- 进程B查询数据库 - 成功,得到旧的数据
- 进程B更新缓存 - 成功,将旧的数据更新到缓存里面
- 进程A更新数据库 - 成功,将新的数据更新到数据库里面
我们发现,由于两个进程之间并发操作,进程A的两步操作均成功,在这两步之间,进程B访问了缓存。最终结果是,缓存中存储了旧的数据,而数据库中存储了新的数据,二者数据不一致。
②先更新数据库,再删除缓存

- 进程A更新数据库 - 成功
- 进程B查询缓存 - 成功,但是读到的是旧数据
- 进程A删除缓存 - 成功
可见,最终缓存与数据库的数据是一致的,并且都是最新的数据。但进程B在这个过程里读到了旧的数据,可能还有其他进程也像进程B一样,在这两步之间读到了缓存中旧的数据,但因为这两步的执行速度会比较快,所以影响不是很大。对于这两步之后,其他进程再读取缓存数据的时候,就不会出现类似于进程B的问题了。
总结
先更新数据库、再删除缓存是影响更小的方案。如果第二步出现失败的情况,则可以采用重试机制来解决问题。
拓展-延时双删
由于刚刚上面说的情况,先删除缓存,再更新数据库没有出现错误的情况下,也可能出现数据不一致的情况,采用延时双删解决:
- 删除缓存
- 更新数据库
- sleep n 毫秒
- 删除缓存
阻塞一段时间之后,再次删除缓存,就可以把这个过程中缓存中不一致的数据删除掉。而具体的时间,要评估你这项业务的大致时间具体设置。
而且对于先更新数据库,再删除缓存没有出现错误的情况下,也存在一种可能性:

这种情况发生的概率很低,首先是缓存刚好失效的那一刻有读请求,并且这个读请求回写缓存的时间大于更新数据库的时间,正常的话回写缓存是比更新数据库要快的。
如果这种极端情况出现,那也需要采用延时双删策略,更新数据库后会删除缓存,此时新开一个线程等待n毫秒后再删除一次缓存,或将删除请求放入消息队列,保证缓存是新数据,或者使用消息队列定时消息,延时删除。
边栏推荐
- 又是一年开源之夏,1.2万项目奖金等你来拿!
- NFT digital collection system development: what are the best digital marketing strategies for NFT digital collection
- 成为 Apache 贡献者,So easy!
- How to expand and repartition the C disk?
- Typora免费版下载安装
- anaconda安装教程-手把手教你安装
- PR subtitle production
- Unity3d asynchronous loading of scenes and progress bar loading
- C51与MDK共存 Keil5安装教程
- 4、数据的完整性
猜你喜欢

NFT数字藏品系统开发:华为发布首款珍藏版数字藏品

Learn browser decoding from XSS payload

Advanced Mathematics (Seventh Edition) Tongji University General exercises two person solution

Singles cup web WP

Opencv learning warp Perspective

又是一年开源之夏,1.2万项目奖金等你来拿!

倒计时2日!基于 Apache DolphinScheduler&TiDB 的交叉开发实践,从编写到调度让你大幅提升效率

"Wei Lai Cup" 2022 Niuke summer multi school training camp 1 supplementary question record (acdgij)

依赖和关联的对比和区别

Redis migrate tool migration error.
随机推荐
3.0.0 alpha blockbuster release! Nine new functions and new UI unlock new capabilities of dispatching system
NFT digital collection system development: digital collections give new vitality to brands
Event loop in browser
Curl post request on the server, using postman tool for parameter conversion
Unity3d asynchronous loading of scenes and progress bar loading
正则表达式规则以及常用的正则表达式
3.0.0 alpha 重磅发布!九大新功能、全新 UI 解锁调度系统新能力
This section is for Supplement 2
Opencv learning color detection
Leetcode 1184: distance between bus stops
PXE高效批量网络装机
4. Data integrity
OAuth2.0系列博客教程汇总
从XSS Playload 学习浏览器解码
Apache dolphin scheduler 2.x nanny level source code analysis, China Mobile engineers uncover the whole process of service scheduling and start
Advanced Mathematics (Seventh Edition) Tongji University General exercises two person solution
Compose canvas custom circular progress bar
Uncover the mystery of cloud native data management: operation level
Drools (2): drools quick start
Screen: frame paste, 0 fit, full fit