如何保证MySQL和Redis中的数据一致性?

文章目录

  • 前言
  • 一、缓存案例
    • 1.1 缓存常见用法
    • 1.2 缓存不一致产生的原因
  • 二、解决方案
    • 2.1 先删除缓存,再更新数据库
    • 2.2 先更新数据库,删除缓存
    • 2.3 只更新缓存,由缓存自己同步更新数据库
    • 2.4 只更新缓存,由缓存自己异步更新数据库
    • 2.5 引入 MQ
  • 三、总结

前言

在高并发的场景下,大量的请求直接访问MySQL很容易造成性能瓶颈。所以,我们都会用Redis来做数据的缓存,削减对数据库的压力。但是,MySQL和Redis是两种不同的数据库,如何保证不同数据库之间数据的一致性就非常关键了。

关于MySQL和Redis中的数据一致性问题,可以先说一下结论:没有完美的方案,只有最适合某场景的方案。这个问题表面上看是数据一致性的问题,其实根本上,又是数据一致性、系统性能和系统复杂度的选择与取舍。我们所能做到的是尽可能让它们的数据在绝大部分时间内保持一致,并保证最终是一致的。

一、缓存案例

1.1 缓存常见用法

通常情况下,我们使用缓存的主要目的是为了提升查询的性能。大多数情况下,我们使用缓存的例子如下图。

在这里插入图片描述
1.用户请求过来之后,先查缓存有没有数据,如果有则直接返回。
2.如果缓存没数据,再继续查数据库。
3.如果数据库有数据,则将查询出来的数据,放入缓存中,然后返回该数据。
4.如果数据库也没数据,则直接返回空。

这是缓存非常常见的用法,一眼看上去,好像没有啥问题。但如果数据库中的某条数据,放入缓存之后,又立马被更新了,那么缓存中的数据就和数据库中的数据不一致了。

1.2 缓存不一致产生的原因

如果数据一直没有变更,那么就不会出现Redis和MySQL数据不一致性的问题。

两者之间数据不一致是因为一者发生了数据的变更,另一者如何在短时间内同步数据的问题。因为每次数据变更需要同时操作数据库和缓存,而他们又属于不同的系统,无法做到同时操作成功或失败,总会有一个时间差。在并发读写的时候可能就会出现缓存不一致的问题。

二、解决方案

缓存更新的设计方法大概有5种,下面分别对这四种方案进行描述。

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

  1. 这种方法在并发读写的情况下容易出现缓存不一致的问题。
    在这里插入图片描述

  2. 如上图所示,其可能的执行流程顺序为:
    1.客户端1 触发更新数据A的逻辑
    2.客户端2 触发查询数据A的逻辑
    3.客户端1 删除缓存中数据A
    4.客户端2 查询缓存中数据A,未命中
    5.客户端2 从数据库查询数据A,并更新到缓存中
    6.客户端1 更新数据库中数据A

可见,最后缓存中的数据A跟数据库中的数据A是不一致的,缓存中的数据A是旧的脏数据。因此一般不建议使用这种方式。

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

  1. 这种方法在并发读写的情况下,也可能会出现短暂缓存不一致的问题。
    在这里插入图片描述
  2. 如上图所示,其可能执行的流程顺序为:
    1.客户端1 触发更新数据A的逻辑
    2.客户端2 触发查询数据A的逻辑
    3.客户端3 触发查询数据A的逻辑
    4.客户端1 更新数据库中数据A
    5.客户端2 查询缓存中数据A,命中返回(旧数据)
    6.客户端1 让缓存中数据A失效
    7.客户端3 查询缓存中数据A,未命中
    8.客户端3 查询数据库中数据A,并更新到缓存中

可见,最后缓存中的数据A和数据库中的数据A是一致的,理论上可能会出现一小段时间数据不一致,不过这种概率也比较低,大部分的业务也不会有太大的问题。

2.3 只更新缓存,由缓存自己同步更新数据库

  1. 只更新缓存,再由缓存去同步更新数据库。一个Write Through的例子如下:

在这里插入图片描述

  1. 如上图所示,其可能的执行流程顺序为:
    1.客户端1 触发更新数据A的逻辑
    2.客户端2 触发查询数据A的逻辑
    3.客户端1 更新缓存中的数据A,返回
    4.客户端2 查询缓存中的数据A,命中返回
    5.缓存异步更新数据A到数据库中

这种方式的优势是读写的性能都非常好,基本上只要操作完内存后就返回给客户端了,但是其是非强一致性,存在丢失数据的情况。

如果在缓存异步将数据更新到数据库中时,缓存服务挂了,此时未更新到数据库中的数据就丢失了。

2.4 只更新缓存,由缓存自己异步更新数据库

  1. 只操作更新缓存,再由缓存异步去更新数据库,例如:
    在这里插入图片描述
  2. 如上图所示,其可能的执行流程顺序为:
    1.客户端1 触发更新数据A的逻辑
    2.客户端2 触发查询数据A的逻辑
    3.客户端1 更新缓存中的数据A,返回
    4.客户端2 查询缓存中的数据A,命中返回
    5.缓存异步更新数据A到数据库中

这种方式的优势是读写的性能都非常好,基本上只要操作完内存后就返回给客户端了,但是其是非强一致性,存在丢失数据的情况。

如果在缓存异步将数据更新到数据库中时,缓存服务挂了,此时未更新到数据库中的数据就丢失了。

2.5 引入 MQ

在高并发的业务场景中,MQ(消息队列)是必不可少的技术之一。它不仅可以异步解耦,还能削峰填谷。对保证系统的稳定性是非常有意义的。MQ的生产者生产了消息之后,通过指定的topic发送到MQ服务器。然后MQ的消费者订阅该topic的消息,读取消息数据之后,做业务逻辑处理。使用MQ重试的具体方案如下:

在这里插入图片描述

  1. 当用户操作写完数据库,但删除缓存失败了,产生一条消息,发送给MQ服务器。
  2. 消费者读取MQ消息,重试5次删除缓存。如果其中有任意一次成功了,则返回成功。如果重试了5次,还是失败,则写入死信队列中。
  3. 推荐MQ使用RocketMQ,重试机制和死信队列默认是支持的。使用起来非常方便,而且还支持顺序消息,延迟消息和事务消息等多种业务场景。

当然在该方案中,删除缓存可以完全走异步。即用户的写操作,在写完数据库之后,不用立刻删除一次缓存。而直接发送消息,到MQ服务器,然后有消费者全权负责删除缓存的任务。因为MQ的实时性还是比较高的,因此改良后的方案也是一种不错的选择。

三、总结

1.我们能放入缓存的数据本就不应该是实时性、一致性要求超高的。所以缓存数据的时候加上过期时间,保证能够再容忍的时间段内拿到当前最新数据即可。
2.我们不应该过度设计,增加系统的复杂性。
3.遇到实时性、一致性要求高的数据,就应该查数据库,即使慢点。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ElementUI 组件:Layout布局(el-row、el-col)

ElementUI安装与使用指南 Layout布局 点击下载learnelementuispringboot项目源码 效果图 el-row_el-col.vue页面效果图 项目里el-row_el-col.vue代码 <script> export default {name:el-row_el-col 布局 }</script><template><div class"roo…

C/C++ (stdio.h)标准库详解

cstdio,在C语言中称为stdio.h。该库使用所谓的流与物理设备&#xff08;如键盘、打印机、终端&#xff09;或系统支持的任何其他类型的文件一起操作。 在本文将会通过介绍函数参数&#xff0c;举出实际的简单例子来帮助大家快速上手使用函数。 目录 一、流 二、库函数 1、F…

离线数仓-数据治理

目录 一、前言 1.1 数据治理概念 1.2 数据治理目标 1.3 数据治理要解决的问题 1.3.1 合规性 元数据合规性 数据质量合规性 数据安全合规性 1.3.2 成本 存储资源成本 计算资源成本 二、数据仓库发展阶段 2.1 初始期 2.2 扩张期 2.3 缓慢发展期 2.4 变革期 三、…

LabVIEW电能质量监测系统

LabVIEW电能质量监测系统 随着全球能源需求的增加以及能源危机的加剧&#xff0c;对电能的有效利用和质量监控变得越来越重要。特别是在电力系统中&#xff0c;电能质量的监测对于保证电力设备的稳定运行和提高能源利用效率具有重要意义。采用LabVIEW软件开发了一套高效的电能…

查看自己电脑是arm还是x64(x86);linux操作系统识别

1、查看自己电脑是arm还是x64&#xff08;x86&#xff09; linux 参考&#xff1a; https://liuweiqing.blog.csdn.net/article/details/131783851 uname -a如果输出是 x86_64&#xff0c;那么你的系统是 64 位的 x86 架构&#xff08;通常我们称之为 x64&#xff09;。如果…

MySQL原理(五)事务

一、介绍&#xff1a; 1、介绍&#xff1a; 在计算机术语中&#xff0c;事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。事务是恢复和并发控制的基本单位。 2、事务的4大特性 原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性…

Zoho Projects与Jira:中国市场的理想替代品之争?

在软件开发生命周期中&#xff0c;项目管理一直是一个非常重要的环节。为了更好地协作、追踪项目的进程和管理任务&#xff0c;许多公司选择了Jira这款著名的项目管理工具&#xff0c;它是个非常强大的工具&#xff0c;但是作为一款纯国外产品&#xff0c;他可能不适合中国市场…

性能篇:如何解决高并发下 I/O瓶颈?

大家好,我是小米!今天我们来聊一个在高并发场景下经常遇到的挑战,那就是I/O瓶颈。随着互联网的快速发展,我们的应用在处理海量数据时,I/O操作成为了一个极为关键的环节。那么,问题来了,什么是I/O呢? 什么是I/O I/O(Input/Output)是计算机系统中一个至关重要的概念,…

canvas设置图形各种混合模式,类似photoshop效果

查看专栏目录 canvas实例应用100专栏&#xff0c;提供canvas的基础知识&#xff0c;高级动画&#xff0c;相关应用扩展等信息。canvas作为html的一部分&#xff0c;是图像图标地图可视化的一个重要的基础&#xff0c;学好了canvas&#xff0c;在其他的一些应用上将会起到非常重…

dubbo+sentinel最简集成实例

说明 在集成seata后&#xff0c;下面来集成sentinel进行服务链路追踪管理&#xff5e; 背景 sample-front网关服务已配置好 集成 一、启动sentinel.jar 1、官网下载 选择1:在本地启动 nohup java -Dserver.port8082 -Dcsp.sentinel.dashboard.serverlocalhost:8082 -Dp…

QSlider使用笔记

最近做项目使用到QSlider滑动条控件&#xff0c;在使用过的过程中&#xff0c;发现一个问题就是点滑动条上的一个位置&#xff0c;滑块并没有移动到鼠标点击的位置&#xff0c;体验感很差&#xff0c;于是研究了下&#xff0c;让鼠标点击后滑块移动到鼠标点击的位置。 1、event…

记录element-plus树型表格的bug

问题描述 如果数据的子节点命名时children,就没有任何问题&#xff0c;如果后端数据结构子节点是其他名字&#xff0c;比如thisChildList就有bug const tableData [{id: 1,date: 2016-05-02,name: wangxiaohu,address: No. 189, Grove St, Los Angeles,selectedAble: true,th…

2024 IC FPGA 岗位 校招面试记录

引言 各位看到这篇文章时&#xff0c;24届校招招聘已经渐进尾声了。 在这里记录一下自己所有面试&#xff08;除了时间过短或者没啥干货的一些研究所外&#xff0c;如中电55所&#xff08;南京&#xff09;&#xff0c;航天804所&#xff08;上海&#xff09;&#xff09;的经…

【安装指南】maven下载、安装与配置详细教程

&#x1f33c;一、概述 maven功能与python的pip类似。 Apache Maven是一个用于软件项目管理和构建的强大工具。它是基于项目对象模型的&#xff0c;用于描述项目的构建配置和依赖关系。以下是一些关键的 Maven 特性和概念&#xff1a; POM&#xff08;Project Object Model&…

Javaweb之SpringBootWeb案例之 @ConfigurationProperties的详细解析

4.3 ConfigurationProperties 讲解完了yml配置文件之后&#xff0c;最后再来介绍一个注解ConfigurationProperties。在介绍注解之前&#xff0c;我们先来看一个场景&#xff0c;分析下代码当中可能存在的问题&#xff1a; 我们在application.properties或者application.yml中配…

神经网络 | 基于多种神经网络模型的轴承故障检测

Hi&#xff0c;大家好&#xff0c;我是半亩花海。本文主要源自《第二届全国技能大赛智能制造工程技术项目比赛试题&#xff08;样题&#xff09; 模块 E 工业大数据与人工智能应用》&#xff0c;基于给出的已知轴承状态的振动信号样本&#xff0c;对数据进行分析&#xff0c;建…

CMake生成osg的FFMPEG插件及Windows下不生成VS工程问题解决

在Windows下&#xff0c;如何利用CMake生成osg的FFMPEG插件&#xff0c;请参考如下博文&#xff0c;同生成jpeg插件类似&#xff1a; osg第三方插件的编译方法&#xff08;以jpeg插件来讲解&#xff09;。 如下为生成FFMPEG时必要的设置&#xff1a; 注意&#xff1a; 一定要…

Transformer实战-系列教程3:Vision Transformer 源码解读1

&#x1f6a9;&#x1f6a9;&#x1f6a9;Transformer实战-系列教程总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Pycharm中进行 本篇文章配套的代码资源已经上传 1、整体解读 在文本任务中大量使用了Transformer 架构&#xff0c;因为文本数据是一个序列非常好…

Django响应式图像库django-pictures

什么是响应式图像&#xff1f; 响应式设计是指网页在不同尺寸的设备上都有良好的显示效果。响应式设计的网页图像&#xff0c;就是响应式图像。 django-pictures是使用现代代码&#xff08;如 AVIF 和 WebP&#xff09;的响应式跨浏览器图像库。 特点 使用 Picture 标签的响应…

QSqlRelationalTableModel 关系表格模型

一、 1.1 QSqlRelationalTableModel继承自QSqlTableModel&#xff0c;并且对其进行了扩展&#xff0c;提供了对外键的支持。一个外键就是一个表中的一个字段 和 其他表中的主键字段之间的一对一的映射。例如&#xff0c;“studInfo”表中的departID字段对应的是“departments…