当前位置: 首页 > article >正文

Redis作为缓存和数据库的数据一致性问题

  • Redis作为缓存和数据库的数据一致性问题
    • 数据更新操作
      • 修改还是删除?
      • 先数据库还是先缓存
    • 设置过期时间

Redis作为缓存和数据库的数据一致性问题

使用Redis作为缓存了,但是会有一个问题,就是当修改了数据库中的数据,这个时候缓存中响应的数据就和数据库不一致了,这个时候应该怎么办呢?注意:本文只关注最终会导致缓存和数据库中数据不一致的情况。

数据更新操作

数据更新操作,也就是对数据库执行update执行更新操作。那么对数据进行修改的同时也需要对Redis中缓存执行一些操作来解决数据不一致的问题,那么应该对Redis中的缓存数据执行同步修改操作还是删除操作呢?

修改还是删除?

首先看更新数据库后是去更新缓存操作,考虑下面两种情景:

**情景1:**用户修改自己的用户名,修改了一次后不满意,就又修改了一次,但是最后显示的却是第一次修改的用户名,第二次修改的没有显示出来。这是为什么。

首先在这期间共发起了四次请求,线程A执行第一次修改,线程B执行查询,线程C执行第二次修改,线程D执行第二次查询。着重看两次修改的线程。这是导致缓存和数据库数据不一致的关键。

如果线程A先更新数据库后,但是出现了网络延迟,缓存的更新操作延迟了,线程C更新了数据库,立马又更新了缓存,此时线程A的缓存更新操作完成了,于是,缓存中的数据就是线程A的更新数据,而数据库中的数据是最终线程C的更新数据,这就造成了数据不一致。
在这里插入图片描述

**情景2:**当前是写多读少的程序,用户执行了1000次修改操作,但是最后才执行了1次查询操作。那么此时就会进行1000次数据库的修改和缓存的修改,但是缓存的前999次修改都是无效的,造成了大量的时间和空间浪费,删除操作又比修改操作快,而且无数据时删除操作是不执行的。所以删除缓存是最好的选择而不是更新。

最终我们选择更新完数据库后进行删除操作

先数据库还是先缓存

我们已经知道是更新数据库,删除缓存这两个操作。那么是先更新数据库还是先删除缓存呢?同样,从用户场景出发。

先删除缓存,再更新数据库:因为对数据库操作是很慢的,而对缓存操作是很快的,所以很容易出现下面一个情景:线程A先更新数据,线程B再读取数据,线程A删除了缓存,但是由于更新数据库的速度很慢,事务还未提交,线程B又进来了,它读取缓存但是缓存被删了就去读数据库,读取到了数据库中的数据返回给了客户端,同时将数据写到了缓存中,最后线程A更新数据库的操作终于完成了。这时,数据库中保存的确实是最终修改后的新值,但是缓存中却保存着更新前的旧值。同样造成了数据不一致问题。

在这里插入图片描述
**先更新数据库再删除缓存:**这种操作的话,也可能会出现数据不一致的问题。就是线程B读缓存,未读到,然后去查询了数据库,但是写入缓存的时候延迟了,这时候线程A更新了数据库,并删除了缓存。最后线程B才将数据库查到的数据写入缓存。这时候缓存就是旧值,数据库中就是新值。但是由于缓存操作肯定会快于数据库操作,所以发生概率不大。但同样也有可能,所以也可以有一些策略来解决:延迟双删操作(更新数据库->第一次删除缓存---->延迟一段时间第二次删除缓存)

设置过期时间

上面所有的操作都只能尽可能地保证数据库和缓存的数据一致,但是就像没有十全十美的人一样,软件也做不到完美,所以总会有疏漏,所以在缓存上添加一个过期时间,在一段时间后自动删除,下次再获取就需要从数据库中获取数据再写入缓存,这样也保证了一致性。这也是最后的兜底方案了。


http://www.kler.cn/a/558253.html

相关文章:

  • ES6中Object.defineProperty 的详细用法和使用场景以及例子
  • php文件上传
  • _vm.xxxxxx is not a function“ vue2错误
  • 贪心算法
  • 基于 DeepSeek LLM 本地知识库搭建开源方案(AnythingLLM、Cherry、Ragflow、Dify)认知
  • 使用Java爬虫获取1688 item_search_factory 接口的工厂搜索数据
  • 网页请求腾讯云环境的云函数
  • [Android]如何让APP快速被系统杀掉
  • 在 Mac ARM 架构的 macOS 系统上启用 F1 键作为 Snipaste 的截屏快捷键
  • 文本分类与情感分析算法
  • 图解【提示工程 VS 微调 VS RAG、全量微调 VS LoRA微调、TopK VS TopP】截图笔记
  • IGBT的损耗性分析
  • deepseek自动化代码生成
  • 知识图谱-学习计划
  • C语言 / C#改造冒泡排序函数bubble_sort()
  • 【练习】【回溯No.1】力扣 77. 组合
  • Windows 上编译 mebedtls 的鸿蒙库
  • 毕业项目推荐:基于yolov8/yolo11的水稻叶片病害检测识别系统(python+卷积神经网络)
  • HTML Application(hta)入门教程
  • SpringBoot 整合 JPA