Redis缓存MySQL数据库存储二者如何保证数据一致性

news/2024/4/24 20:15:47/

文章目录

  • Redis缓存MySQL数据库存储二者如何保证数据一致性
    • 数据一致性问题
      • 缓存穿透
      • 缓存雪崩
    • Redis缓存MySQL数据库存储一致性解决方案
      • 方案一:读写数据库时同步更新缓存
      • 方案二:使用消息队列异步更新缓存
    • 总结

Redis缓存MySQL数据库存储二者如何保证数据一致性

在大型互联网应用中,由于数据库读写频繁、压力大等原因,我们通常会使用缓存来减少数据库的访问次数,提高系统的性能。而Redis作为一个高性能的内存数据库,成为了缓存的首选方案之一。但是,缓存和数据库之间存在数据一致性的问题,如何解决这个问题呢?本文将结合JAVA语言和当前各大互联网公司主流解决方案,介绍一下Redis缓存MySQL数据库存储二者如何保证数据一致性。

数据一致性问题

当我们使用缓存后,就需要考虑数据库和缓存之间的数据一致性问题。在没有缓存的情况下,数据的更新和删除直接操作数据库即可。但是,当我们使用缓存后,如果缓存和数据库的数据不一致,就会出现脏数据、数据丢失等问题,导致应用程序的异常或错误。因此,我们需要对缓存和数据库之间的数据进行同步和验证,以确保数据的一致性。

缓存穿透

缓存穿透是指在数据不存在于缓存并且不在数据库中,每次请求都要查询一次缓存和一次数据库,这样会给数据库造成很大的压力。解决这个问题的方法是在查询缓存之前添加一个布隆过滤器,用来快速判断数据是否存在于数据库中。如果不存在则直接返回,否则再去查询缓存和数据库。

缓存雪崩

缓存雪崩是指当缓存中的数据失效或者集体失效,导致所有的请求都打到了数据库上,给数据库造成很大的压力,甚至会导致宕机。解决这个问题的方法是在缓存中设置不同的过期时间,避免缓存同时失效。

Redis缓存MySQL数据库存储一致性解决方案

为了保证Redis缓存和MySQL数据库之间的数据一致性,我们可以使用以下两种主流解决方案:

方案一:读写数据库时同步更新缓存

当有数据变动时,首先操作数据库,然后再操作缓存,保证缓存中的数据和数据库中的数据一致。

public class UserService {private final JdbcTemplate jdbcTemplate;private final String REDIS_KEY_PREFIX = "user_";public User getById(int id) {// 先从缓存中获取数据User user = cache.get(REDIS_KEY_PREFIX + id);if (user != null) {return user;}// 缓存中没有数据,则从数据库中获取,并更新缓存user = jdbcTemplate.queryForObject("select * from user where id = ?", User.class, id);cache.set(REDIS_KEY_PREFIX + id, user);return user;}public void update(User user) {// 先更新数据库jdbcTemplate.update("update user set name = ?, age = ? where id = ?", user.getName(), user.getAge(), user.getId());// 再更新缓存cache.set(REDIS_KEY_PREFIX + user.getId(), user);}public void deleteById(int id) {// 先删除数据库中的数据jdbcTemplate.update("delete from user where id = ?", id);// 再删除缓存中的数据cache.delete(REDIS_KEY_PREFIX + id);}
}

这种方案能够保证数据一致性,但是会对写入性能产生一定的影响,并且容易出现高并发下的缓存与数据库不一致的问题。

方案二:使用消息队列异步更新缓存

当有数据变动时,我们先操作数据库,然后通过消息队列发送消息到一个缓存更新的队列中,异步更新缓存。这种方式能够让写操作变得更加高效,并且避免了高并发下的缓存与数据库数据不一致的问题。

public class UserService {private final JdbcTemplate jdbcTemplate;private final String REDIS_KEY_PREFIX = "user_";private final RabbitTemplate rabbitTemplate;public User getById(int id) {// 先从缓存中获取数据User user = cache.get(REDIS_KEY_PREFIX + id);if (user != null) {return user;}// 缓存中没有数据,则从数据库中获取,并发送消息到更新缓存的队列中user = jdbcTemplate.queryForObject("select * from user where id = ?", User.class, id);rabbitTemplate.convertAndSend("updateCacheQueue", user);return user;}@RabbitListener(queues = "updateCacheQueue")public void updateCache(User user) {cache.set(REDIS_KEY_PREFIX + user.getId(), user);}public void update(User user) {// 先更新数据库jdbcTemplate.update("update user set name = ?, age = ? where id = ?", user.getName(), user.getAge(), user.getId());// 发送消息到更新缓存的队列中rabbitTemplate.convertAndSend("updateCacheQueue", user);}public void deleteById(int id) {// 先删除数据库中的数据jdbcTemplate.update("delete from user where id = ?", id);// 发送消息到更新缓存的队列中rabbitTemplate.convertAndSend("deleteCacheQueue", REDIS_KEY_PREFIX + id);}@RabbitListener(queues = "deleteCacheQueue")public void deleteCache(String key) {cache.delete(key);}
}

这种方案能够保证写操作的高效性和数据一致性,但是需要引入消息队列,增加了系统复杂度,同时也需要考虑缓存更新失败的情况。

总结

Redis缓存MySQL数据库存储二者如何保证数据一致性,既可以同步更新缓存,也可以异步更新缓存。同步更新缓存能够保证数据一致性,但会对写操作的性能产生影响;异步更新缓存则能够避免这个问题,但需要引入消息队列,并且也需要考虑缓存更新失败的情况。根据实际情况选择不同的方案即可。


http://www.ppmy.cn/news/48269.html

相关文章

背锅侠?软件测试各类bug分类定位,从功能到性能超细总结......

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 遇到功能性问题&a…

软件测试概念篇(下)|开发模型与测试模型

作者:爱塔居 专栏:软件测试 作者简介:大三学生,希望同大家一起进步! 文章简介:主要介绍软件生命周期、瀑布模型和螺旋模型两个开发模型,V模型和W模型两个测试模型 文章目录 目录 文章目录 一、软…

IOC容器与DI依赖注入示例

IOC容器与DI依赖注入示例 IOC深入理解IOC示例: DI深入理解DI示例 IOC深入理解 我们先通过几个问题来加深一下对IOC的理解 (1)Spring是使用IOC容器来管理bean对象的,我们主要管理什么? 主要管理项目中所使用到的类对象,比如(Service层对像和…

在现成的3D打印机上进行实验理论:一种数据孪生的攻击探测框架

在现成的3D打印机上提供了一种DT中攻击探测框架的DT解决方案的实验演示,作为说明性CPMS资源。通过网络安全DT对打印机正常运行、异常运行和攻击三种情况下的实验数据进行收集和分析,得出攻击检测结果。实验装置概述如下图所示。该实验研究是在现实世界设…

tokenURI的实现方式

做数字藏品最重要的function是tokenURI(tokenId)。 实现1 基本路径tokenID ERC721 function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {_requireMinted(tokenId);string memory baseURI _baseURI();return bytes(baseURI).length &…

HarmonyOS原子化服务卡片整改、下架、升级失败部分原因及处理办法

随着HarmonyOS应用体系相关规则、团队的不断发展和完善,早期上架运营的HarmonyOS原子化服务卡片,很多都收到了整改、下架的通知,主要集中在用户协议、隐私声明、服务卡片的设计规范性等细节方面的问题;需要进行优化调整升级才行。…

源码:LeakCanary

一、介绍 自动检测内存泄漏的检查工具 二、使用 debugImplementation com.squareup.leakcanary:leakcanary-android:2.5debugImplementation只在debug模式的编译和最终的debug apk打包时有效 Memory Profiler 使用步骤 生成的内存泄漏快照 会放在sdcard/Download/leakcanar…

SSR在天猫优品大促会场的探索实践

BBC 发现其网站加载时间每增加一秒,用户便会流失 10%。为提高页面的秒开率,我们不断探索着优化策略,仅仅在浏览器领域下的优化已经满足不了我们的极致要求,开始往服务端方向不断探索。本文将讨论业务接入SSR的几个问题&#xff1a…

Spring Security --- formLogin配置

目录 环境准备 配置自定义登录表单页面 配置登录成功的跳转页面方式 配置登录失败的跳转页面方式 前端表单参数获取 CustomWebSecurityConfigurerAdapter配置类代码示例 环境准备 创建springboot项目引入spring security框架引入thymeleaf模板引擎 配置自定义登录表单页面…

水平居中、垂直居中的几种方法

水平居中的方法: 若是针对inline, 内联块inline-block, 内联表inline-table, inline-flex元素及img,span,button等元素 父元素设置 text-align:center; 绝对定位;弹性布局;grid网格布局 不定宽块状元素 设置 margin:auto; 绝对定…

第二章:uniapp整合axios之真机测试两问题

第二章:uniapp整合axios之真机测试两问题 上一章节,笔者编写了uniapp整合axios并实现前后端跨域请求的方案,完成了这些基本配置后,在浏览器端的测试基本是可以完成了,但是当笔者将程序运行到手机时,却出现…

springboot mybatis-plus 对接 sqlserver 数据库 批处理的问题 批量更新添加数据 方案三

问题: 在对接 sqlserver数据库的时候 主子表 保存的时候 子表批量保存 使用的 mybatis-plus提供的 saveOrUpdateBatch saveBatch 这两个方法 但是 报错 报错内容为 : com.microsoft.sqlserver.jdbc.SQLServerException: 必须执行该语句才能获得结果。 框…

springboot web项目统一时区方案

背景 springboot项目国际化中,会遇到用户选择的时间和最终存到数据库的时间不一致,可能就是项目开发和部署时的时区没有处理好,导致时间转换出现了问题。 先了解时区都有哪些: 1.GMT:Greenwich Mean Time 格林威治…

Kubernetes Operator开发

案例一 Traefik Operator开发 1.kubebuilder 创建项目 2.Crontroller开发与部署 开发环境准备 kubebuilder 介绍 CRD的开发与部署 Crontroller开发与部署 Operator功能设计 借助operator完成 和企业内部注册中心打通 这里以Traefiketcd的模式为例进行演示说明 在这里etcd p…

1.2和1.3、GCC

1.2和1.3、GCC 1.2和1.3、GCC1.2.1、什么是GCC1.2.2、编程语言的发展1.2.3、GCC工作流程1.2.4、gcc和g的区别1.2.5、GCC常用参数选项实际操作①接下来进行预处理操作(test.c为需要预处理的源代码,test.i为要生成的目标代码)②汇编操作&#x…

多线程基础

1.多线程基础概念 多线程:让程序同时做多件事情 多线程作用:提高效率 并发:在同一时间,有多个指令在单个cpu上交替执行 并行:在同一时刻,有多个指令在多个cpu上同时执行 2.多线程的实现 (1)继承Thread类…

电脑卡顿反应慢怎么处理?电脑提速,4个方法!

案例:电脑卡顿反应慢怎么处理? 【快帮帮我!我的电脑现在越用越卡了,有时候光是打开一个文件都要卡好几分钟,我真的太难了,有什么可以加速电脑反应速度的好方法吗?万分感谢!】 随着…

es7.x集群部署-多台物理机部署-docker环境部署-docker-compose管理

es集群部署文档 部署es服务的三台服务器的ip和host分分别是: iphost_name192.168.1.2web02192.168.1.3storage02192.168.1.4Storage03 这个配置需要在服务器上编写对应的hosts文件,然后才可以使用host进行配置。 本次部署没有外挂配置文件&#xff0…

手把手教你 DVOL

分享本文在朋友圈的读者可获得本文数据和 Python 代码。留个言说已分享(不用截屏)我相信你,我会发给你百度盘下载链接。 本文长度为 6393 字,建议阅读 32 分钟 题图:SignalPlus Dashboard 0 引言 Deribit volatility (…

Qt音视频开发37-识别鼠标按下像素坐标

一、前言 在和视频交互过程中,用户一般需要在显示视频的通道上点击对应的区域,弹出对应的操作按钮,将当前点击的区域或者绘制的多边形区域坐标或者坐标点集合,发送出去,通知其他设备进行处理。比如识别到很多人脸,用户单击某个人脸后指定对该人脸进行详细的信息查询等;…