Redis缓存与数据库如何保证一致性

数据库和缓存如何保证一致性?

目录

  • 数据库和缓存如何保证一致性?
    • 背景
    • 方案
    • 先更新数据库,还是先更新缓存?
      • 先更新数据库,再更新缓存
      • 先更新缓存,再更新数据库
    • 先更新数据库,还是先删除缓存?
      • 先删除缓存,再更新数据库
      • 先更新数据库,再删除缓存
      • 最终解决方案
        • 先更新数据库再更新缓存
        • 先更新数据库再删除缓存

背景

公司项目是教育方面的产品,对于课程数据使用比较频繁,用户使用的是时候对其响应速度要求较高,随着使用人数越来越多,并发越来越高,查询数据库的频率越来越高,导致接口访问速度越来越差,数据库性能达到瓶颈。

方案

目前解决此类常用数据的方案就是使用缓存,将查看的课程数据缓存到缓存中,这样,在客户端请求数据时,如果能在缓存中命中数据,那就查询缓存,不用在去查询数据库,从而减轻数据库的压力,提高服务器的性能。但是需要注意的是,当数据发生变化的时候,缓存数据也需要同事变更,需要考虑数据库和缓存如何保证一致性?

先更新数据库,还是先更新缓存?

我们首选要考虑的问题,就是如果数据更新的时候,是先更新数据库还是先更新缓存呢?

在这里插入图片描述

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

在这里插入图片描述

这个是属于一个理想状态想的操作,我们想象一下如果并发的情况下一定会出现缓存的数据与数据库的数据不一致的问题,举例说明一下:

  1. A请求和B请求同事更新同一个资源,A想更新这个资源的名称为lesson1,B想更新这个资源的名称为lesson2

  2. 假设A进行更新数据库,已经更新成功了讲数据库的资源名称更新成了lesson1

  3. 在更新缓存之前,B这个请求先进来更新数据库操作,将资源名称更新为lesson2 了,并且同事更新缓存为lesson2

  4. 这个时候A请求才处理更新缓存操作,将缓存更新为lesson1

  5. 这个时候数据库的资源名称为:lesson2,而缓存为lesson1

下面我们画个时序图帮助理解:

在这里插入图片描述

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

其实是一样的道理,并发情况下也一样,只是跟上面的反过来,所以这里就不做赘述了。

先更新数据库,还是先删除缓存?

我们换个思路看看,如果我们不去做更新,而直接删除缓存的,用户更新数据库以后直接删除缓存,这样用户查询的时候查不到缓存就直接取数据库,然后再缓存。其实这个跟上面的类似,只是这种情况在于删除缓存比更新缓存要快的多,出现并发的情况的概率会小很多,而且如果加上缓存失效时间,就更可靠了,下面继续分析。

在这里插入图片描述

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

在这里插入图片描述

  1. 还是A、B两个请求并发,A请求是需要更新数据库资源,B请求则是查询数据库资源
  2. 由于方案是先删除缓存再更新数据库,A请求先删除缓存的数据,缓存删除成功以后,需要更新数据库,再这个时候,B请求进来查询这条数据,先查询缓存,未命中,于是从数据库进行查询,查到的数据为lesson2,并更新缓存数据为lesson2
  3. A删除完缓存以后,再进行更新数据为lesson1值数据库中。
  4. 此时缓存的数据为lesson2,数据库的数据为lesson1

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

在这里插入图片描述

  1. A、B两个请求并发,A请求是需要更新数据库资源,B请求则是查询数据库资源
  2. A先更新数据库为lesson1,更新成功以后,删除缓存;B请求来查询数据 ,查不到,则查询数据库,查到数据,再更新缓存为lesson1
  3. 看起来没问题,但是如果缓存删除的时候,由于网络原因,或者某种不可控的原因删除失败了,那B拿到数据的就是旧的缓存数据,同时也会存在缓存问题与数据库不一致的问题

最终解决方案

如果对缓存命中率要求较高的话就得采用更新数据库再更新缓存的方案,如果对命令率要求不高则采用先更新数据库再删除缓存。前面也分析了这两种方案都有缺陷,都可能在并发情况下存在缓存与数据库不一致。那么针对这两种情况做下优化。

先更新数据库再更新缓存

这种方案前面我们也分析过,在两个更新请求并发执行的时候,会出现数据不一致的问题,因为更新数据库和更新缓存这两个操作是独立的,而我们又没有对操作做任何并发控制,那么当两个线程并发更新它们的话,就会因为写入顺序的不同造成数据的不一致。

这个地方我们可以在更新缓存的时候增加一个分布式锁,保证同一时间只运行一个请求更新缓存,就会不会产生并发问题了,当然引入了锁后,对于写入的性能就会带来影响。然后在此基础上给缓存添加一个过期时间,这样就算出现缓存数据库不一致的情况,也有补偿机制。

先更新数据库再删除缓存

其实这种情况最好解决,我们只需要在删除缓存的时候增加重试机制,引入mq消息,如果删除失败,则进行重试,删除成功,消息消费完成,然后再对缓存增加过期时间作为补偿机制,这样就可以高枕无忧了。

这里也说明一下为什么推荐删除缓存,因为大家知道更新缓存的话,如果这个缓存的数据关联比较多,那么这个查询就会很多,就会很麻烦,如果删除缓存的,就方便多了,速度也会快很多,当然这样缓存命中率就会低很多。

存的数据关联比较多,那么这个查询就会很多,就会很麻烦,如果删除缓存的,就方便多了,速度也会快很多,当然这样缓存命中率就会低很多。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/288102.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

代码随想录刷题笔记(DAY4)

今日总结:今天把中心放在前端学习上,最后一个题没有完全理解,明天早起补上吧。勉强算完成任务。(已补上) Day 4 01. 两两交换链表中的节点(No. 24) 题目链接 代码随想录题解 1.1 题目 给你…

Python高级用法:装饰器(decorator)

装饰器(decorator) Python装饰器的作用是使函数包装与方法包装(一个函数,接受函数并返回其增强函数)变得更容易阅读和理解。最初的使用场景是在方法定义的开头能够将其定义为类方法或静态方法。 不使用装饰器的代码如…

Cesium特效-2023年汇总

1-3dTiles建筑实现随机贴图 使用3dTiles的customShader接口,在前端实现不同白模建筑贴不同的图片 2-淡入淡出的扩散雷达效果 在扩散雷的基础上,实现渐隐渐现的效果 3-不规则多边形的扩散效果 指定一个中心点,改变每个多边形的顶点位置来实现动…

如何做一个炫酷的Github个人简介(3DContribution)

文章目录 前言3D-Contrib第一步第二步第三步第四步第五步第六步 前言 最近放假了,毕设目前也不太想做,先搞一点小玩意玩玩,让自己的github看起来好看点。也顺便学学这个action是怎么个事。 3D-Contrib 先给大家看一下效果 我的个人主页&am…

坐标转换 | EXCEL中批量将经纬度坐标(EPSG:4326)转换为墨卡托坐标(EPSG:3857)

1 需求 坐标系概念: 经纬度坐标(EPSG:4326):WGS84坐标系(World Geodetic System 1984)是一种用于地球表面点的经纬度坐标系。它是美国国防部于1984年建立的,用于将全球地图上的点定位&#xff0…

普中STM32-PZ6806L开发板(HAL库函数实现-读取内部温度)

简介 主芯片STM32F103ZET6,读取内部温度其他知识 内部温度所在ADC通道 温度计算公式 V25跟Avg_Slope值 参考文档 stm32f103ze.pdf 电压计算公式 Vout Vref * (D / 2^n) 其中Vref代表参考电压, n为ADC的位数, D为ADC输入的数字信号。 实现…

Linux驱动学习—设备树及设备树下的platform总线

1、什么是设备树? 设备树是一种描述硬件资源的数据结构。他通过bootloader将硬件资源传给内核,使得内核和硬件资源 描述相对独立。 2、设备树的由来 2.1 平台总线的由来 要想了解为什么会有设备树,设备树是怎么来的,我们就要先…

网络安全—模拟IP代理隐藏身份

文章目录 网络拓扑安装使用代理服务器设置隐藏者设置 使用古老的ccproxy实现代理服务器,仅做实验用途,禁止做违法犯罪的事情,后果自负。 网络拓扑 均使用Windows Server 2003系统 Router 外网IP:使用NAT模式 IP DHCP自动分配或者…

提升软件质量与效率:UI自动化测试的重要性

在软件开发领域,UI自动化测试工具被广泛应用,其意义不仅仅体现在节省时间和资源上,更关系到软件质量的提升、团队效率的增加,以及用户体验的改善。本文将探讨使用UI自动化测试工具的重要性,以及它在软件开发生命周期中…

IDEA生成jar包

一、打开项目结构管理界面 英文版可以使用Ctrl Alt Shift S 打开 Project Structure 窗口 如下图 汉化idea 在设置中 tips:idea汉化包如果不能下载的话,可以手动下载安装 1、先确认自己安装的idea版本 2、来这里Chinese (Simplified) Language Pack…

一篇了解springboot3请求参数种类及接口测试

SpringBoot3数据请求: 原始数据请求: //原始方式RequestMapping("/simpleParam")public String simpleParam(HttpServletRequest request){//获取请求参数String name request.getParameter("name");String age request.getParame…

【备忘】今天写一下如何买免费证书

使用场景 使用微信支付宝支付转账时小游戏小程序接口开发时其它情况 开发中不可避免的会接触https,有的公司有运维去做这个事,有的是老板自己会搞https证书,咱多了解一项技术也是好事。 如何买证书 登录阿里云控制台,搜索ssl证…

transformers Trainer自定义optimizer和scheduler

1.需求 我自定义了一个evaluate方法,想在每一轮训练过后都执行一次。如果只是在TrainingArguments里设置warmup_steps100,那么每轮都会重置学习率,也就是每一轮开始的时候都会按照warmup刚开始的学习率进行训练,这就很头疼。 2.…

Android App从备案到上架全过程

不知道大家注意没有,最近几年来,新的移动App想要上架是会非常困难的,并且对于个人开发者和小企业几乎是难如登天,各种备案和审核。但是到底有多难,或许只有上架过的才会有所体会。 首先是目前各大应用市场陆续推出新的声明,各种备案截止日期到12月就要到最后期限责令整改…

MT8766安卓核心板规格参数_MTK8766核心板模块方案定制

MT8766安卓核心板:高性能、稳定可靠、集成度高的一体化解决方案 MT8766安卓核心板采用联发科MTK8766四核4G模块方案,是一款高度集成的安卓一体板。四核芯片架构,主频可达到2.0GHz,支持国内4G全网通。12nm制程工艺,支持…

全国计算机等级考试| 二级Python | 真题及解析(6)

全国计算机等级考试二级Python真题及解析(8)图文 一、选择题 1.python中表达式4**3=( )。 A.12 B.1 C.64 D.7 2.在Python中,通过( )函数查看字符的编码。 …

学生公寓安全用电管理系统应用案例

摘要:安全用电是学校公寓用电管理的首要任务,这就需要对一些恶性负载进行识别和控制,同时为了减少电工和后期管理人员的成本,引进了安全用电管理系统。本文在在描述了安全用电管理系统的工作原理和利用智能电表可实现的功能后,阐明…

B端产品经理学习-B端产品系统调研的工具

系统性调研目标的工具 系统性调研的目标 相对于背景调研,系统行调研是对公司可控因素(公司内部)和直接作用力(消费者、竞争者)进行的调研。系统性调研需要输出结论,为达成产品或公司的战略目标而制定行动的…

Dockerfile与DockerCompose

Docker的Image结构是怎样的? 镜像是将应用程序 及其需要的 系统函数库、环境、配置、依赖 打包而成。 镜像结构 入口( Entrypoint ) 镜像运行入口,一般是程序启动的脚本和参数 层( Layer ) 在BaseImage基…

Spring-IOC综述

文章迁移自语雀。 怎么查看spring的文档 ioc综述 说到spring的ioc,其实就是控制反转,为啥需要控制反转呢,其实是为了功能的增强,如果不用spring, 我们直接使用工厂方法,静态工厂方法, 都是是可以获取到对象的,但是如果需求变了,我们在类的生成时,添加了很多信息,使用工厂就不…