拨云见日:Redis和数据库之间的一致性如何保证?

news2024/12/24 22:17:27

概  述

Redis在使用过程中,有四个异常问题:缓存穿透、缓存击穿、缓存雪崩、以及缓存和数据库(MySQL)双写一致性问题。

前三个问题可能会因为业务体量的不同而有所不同,但是最后一个问题是无法避免的。就算你的电商业务规模不大,缓存中的价格或库存信息和数据库不一致也会给公司带来巨大的损失。所以,这个问题也成为了面试中的必考问题。

那么,你是如何解决Redis和MySQL双写数据不一致问题的呢?或者说,你是如何保证他们之间的一致性呢?

问题背景

回答一个问题,首先要明白它是为什么产生的。

如果没有引入 Redis 技术,我们单纯往 MySQl 中写入数据(单实例)会有一致性问题吗?当然不会。

MySQL 的 InnoDB 引擎的事务特性已经保证了这点,我们不做赘述。

因为我们引入Redis后的读取流程是这样的:如果缓存存在,直接读取;如果缓存不存在,直接读取数据库数据,然后更新到缓存中。所以就产生了这样的一致性场景:

  1. 缓存中有数据,和 MySQL 中的数据保持一致。

  2. 缓存中没有数据,MySQL 存储的是最新数据。

对于第一种情况,我们需要保证 MySQL 和 Redis 数据是一样的;对于第二种情况,我们需要保证数据用适当的方式更新到缓存中。MySQL 和 Redis 之间并没有事务这种强约束去保证以上两点,当任意情况被打破的时候就是数据不一致。

在缓存的使用上又分为读写缓存和读缓存:

  • 读写缓存:除了读场景,会直接修改缓存中的数据,它又分为同步直写和异步写回。同步直写会同步直接修改缓存数据和数据库;异步写回会在缓存淘汰时候写回数据库。这种方案出现不一致的概率更高,并且用于大量读写场景,这里不考虑。

  • 读缓存:不会直接修改缓存内容。修改数据库时直接作废缓存,缓存中不存在会读取数据库值然后设置到缓存中。这种适合读多写少的场景,我们主要讨论这种方案。

先给出结论:其实从技术上来说,我们几乎无法保证Redis 和数据库的严格一致,所有的方案都是尽可能降低不一致的可能性和不一致时间。

1.先删除缓存再更新数据库

如果先删除缓存,再更新数据库,有可能出现如下情况:

  1. 线程 1 删除缓存,准备更新数据库。

  2. 线程2开始读取数据,发现缓存没有,就读取数据库中数据。由于读比写快很多,这时候大概率线程1还没有完成更新。

  3. 线程2把旧数据更新到 Redis 中,这时候线程1完成数据库更改。数据不一致出现。

既然先删除可能出现这样的问题,那我过一会再删一次不就好了嘛。

 

2.缓存延时双删

比起上一个方案,我们多加了一次删除,但是这也有缺点。

这个sleep时间怎么确定呢?sleep时间要大于线程2读取并且设置缓存的时间,设置的太小有可能无法在设置后删除;设置的太大又影响系统的吞吐量。

3.先更新数据库再删缓存

 

能不能第一次不删除,只是第二次删除呢?先更新数据库,再删除缓存。这样线程2就可以在线程1提交数据前一直读取旧数据,只有线程1更新后才会去数据库读新值。它似乎完美的解决了这个问题。

但是有一种极端情况。

  1. 线程1更新数据库,但是还没有提交事务。然后删除缓存,等事务提交后才完成数据修改。

  2. 但是在事务最终提交和删除缓存这个间隙中,发生了线程二读取缓存发现不存在,并且设置数据库旧值这个过程。

  3. 这样在线程1最终提交数据后,又发生了数据库和缓存不一致问题。

但是这个概率多大呢?非常非常小。一个commit操作的间隙显然非常短,只需要一次网络链接的过程。但是依旧存在这种可能。

针对这个问题还可以这么解决:在删除缓存的时候设置一个锁并且加一个很短的过期时间,作为lua脚本原子的去操作。如果有线程发现缓存不存在,就去阻塞等待或者返回查询失败。等数据库事务提交成功后删除锁。当然这种方案会造成吞吐量的降低或者接口短暂不可用。

如果把线程1事务提交的时机提交到删除缓存前呢?

 

这样流程会看起来简单很多。在线程1数据库修改后,到删除redis前这段短暂的时间内线程2会读取到旧数据,但是终究会被线程1删除。这种方案的不一致时间和成本显然最低。

但是,如果最后一步删除缓存失败怎么办呢?那缓存中永远是旧数据了。

 

4.消息队列重试删除

无论是第二种还是第三种方案,都有可能出现缓存删除失败的情况,可以在最后删除缓存的时候利用消息队列增加重试机制,保证最终一致。

  1. 更新数据库。

  2. 删除缓存,并且发送一条MQ消息。

  3. 收到MQ,删除成功。否则不断重试。

这种方案有可能会造成业务入侵的问题。但是我觉得还好,你可以将删除逻辑封装一下,将删除和发送MQ写到一起,消费MQ也做成通用的删除功能。

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

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

相关文章

OPNET出现错误的解决办法汇总

文章目录 Packet pointer references unowned packet(<pk_id>) 错误Standard function stack imbalance 错误Invalid Memory Access 错误 在使用 OPNET Modeler 软件时&#xff0c;会遇到很多奇奇怪怪的报错&#xff0c;这篇文章收集的是自己在使用该软件时遇到的一些错误…

易基因:组学研究揭示不同牛品种的DNA甲基化、染色质和基因表达互作机制|科研进展

大家好&#xff0c;这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。 在全球范围内&#xff0c;牛为60多亿人提供了重要的营养来源。传染病是养牛生产的主要限制因素&#xff0c;且许多疾病人畜共患&#xff0c;因此与人类健康直接相关。近年来牛的许多复杂…

CBTC信号系统ATP子系统接口

ATP/ATO车载设备与车辆接口要求 ATP/ATO车载设备应实现与车辆制动装置的可靠接口&#xff0c;保证安全和对列车实施连续有效的控制。 ATP/ATO车载设备与车辆的接口分为开关量、模拟量、通信接口三种。 涉及行车安全的电气接口应采用安全输入&#xff0f;输出接口方式。 ATP…

electron 快速创建一个本地应用

参考官方文档流程 快速入门 | Electron 建议先全局安装electron&#xff0c;npm install -g electron 开发过程中可以在本地开发安装 使用electron快速创建一个web页面 &#xff0c;参考官方demo 实例 electron-quick-start 第一步&#xff1a; mkdir my-electron-app &am…

银行信用卡流失预测模型_基于ANN神经网络_金融培训_论文科研_毕业设计

业务背景 根据央行公布的数据显示&#xff0c;全国性银行信用卡和借贷合一卡的发卡量增速从2017年同比增速26.35%的高点逐年下降&#xff0c;截至2020年同比增速降至4.26%。银行信用卡发卡增速明显放缓的背景下&#xff0c;预防老客户流失的问题变得愈发重要。 假设一家消费信…

前端开发中有哪些鲜为人知的技巧?

下面分享一些前端开发鲜为人知的HTML/CSS/JS技巧&#xff0c;希望大家可以有所收获。 一、Datalist元素 不知道为什么&#xff0c;这个元素不太被人所使用。<datalist>标签被用于为<input>元素提供一个“自动补全”的功能。 例如&#xff1a; <input list&qu…

MMPose安装记录

参考&#xff1a;GitHub - open-mmlab/mmpose: OpenMMLab Pose Estimation Toolbox and Benchmark. 一、依赖环境 MMPose 适用于 Linux、Windows 和 macOS。它需要 Python 3.7、CUDA 9.2 和 PyTorch 1.6。我的环境&#xff1a; Windows 11 Python 3.9 CUDA 11.6 PyTorch 1.13 …

影响客户管理系统的因素有哪些?能买断吗?

客户管理系统是企业数字化转型的必由之路&#xff0c;对于没有部署CRM客户管理系统的企业来说除了关注软件功能还要关注价格&#xff0c;客户管理软件系统多少钱&#xff1f;是否需要买断&#xff0c;今天我们就来说一说。 一、什么是客户管理系统 客户管理系统是帮助企业建立…

经典基于外观的SLAM框架-RTABMAP(RGBD视觉输入方案)

经典基于外观的SLAM框架-RTABMAP 文章目录 经典基于外观的SLAM框架-RTABMAP1. RTABMAP整体框架2.RTABMAP的内存管理机制3. 视觉里程计4. 局部地图5. 回环检测与图优化6. 代码工程实践 1. RTABMAP整体框架 RTABMAP是采用优化算法的方式求解SLAM问题的SLAM框架&#xff0c;本赛题…

Linux---虚拟机配置固定IP

1. IP地址 每一台联网的电脑都会有一个地址&#xff0c;用于和其它计算机进行通讯 IP地址主要有2个版本&#xff0c;V4版本和V6版本&#xff08;V6很少用&#xff0c;课程暂不涉及&#xff09; IPv4版本的地址格式是&#xff1a;a.b.c.d&#xff0c;其中abcd表示0~255的数字…

深度学习应用篇-元学习[15]:基于度量的元学习:SNAIL、RN、PN、MN

【深度学习入门到进阶】必看系列&#xff0c;含激活函数、优化策略、损失函数、模型调优、归一化算法、卷积模型、序列模型、预训练模型、对抗神经网络等 专栏详细介绍&#xff1a;【深度学习入门到进阶】必看系列&#xff0c;含激活函数、优化策略、损失函数、模型调优、归一化…

免费的Outlook邮箱备份的方法!

关于Outlook邮箱备份 Outlook是Microsoft Office微软办公软件套装的组件之一&#xff0c;利用一套Microsoft应用程序和服务&#xff0c;与Office工具共享与协作&#xff0c;和各种设备时刻保持联系。用户可以通过登录邮箱首页申请Outlook为域名后缀的邮箱。 长时间使用Outl…

使用海外社交媒体的九种方法(和五个专业提示!)

社交媒体是推广您的产品、吸引新客户以及围绕您的业务建立社区的有效方式。您可以使用社交媒体做的事情几乎没有限制&#xff0c;但无限的可能性会带来让自己过于分散的风险。好消息是&#xff0c;通过遵循一些最佳实践&#xff0c;您的在线商店可以取得成功。 目录 使用…

3ds MAX 灯光

简单展示一下3dsMAX中灯光的不同效果&#xff1a; 先简单画一个房间出来&#xff0c;展示效果就不添加材质了 在选项卡中添加灯光&#xff1a; 首先是直接渲染的结果&#xff0c;没有添加光照&#xff0c;可以看出也没有阴影等 采用【目标聚光灯】&#xff0c;这有点类似在摄…

【MySQL新手入门系列二】:手把手教你入门MySQL - 数据库及数据表操作

如果您是一位刚刚开始学习MySQL的新手&#xff0c;本文将为您提供一些实用的入门知识和技巧&#xff0c;帮助您快速上手。 【MySQL新手入门系列一】&#xff1a;手把手教你入门MySQL 前面我们已经大致讲了一下mysql的安装等介绍&#xff0c;本篇文章将以windows为例&#xff0c…

聚类分析(文末送书)

目录 聚类分析是什么 一、 定义和数据类型 聚类应用 聚类分析方法的性能指标 聚类分析中常用数据结构有数据矩阵和相异度矩阵 聚类分析方法分类 二、K-means聚类算法 划分聚类方法对数据集进行聚类时包含三个要点 K-Means算法流程: K-means聚类算法的特点 三、k-med…

【JVM系列】垃圾收集器介绍

文章目录 垃圾收集器Serial收集器ParNew收集器Parallel收集器CMS收集器G1收集器 常用的收集器组合 垃圾收集器 Serial收集器 串行收集器是最古老&#xff0c;最稳定以及效率高的收集器&#xff0c;可能会产生较长的停顿&#xff0c;只使用一个线程去回收。新生代、老年代使用…

不逆向解决5s盾之cloudscraper

一、背景 经常写爬虫的同学&#xff0c;肯定知道 Cloud Flare 的五秒盾。当你没有使用正常的浏览器访问网站的时候&#xff0c;它会返回如下这段文字&#xff1a; Checking your browser before accessing xxx. This process is automatic. Your browser will redirect to your…

020+limou+C语言内存管理

0.在Linux下验证C语言地址空间排布 这里是limou3434的博文系列。接下来&#xff0c;我会带您了解在C语言程序视角下的内存分布&#xff0c;会涉及到一点操作系统的知识&#xff0c;但是不多&#xff0c;您无需担忧。 注意&#xff1a;只能在Linux下验证&#xff0c;因为Windo…

外观模式(十三)

每天都是全新的一天&#xff0c;感谢今日努力的自己。 上一章简单介绍了组合模式(十二), 如果没有看过, 请观看上一章 一. 外观模式 引用 菜鸟教程里面的外观模式介绍: https://www.runoob.com/design-pattern/facade-pattern.html 外观模式&#xff08;Facade Pattern&…