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

背景

使用Reids作为缓存的原因:
在高并发场景下,传统关系型数据库的并发能力相对比较薄弱(QPS不能太大);
使用Redis做一个缓存。让用户请求先打到Redis上而不是直接打到数据库上。
但是如果出现数据更新操作:数据库与缓存更新,就会出现缓存(Redis)和数据库(MySQL)之间的数据一致性问题。

非读写分离架构:延时双删

先更新数据库,再更新缓存,为什么不可行?

线程安全角度

同时有请求A、B进行更新操作

执行顺序如下:
线程A更新了数据库
线程B更新了数据库
线程B更新了缓存
线程A更新了缓存

缓存和数据库出现了不一致

业务角度

如果某个业务场景是写多读少,就会导致缓存并未被读取就会被频繁的更新,极大的浪费了服务器的性能。
因为数据库的值,并不是直接刷入缓存,有的业务需要经过一系列复杂的计算再写入缓存。

先删除缓存,再更新数据库,为什么不可行?

线程安全角度

请求A进行写操作,先删除缓存
请求B查询发现缓存不存在
请求B去数据库查询得到旧值
请求B将旧值写入缓存
请求A更新数据库

此时数据库中的值是新值,缓存的值是旧值,就发生了数据不一致问题

延时双删

线程 A:
当应用程序需要更新数据时,首先将数据更新到数据库
A 线程向 Redis 发送删除缓存的指令,将缓存标记为过期
A 线程等待一定的时间窗口(通常是几十ms~几百ms),让 B 线程有足够的时间去访问缓存

线程 B:
在时间窗口内,当有请求访问过期的缓存数据时,B 线程发现缓存已过期,并触发缓存更新的操作
B 线程从数据库中获取到最新数据,并将其存储到缓存中
B 线程返回更新后的缓存数据

线程 A(续):
在时间窗口结束后,A 线程再次向 Redis 发送删除缓存的指令,彻底删除缓存数据
如果在时间窗口内没有请求访问到过期的缓存数据,A 线程会删除已标记为过期的缓存数据

通过上述流程
A 线程负责标记缓存过期并等待一段时间,给 B 线程足够的时间去访问缓存并更新
B 线程则负责处理实际的缓存更新操作
这样即使在缓存更新期间有请求访问过期的缓存数据,也能获取到最新的数据,避免脏读

注意
具体的时间窗口大小和线程的实现方式可以根据实际需求和系统性能进行调整。
同时,对于高并发环境,还需要考虑线程安全和并发控制的实现,以确保操作的正确性和性能。

读写分离架构(有专门的读服务、专门的写服务,写主,读从主)

可以采用先更新数据库,再删除缓存,配合上重试机制

问题

两个请求:请求A进行更新操作,请求B进行查询操作
请求A进行写操作,删除缓存
请求A将数据写入数据库,
请求B查询缓存发现,缓存没有值
请求B去从库查询,这时,还没有完成主从同步,因此查询到的是旧值
请求B将旧值写入缓存
数据库完成主从同步,从库变为新值
仍然会出现缓存与数据库数据不一致问题

延时双删的问题

延时时间需要在主从同步的延时时间基础上,加几百ms

双删失败
如果第二次删除缓存失败,仍然会出现缓存与数据库数据不一致的问题

同样还是有两个请求请求A进行更新操作,请求B进行查询操作(单库)
请求A进行写操作,删除缓存
请求B查询发现缓存不存在
请求B去数据库查询得到旧值
请求B将旧值写入缓存
请求A将新值写入数据库
请求A试图去删除请求B写入的缓存值,结果失败了

删除失败的重试补偿机制

先更新数据库,再删除缓存
同样存在并发问题,但是发生几率很低

两个请求:请求A进行更新操作,请求B进行查询操作(单库)
缓存刚好失效
请求A查询数据库,得一个旧值
请求B将新值写入数据库
请求B删除缓存
请求A将查到的旧值写入缓存

该情况发生的必要条件就是请求B写数据库的操作比请求A读数据库的操作耗时更短,才能使请求B先删除缓存
但是通常来说数据库的读操作是远远快于写操作的,所以这种并发问题很难发生。

如果在极端情况下,这种并发问题仍然发生了
给缓存设置一定的有效时间

异步延时双删策略

另起一个线程,异步删除,保证读请求完成以后,再进行删除操作

重试机制
与先删除缓存,再更新数据一样,如果删除缓存失败,那么仍然会出现数据不一致问题

选择靠谱的重试机制,比如利用消息队列进行删除的补偿

方案一:

更新数据库数据;
缓存因为种种问题删除失败
将需要删除的key发送至消息队列
自己消费消息,获得需要删除的key
继续重试删除操作,直到成功

在这里插入图片描述
缺点
对业务线代码造成大量的侵入,需要在业务代码中额外添加生成消息和消费消息的功能
业务代码变得不再专注于业务需求。

改进:
启动一个订阅程序去订阅数据库的binlog,获得需要操作的数据
在应用程序中,另起一段程序(避免业务侵入),获得这个订阅程序传来的信息,进行删除缓存操作

方案二

更新数据库数据
数据库会将操作信息写入binlog日志当中
订阅程序提取出所需要的数据以及key
另起一段非业务代码,获得该信息
尝试删除缓存操作,发现删除失败
将这些信息发送至消息队列

在这里插入图片描述
重新从消息队列中获得该数据,重试操作订阅binlog程序在mysql中有现成的中间件叫canal
可以完成订阅binlog日志的功能

附录

MySQL的查询QPS主要取决于硬件性能以及应用的查询优化,通常在千到万的范围
但在特定的配置下可以达到几万到十几万。

通常来说,对于大多数应用场景而言,MySQL的QPS在2000-3000就已经比较高了。

过高的QPS可能会对服务器性能产生负面影响,如CPU和I/O压力过大。
因此,最佳的QPS应根据实际的硬件配置和应用需求来定。

通过对查询的优化,如合理的索引设计、合理的查询设计,也能够有效提高QPS
通过使用缓存、读写分离、分库分表等方式,也能显著提高系统的并发处理能力,从而提高QPS

词汇

写入失败重试直到成功,称之为:删除补偿

学习文档

https://mp.weixin.qq.com/s?__biz=Mzg5MjE0MjE3Mw==&mid=2247488095&idx=1&sn=c4f50e3dbfd381c3f9c6948b973f8063&chksm=cfc3c56df8b44c7be1a7284a0f6b9255274fb50e3cefcf98e7e6897b1df0f8080223012a312b#rd

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

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

相关文章

Windows下同一电脑配置多个Git公钥访问不同的账号

前言 产生这个问题的原因是我在Gitee码云上有两个账号,为了方便每次不用使用http模式推拉代码,于是我就使用了ssh的模式,起初呢我用两台电脑分别连接两个账号,用起来也相安无事,近段时时间台式机在家里,我在外地出差了,就想着把ssh公钥同时添加到不同的账号里,结果却发现不能用…

超网、IP 聚合、IP 汇总分别是什么?三者有啥区别和联系?

一、超网 超网(Supernet)是一种网络地址聚合技术,它可以将多个连续的网络地址合并成一个更大的网络地址,从而减少路由表的数量和大小。超网技术可以将多个相邻的网络地址归并成一个更大的网络地址,这个更大的网络地址…

Git使用教程:入门到精通

Git使用教程:入门到精通 一、Git安装根据需求选择电脑位数安装;20231023210945建议这里先新建一个文件夹如:D:/Git;专门来存放Git安装包和后续Git代码,方便管理; 二、Git使用前的配置需要先创建自己的Gitee…

贪心算法(蓝桥杯 C++ 题目 代表 注解)

介绍: 贪心算法(Greedy Algorithm)是一种在每一步选择中都采取当前状态下最好或最优(即最有利)的选择,从而希望最终能够得到全局最好或最优的结果的算法。它通常用来解决一些最优化问题,如最小生…

❤ Vue3项目搭建系统篇(二)

❤ Vue3项目搭建系统篇(二) 1、安装和配置 Element Plus(完整导入) yarn add element-plus --savemain.ts中引入: // 引入组件 import ElementPlus from element-plus import element-plus/dist/index.css const ap…

剑指offer经典题目整理(二)

一、斐波那契数列(fib) 1.链接 斐波那契数列_牛客题霸_牛客网 (nowcoder.com) 2.描述 斐波那契数列就是数列中任意一项数字,都会等于前两项之和,满足f(n) f(n-1) f(n-2) 的一个数列,例如:1 1 2 3 5 8…

VMware虚拟机安装Ubuntu kylin22.04系统教程(附截图详细步骤)

一、版本信息 虚拟机产品:VMware Workstation 17 Pro 虚拟机版本:17.0.0 build-20800274 ISO映像文件:ubuntukylin-22.04-pro-amd64.iso 二、安装步骤 打开虚拟机,点击创建新的虚拟机: 选择自定义: 硬…

HarmonyOS NEXT应用开发之MpChart图表实现案例

介绍 MpChart是一个包含各种类型图表的图表库,主要用于业务数据汇总,例如销售数据走势图,股价走势图等场景中使用,方便开发者快速实现图表UI。本示例主要介绍如何使用三方库MpChart实现柱状图UI效果。如堆叠数据类型显示&#xf…

嘉绩咨询:搭建品牌招商桥梁,提供卓越讲师与会议服务

当下,品牌成功的关键在于强大的渠道支撑和高效的招商能力,在这一背景下,嘉绩咨询,这一专注于渠道招商全案系统孵化的知名平台型企业,今日宣布,将进一步加强其在品牌招商桥梁搭建上的服务功能,通…

HTML 学习笔记——标签创建小技巧

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Emmrt工具</title></head><body>&…

【Linux】CentOS网络故障排查大揭秘: 实战攻略解读

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;Linux ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 检查网络连接状态&#xff1a; 检查网络配置&#xff1a; 重启网络服务&#xff1a; 检查防火墙设置&#xff1a; 查看日志文…

VBA技术资料MF128:批量创建文件夹及子文件夹

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套&#xff0c;分为初级、中级、高级三大部分&#xff0c;教程是对VBA的系统讲解&#…

基于SpringBoot+MYSQL的网页时装购物系统

目录 1、 前言介绍 2、主要技术 3、系统流程分析 3.1、系统登录流程图 3.2、添加信息流程图 3.3、删除信息流程图 4、系统体系结构 4.1、时装购物系统的结构图 4.2、登录系统结构图 4.3、时装购物系统结构图 5、数据库设计原则 5.1、管理员信息属性图 5.2、用户管…

2024038期传足14场胜负前瞻

2024038期售止时间为3月10日&#xff08;周日&#xff09;20点30分&#xff0c;敬请留意&#xff1a; 本期深盘多&#xff0c;1.5以下赔率3场&#xff0c;1.5-2.0赔率2场&#xff0c;其他场次是平半盘、平盘。本期14场整体难度中等偏上。以下为基础盘前瞻&#xff0c;大家可根据…

Day28:安全开发-JS应用原生开发JQuery库Ajax技术前端后端安全验证处理

目录 JS原生开发-文件上传-变量&对象&函数&事件 JS导入库开发-登录验证-JQuery库&Ajax技术 JS导入库开发-逻辑购买-JQuery库&Ajax技术 实例测试-某违规APP-密码找回&JS验证逻辑安全 思维导图 JS知识点&#xff1a; 功能&#xff1a;登录验证&…

c语言实现http协议服务器端和客户端

本代码参考https://blog.csdn.net/ymxyld/article/details/124812731思路&#xff0c;并添加了客户端代码。 代码各个函数注释写的非常详细&#xff0c;仅供学习参考&#xff0c;有任何疑问请留言。 服务器端 代码流程&#xff1a; #define SERVER_PORT 8080 //设置端口号 …

docker 使用官方镜像搭建 PHP 环境

一、所需环境&#xff1a; 1、PHP&#xff1a;7.4.33-fpm 的版本 2、Nginx&#xff1a;1.25.1 的版本 3、MySQL&#xff1a; 5.7 的版本 4、Redis&#xff1a;7.0 的版本 1.1、拉取官方的镜像 docker pull php:7.4.33-fpm docker pull nginx:1.25.1 docker pull mysql:5.7 do…

ChatGPT发不出消息?GPT发不出消息怎么办?

前言 今天发现&#xff0c;很多人的ChatGPT无法发送信息&#xff0c;我就登陆看一下自己的GPT的情况&#xff0c;结果还真的无法发送消息&#xff0c;ChatGPT 无法发送消息&#xff0c;但是能查看历史的对话&#xff0c;不过通过下面的方法解决了。 第一时间先打开官方的网站&a…

项目实战之跨语言调用api——结合语言优点解决实际问题

前情提要 在一个项目开发中需要后端解析并分析数据得出结果报告&#xff0c;一开始用的Java后端&#xff0c;后面一堆Json数据解析的实在头疼&#xff0c;于是捡起老胶水&#xff1a;Python 辅助开发作为后端的核心算法部分服务接口 Java&#xff1a;SpringBoot 结合 RestTemp…

【Linux】Linux——Centos7安装

目录 虚拟机安装【空壳子】安装VMware Workstation新建虚拟机硬件兼容性(直接下一步)稍后安装操作系统客户及操作系统选择Linux&#xff0c;版本Centos764位给虚拟机命名&#xff0c;并选择安装位置处理器配置&#xff08;默认即可&#xff0c;不够用后面可以调&#xff09;虚拟…