如何保证数据库的数据和Redis的数据一致性

实际项目中有可能会使用Redis缓存数据,那么在更新数据的时候如何保证数据库中的数据和Redis缓存的数据一致,缓存同步策略的选择是一个很重要的问题。网上有各种说法,大概总结有以下几种,看看每种方案是否可行以及存在的问题和适用场景。

1、先更新Redis,再更新数据库 (不可行 )

数据库是比较复杂的,而且还会涉及事务,因为超时等原因更新操作失败的可能性较大,这种方案很可能因为数据库更新失败,导致缓存和数据库的数据不一致。
在这里插入图片描述
如上图所示,如果第2步更新数据库失败了,那么缓存的数据被更新为20,和数据库值10不一致了。

这种情况可能会想到补救措施:数据库更新失败了再将Redis数据做逆向操作进行回退,但是如果Redis数据回退操作也失败了呢?甚至还要继续针对这种失败做重试?显然事情越做越复杂了,这种方式不可行。

2、先更新数据库,再更新Redis (部分场景可用,不推荐 )

上面的方案不可取,这种先更新数据库的是否就可行呢?假设有两个请求更新数据,时序图如下:
在这里插入图片描述

如果是并发量不高,对一致性要求没有特别高时,如上图更新完数据库再更新Redis没有问题。

在这里插入图片描述

如果是并发量较高,如图所示这种场景下虽然请求1和请求2先后完成数据库更新,但更新缓存时却是请求2和请求1的顺序,那就很可能会把旧数据更新到缓存中导致数据不一致。

3、先删除Redis,再更新数据库,访问的时候再加载数据到缓存 (不可行 )

这里同样以两个请求的场景为例,时序图如下:
在这里插入图片描述
从图上可以看到,当并发场景下如果请求1更新耗时较长,还未来得及更新数据库中的值,请求2已经先读取了旧值并加载到缓存中了。这种也会导致两边数据不一致,而且并发量很高的时候这种概率也会更大。

针对这个方案存在的问题可以在请求1更新完数据库后再对Redis做一次删除操作。也就是缓存双删

4、先删除Redis,再更新数据库,再删除Redis,访问的时候再加载数据到缓存(缓存双删)

在这里插入图片描述
这种方案一定程度上解决了方案4数据不一致的问题,但是也有一个关键点,如上图所示必须保证第6步删除缓存操作在第5步回写入缓存操作之后执行,否则还是会有问题。那么这又引出了另外两个问题:

  • 问题一:如何保证第二次删除缓存一定在回写后面执行呢?

关于双删的这个问题网上有方案是让请求1删除缓存时等待xxx毫秒,这个方案似乎可行,但是这个时间不好控制还是会存在一定风险。
另外也有博主给出的建议方案是将删除请求加入消息队列,异步串行化处理删除

  • 问题二:如果双删失败了怎么办?

同样的网上也有方案:给redis加一个缓存过期时间、删除加入消息队列利用消息队列的重试机制、自己记录删除失败进行重试等

5、先更新数据库,再删除Redis,访问的时候再加载数据到缓存

在这里插入图片描述
这种方案除了请求2第一次查询这一次不一致,还有另一个极端场景会存在数据不一致。请求1更新数据节点缓存刚好失效了,另一个请求2刚好这时读取缓存没有进而读了数据库旧值,如下图所示:
在这里插入图片描述
这个极端场景需要满足缓存更好失效,而且请求2读取数据库及回写缓存耗时较请求1更新数据库更长,发生的概率非常小,可以忽略,所以相比较而言,方案5是最推荐的处理策略。

通过以上几种处理方案的分析,可以看到不管哪种方案都存在一定的问题,在满足实时性的条件下,尽量保证不一致出现的概率更低,或者不一致持续的时间非常短暂,避免长期不一致。非要满足强一致性可能就需要考虑使用锁的方案了。

总的来说,针对缓存同步更推荐的方式是,缓存中的数据不由数据更新操作主动触发,统一在需要使用的时候按需加载,数据更新后及时删除缓存中的数据。

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

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

相关文章

安装软件包

安装软件包 创建一个名为 /home/curtis/ansible/packages.yml 的 playbook : 将 php 和 mariadb 软件包安装到 dev、test 和 prod 主机组中的主机上 将 RPM Development Tools 软件包组安装到 dev 主机组中的主机上 将 dev 主机组中主机上的所有软件包更新为最新版本 vim packa…

关于Firmae缺失binwalk模块

问题 david707:~/FirmAE$ sudo ./run.sh -c weyow ./WAM_9900-20.06.03V.trx [*] ./WAM_9900-20.06.03V.trx emulation start!!! Traceback (most recent call last):File "./sources/extractor/extractor.py", line 19, in <module>import binwalk ModuleNot…

Android Studio调试的时候Logcat不显示日志了

文章目录 问题描述解决方案 问题描述 使用Log输出日志的时候&#xff0c;Logcat窗口并没有显示日志。 去除所有的过滤条件之后&#xff0c;Logcat窗口仍然没有一条消息。 解决方案 关闭Android Studio&#xff0c;重启Android Studio即可。

Docker容器:docker基础概述、安装、网络及资源控制

文章目录 一.docker容器概述1.什么是容器2. docker与虚拟机的区别2.1 docker虚拟化产品有哪些及其对比2.2 Docker与虚拟机的区别 3.Docker容器的使用场景4.Docker容器的优点5.Docker 的底层运行原理6.namespace的六项隔离7.Docker核心概念 二.Docker安装 及管理1.安装 Docker1.…

【k8s】基于Prometheus监控Kubernetes集群安装部署

目录 基于Prometheus监控Kubernetes集群安装部署 一、环境准备 二、部署kubernetes集群 三、部署Prometheus监控平台 四、部署Grafana服务 五、grafana web操作 基于Prometheus监控Kubernetes集群安装部署 一、环境准备 IP地址 主机名 组件 192.168.100.131 k8s-ma…

时序预测 | MATLAB实现WOA-CNN-GRU鲸鱼算法优化卷积门控循环单元时间序列预测

时序预测 | MATLAB实现WOA-CNN-GRU鲸鱼算法优化卷积门控循环单元时间序列预测 目录 时序预测 | MATLAB实现WOA-CNN-GRU鲸鱼算法优化卷积门控循环单元时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 时序预测 | MATLAB实现WOA-CNN-GRU鲸鱼算法优化卷积…

PrefetchParameters

Windows XP重新设置预读对象是允许的。具体方法是&#xff1a;打开注册表编辑器&#xff0c;依次展开 HKEY_LOCAL_MACHINE&#xff3c;SYSTEM&#xff3c;CurrentControlSet&#xff3c;Control&#xff3c;Session Manager&#xff3c;Memory Management&#xff3c;PrefetchP…

基于LVQ神经网络的人脸朝向识别

1案例背景 1.1人脸识别概述 人脸识别作为一个复杂的模式识别问题,近年来受到了广泛的关注,识别领域的各种方法在这个问题上各显所长,而且发展出了许多新方法,大大丰富和拓宽了模式识别的方向。人脸识别、检测,跟踪、特征定位等技术近年来一直是研究的热点。人脸识别是人脸应用…

【制作npm包1】申请npm账号、认识个人包和组织包

概述 在开发当中经常有一种现象&#xff0c;重复代码写了N多遍&#xff0c;再次写同样的逻辑就再次翻查以前的代码逻辑。效率低下且容易出错&#xff0c;封装一个npm包的价值也不仅仅是给别人用&#xff0c;封装一套属于自己或者本部门的npm包也是相当有必要。 也许经常看到一…

RabbitMQ的5种消息队列

RabbitMQ的5种消息队列 1、七种模式介绍与应用场景 1.1 简单模式(Hello World) 一个生产者对应一个消费者&#xff0c;RabbitMQ 相当于一个消息代理&#xff0c;负责将 A 的消息转发给 B。 应用场景&#xff1a;将发送的电子邮件放到消息队列&#xff0c;然后邮件服务在队列…

【JS学习】Object.assign 用法介绍

Object.assign 是ES6中的一个方法。该方法能够实现对象的浅复制以及对象合并。Object.assign 并不会修改目标对象本身&#xff0c;而是返回一个新的对象&#xff0c;其中包含了所有源对象的属性。 例1 2个对象合并 const target { a: 1, b: 2 }; const source { b: 3, c: 4…

【git】初次使用git上传代码到github远程仓库

目录 0.前言1.新建代码库2.添加SSH公钥2.1 前置准备2.2 Git 基本信息设置2.3 添加SSH Key 3.本地仓库上传到github3.1 建立本地仓库并初始化3.2 初始化仓库3.3 建立本地与github上新建项目链接3.4 同步github新建项目到本地3.5 添加本地文件到缓存区3.6 为上传文件添加注释3.7 …

注册中心Eureka和Nacos,以及负载均衡Ribbon

1.初识微服务 1.1.什么是微服务 微服务&#xff0c;就是把服务拆分成为若干个服务&#xff0c;降低服务之间的耦合度&#xff0c;提供服务的独立性和灵活性。做到高内聚&#xff0c;低耦合。 1.2.单体架构和微服务架构的区别&#xff1a; 单体架构&#xff1a;简单方便&#…

TS基本语法

一、安装 npm install -g typescript 或者 cnpm install -g typescript 或者 yarnlobal add typescript二、运行 tsc xxxx.ts注意&#xff1a;如果电脑上面没有安装过cnpm&#xff0c;请先安装cnpm npm install -g cnpm --registryhttps://registry.npm.taobao.org注意&…

数字图像处理-AWB跳变

1、自动白平衡&#xff08;AWB&#xff09;算法是相机中常用的图像处理技术&#xff0c;它能够自动调整图像中的白平衡&#xff0c;使得图像中的颜色更加真实、自然。然而&#xff0c;在实际应用中&#xff0c;AWB算法也存在着一些问题&#xff0c;例如AWB跳变&#xff08;Whit…

DevExpress WinForms数据编辑器组件,提供丰富的数据输入样式!(一)

DevExpress WinForms超过80个高影响力的WinForms编辑器和多用途控件&#xff0c;从屏蔽数据输入和内置数据验证到HTML格式化&#xff0c;DevExpress数据编辑库提供了无与伦比的数据编辑选项&#xff0c;包括用于独立数据编辑或用于容器控件(如Grid, TreeList和Ribbon)的单元格。…

云原生 envoy xDS 动态配置 java控制平面开发 支持restful grpc实现 EDS 动态endpoint配置

envoy xDS 动态配置 java控制平面开发 支持restful grpc 动态endpoint配置 大纲 基础概念Envoy 动态配置API配置方式动静结合的配置方式纯动态配置方式实战 基础概念 Envoy 的强大功能之一是支持动态配置&#xff0c;当使用动态配置时&#xff0c;我们不需要重新启动 Envoy…

spring boot 整合mongodb

1、安装依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId></dependency>2、配置数据库连接 spring:data:mongodb:host: localhostport: 27017username: xxxxxxp…

2682. 找出转圈游戏输家

题目描述&#xff1a; n 个朋友在玩游戏。这些朋友坐成一个圈&#xff0c;按 顺时针方向 从 1 到 n 编号。从第 i 个朋友的位置开始顺时针移动 1 步会到达第 (i 1) 个朋友的位置&#xff08;1 < i < n&#xff09;&#xff0c;而从第 n 个朋友的位置开始顺时针移动 1 步…

“华为杯”研究生数学建模竞赛2018年-【华为杯】F题:中转航班调度:从 MILP 模型到启发式算法

目录 摘 要 1 问题描述 2 模型假设 3 符号定义及数据预处理 3.1 符号定义