如何保障 MySQL 和 Redis 的数据一致性?
数据一致性问题是如何产生的?
数据一致性问题通常产生于数据在不同的时间点、地点或系统中存在多个副本的情况,
系统只存在一个副本的情况下也完全可能会产生。
设想一下,你在一家连锁咖啡店有一张会员卡这张会员卡可以绑定两个账号(假设是微信号),这张卡记录了你的积分。
你在北京的分店购买了一杯拿铁,积分增加了5分。就是这么巧,同一时间,你的好朋友在上海的分店也买了一杯拿铁,积分也增加了5分。
按理来说用这张卡买了两杯咖啡,系统上应该给你增加10分,但是,如果北京分店的系统更新到中央数据库的操作延迟了,
上海分店的系统可能还没有得到最新的积分信息。
这时,上海分店计算总积分的方式就是:原来的总积分 + 5分,北京的分店的计算方式也是:原来的总积分 + 5分,这张卡总的就加了5分,这就是一种数据一致性问题。
即使在单个系统内部,也可能存在类似的问题。
假设咖啡店的积分记录系统在进行维护,而你在这个时间点进行了消费。
如果维护操作和积分更新操作没有被正确的协调,可能会导致你的消费没有被记录到积分中,引发数据一致性问题。
在上面这个例子中,数据一致性问题是由于信息更新在不同地点之间同步不及时造成的,而在单个系统中,
可能是因为操作的顺序和同步机制没有设计得当导致一致性问题。
解决这类问题通常需要引入事务管理、分布式锁、队列、事件驱动的更新机制等策略来确保数据的准确性和实时性。
迪米特法则
在软件架构设计中,遵循的原则是尽量保持简洁和避免不必要的复杂性,
这个原则被称作 “最少知识原则” (Principle of Least Knowledge),也被称为 “迪米特法则” (Law of Demeter)。
当它和架构设计中的简约原则联系起来时,你可能指的是 “简单性原则” 或 “奥卡姆剃刀”(Occam’s Razor) 原则。
奥卡姆剃刀原则通常被解释为在没有明显差别的情况下,应该选择假设较少、假设简单的理论。
在软件架构的上下文中,这意味着在其他条件相同的情况下,应该选择更简单、组件更少的设计方案。
这样做的好处包括减少潜在的错误来源、降低系统的维护成本、提高系统的可理解性,并且有时还能提高性能。
每引入一个新组件,就增加了系统的复杂度和潜在的维护负担。因此,设计时应当权衡新组件带来的好处与其引入的复杂度之间的关系。
回到原本的问题
MySQL 和 Redis 的数据一致性问题是如何产生的?
MySQL 和 Redis 的数据一致性问题通常来源于它们在系统架构中扮演的不同角色和特性。
MySQL 是一个关系型数据库,通常用于存储持久化数据,而 Redis 是一个内存中的数据结构存储,常用作缓存和消息代理。
它们之间的数据一致性问题主要产生于下面几个方面:
-
数据更新时机:当数据在 MySQL 中被更新后,如果 Redis 中缓存的同一份数据没有被同时更新,就会出现不一致的情况。用户可能从缓存中获取到了旧的数据。
-
复制延迟:如果你使用 Redis 的复制功能来增强数据的可用性和冗余,可能会遇到主从复制延迟的问题。在高负载情况下,从节点上的数据可能会落后于主节点,导致数据一致性问题。
-
缓存穿透:如果请求的数据在 Redis 中没有找到,就会查询 MySQL 数据库。如果大量此类请求发生,而数据实际上并不存在于数据库中,这可能会导致数据库层面的性能问题,进而影响数据的读取和写入一致性。
-
缓存失效策略:当缓存因为达到了设定的时间限制或空间限制而被清除,如果数据更新策略没有得到很好的处理,那么当下一次读取时,就会从 MySQL 中读取到新的数据,而这段时间内,读取操作可能会得到不一致的结果。
-
事务处理:MySQL 支持事务处理,可以通过 ACID 属性(原子性、一致性、隔离性、持久性)来保证操作的准确性。而 Redis 对事务的支持是有限的,尽管它有一定的事务操作命令,但没有严格的 ACID 属性保证。
-
系统故障:系统崩溃或网络故障可能会导致正在同步的数据丢失或不完整,这也会引起数据一致性问题。
如何保障 MySQL 和 Redis 的数据一致性?
确保 MySQL 和 Redis 数据一致性可以通过以下几个更加详细的解决方案来实现:
1、先写数据库后写缓存:
首先更新 MySQL 数据库,确保数据持久化后,再更新 Redis 缓存。
这样即使缓存更新失败,应用也可以从数据库中读取最新数据,然后重试更新缓存。例如:
try {// 更新数据库updateDatabase(record);// 同步更新缓存updateCache(record);
} catch(Exception e) {// 如果缓存更新失败,可以记录日志并进行重试或者使用其他补偿机制log.error("Error updating cache", e);// 可以选择重新尝试更新缓存或者放入队列稍后处理retryUpdateCache(record);
}
![ ][nbsp]
2、事务消息:
使用本地事务配合事务消息中间件,比如 RocketMQ 的事务消息功能。
先发送预备消息,然后在本地事务中执行数据库操作,根据操作结果最后提交或回滚消息。
如果消息提交成功,则消费者监听到消息后更新 Redis 缓存。这样就能保证数据库操作和缓存更新的最终一致性。
3、缓存双删策略:
在更新数据库之前和之后都删除缓存,第一次删除是为了防止在更新数据库的过程时间窗口内有新的请求访问到旧的缓存数据,
第二次删除是为了处理在第一次删除之后到数据库更新期间产生的脏数据。
// 第一次删除缓存
deleteCache(key);// 更新数据库
updateDatabase(record);// 休眠一段时间,比如100ms,让前面的数据库操作和缓存删除操作完成
Thread.sleep(100);// 第二次删除缓存
deleteCache(key);
![ ][nbsp 1]
缓存双删策略为什么要删除两次?
缓存双删策略就是在更新数据库记录之前和之后都执行一次缓存删除操作。
这个策略的目的是为了尽可能减少数据库与缓存间数据不一致的时间窗口,解决缓存数据可能出现的脏读问题。具体的原因如下:
a、预防更新期间的脏读:
当更新数据库记录之前先删除缓存,目的是为了防止在数据库更新期间,如果有新的请求进来,这个请求会因为缓存不命中而去读取数据库中的最新数据,并将其写入到缓存中。
b、处理更新期间的写请求:
即使进行了第一次缓存删除操作,但在数据库更新完成之前,新的读请求可能已经带着旧的数据重新填充了缓存(这是因为删除缓存和更新数据库之间还是有一个很短的时间窗口)。因此,在数据库更新之后再次删除缓存,可以确保如果有旧数据被写入缓存,那么这些旧数据也会被清除。
c、确保数据一致性:
第二次删除操作是为了确保任何在两次删除操作中间由于旧数据写入缓存的情况得到处理。
这样即使发生了这种情况,缓存中的旧数据最终也会被清除,新的读请求会再次触发缓存的重建,这次则会从数据库加载最新的数据。
简单来说,缓存双删策略是一种实践中比较简单有效的方法,用于降低缓存数据不一致的风险。
然而,这种策略也不能完全保证缓存和数据库数据的强一致性,因为在高并发场景下仍然存在极小的窗口期可能会导致脏读。
因此,在一些对数据一致性要求极高的场景中,可能需要其他更复杂的数据同步机制。
![ ][nbsp 2]
4、发布/订阅模式:
在更新数据库后,发布一个事件到消息队列。有一个订阅了这个队列的缓存更新服务,它会监听这些事件,并且负责更新或者删除对应的缓存。
5、定时校对进程:
定期运行一个后台进程,该进程对数据库和缓存数据进行校对。如果发现不一致,将缓存数据更新为数据库中的最新状态。这种方法适用于对一致性要求不是非常实时的场景。
这些方法可以根据实际业务的需求和场景进行选择和调整,通常需要综合使用这些策略来达到较优的一致性保障。
在实践中,还需要对各种边界条件和异常情况进行详细的考虑,以确保系统的健壮性。
最后说一句(求关注,求赞,别白嫖我)
最近无意间获得一份阿里大佬写的刷题笔记和面经,一下子打通了我的任督二脉,进大厂原来没那么难。
这是大佬写的, 7701页的阿里大佬写的刷题笔记,让我offer拿到手软
求一键三连:点赞、分享、收藏
点赞对我真的非常重要!在线求赞,加个关注我会非常感激!@小郑说编程
[nbsp]: https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=http%3A%2F%2F%2Fwww.feiz.vip%2Fimages%2Ffenbushi%2FMySQL_Redis%2Fconsistency%2Ffirst_MySQL.png&pos_id=img-fdg0tjWU-1704726201602)
[nbsp 1]: https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=http%3A%2F%2F%2Fwww.feiz.vip%2Fimages%2Ffenbushi%2FMySQL_Redis%2Fconsistency%2Fdouble_del1.png&pos_id=img-xpIJro8b-1704726201892)
[nbsp 2]: https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=http%3A%2F%2F%2Fwww.feiz.vip%2Fimages%2Ffenbushi%2FMySQL_Redis%2Fconsistency%2Fdouble_del2.png&pos_id=img-bicyRUqp-1704726202539)
相关文章:
如何保障 MySQL 和 Redis 的数据一致性?
数据一致性问题是如何产生的? 数据一致性问题通常产生于数据在不同的时间点、地点或系统中存在多个副本的情况, 系统只存在一个副本的情况下也完全可能会产生。 设想一下,你在一家连锁咖啡店有一张会员卡这张会员卡可以绑定两个账号&#x…...
Leetcode 2999. Count the Number of Powerful Integers
Leetcode 2999. Count the Number of Powerful Integers 1. 解题思路2. 代码实现 题目链接:10034. Count the Number of Powerful Integers 1. 解题思路 这一题的话其实还是一个典型的求不大于 N N N的特殊数字个数的问题。 这道题本质上进行一下替换还是要求如…...
【Reading Notes】(2)
文章目录 FreestyleHip-hop dance and MusicProgrammerMaster Freestyle 都说人的成长有三个阶段,第一个阶段认为自己独一无二,天之骄子;第二个阶段发现自己原来如此渺小,如此普通,沮丧失望;第三阶段&#…...
【设计模式之美】SOLID 原则之一:怎么才算是单一原则、如何取舍单一原则
文章目录 一. 如何判断类的职责是否足够单一?二. 类的职责是否设计得越单一越好? 开始学习一些经典的设计原则,其中包括,SOLID、KISS、YAGNI、DRY、LOD 等。 本文主要学习单一职责原则的相关内容。 单一职责原则的定义:…...
# [NOIP2015 普及组] 扫雷游戏#洛谷
题目背景 NOIP2015 普及组 T2 题目描述 扫雷游戏是一款十分经典的单机小游戏。在 n n n 行 m m m 列的雷区中有一些格子含有地雷(称之为地雷格),其他格子不含地雷(称之为非地雷格)。玩家翻开一个非地雷格时&#…...
Unity中Shader的_Time精度问题
文章目录 前言一、U方向上优化二、V方向上优化在这里插入图片描述 三、最终代码1、效果2、Shader 前言 在Unity的Shader中,使用了_Time来达到UV的流动效果,普遍会出现一个问题。我们的UV值会随着时间一直增加(uv值增加了,但是因为…...
听GPT 讲Rust源代码--compiler(15)
File: rust/compiler/rustc_arena/src/lib.rs 在Rust源代码中,rustc_arena/src/lib.rs文件定义了TypedArena,ArenaChunk,DroplessArena和Arena结构体,以及一些与内存分配和容器操作相关的函数。 cold_path<F: FnOnce,drop,new,…...
关键字联合体union的定义和使用
联合体的定义 联合体的定义和结构体相同。 联合体成员共用存储空间,联合体占用的空间最大长度的数据成员的长度。 union State {char sleep;char run;int suspend;double error; }state_u;以上例子,State表示联合体的名字,它相当于声明了一…...
基于GA-PSO遗传粒子群混合优化算法的VRPTW问题求解matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 4.1 遗传算法(GA)基本原理 4.2 粒子群优化(PSO)基本原理 4.3 算法优化策略 5.完整程序 1.程序功能描述 VRPTW是车辆路径问题(VR…...
【leetcode100-033】【链表】排序链表
【题干】 给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。 【思路】 递归版归并法链表版~没什么特别好说的(非递归版归并也是可以哒,但是马上要考试了今天懒得写了!打个flag在这里也许哪天想起来…...
[Kubernetes]5. k8s集群StatefulSet详解,以及数据持久化(SC PV PVC)
前面通过deployment结合service来部署无状态的应用,下面来讲解通过satefulSet结合service来部署有状态的应用 一.StatefulSet详解 1.有状态和无状态区别 无状态: 无状态(stateless)、牲畜(cattle)、无名(nameless)、可丢弃(disposable) 有状态: 有状态(stateful)、宠物(pet)…...
数据库系统-甘晴void学习笔记
数据库系统笔记 计科210X 甘晴void 202108010XXX 教材:《数据库系统概论》第6版 (图片来源于网络,侵删) 文章目录 数据库系统<br>笔记第一篇 基础篇1 绪论1.1数据库系统概述1.2数据模型1.3数据库系统的结构(三级模式结构…...
Azure Machine Learning - 人脸识别任务概述与技术实战
Azure AI 人脸服务提供了可检测、识别和分析图像中的人脸的 AI 算法。 人脸识别软件在许多不同情形中都十分重要,例如识别、无接触访问控制和实现隐私的人脸模糊。你可以通过客户端库 SDK,或者直接调用 REST API 使用人脸服务。 目录 一、人脸识别服务场…...
强化学习的数学原理学习笔记 - 蒙特卡洛方法(Monte Carlo)
文章目录 概览:RL方法分类蒙特卡洛方法(Monte Carlo,MC)MC BasicMC Exploring Starts🟦MC ε-Greedy 本系列文章介绍强化学习基础知识与经典算法原理,大部分内容来自西湖大学赵世钰老师的强化学习的数学原理…...
DDIA 第十一章:流处理
本文是《数据密集型应用系统设计》(DDIA)的读书笔记,一共十二章,我已经全部阅读并且整理完毕。 采用一问一答的形式,并且用列表形式整理了原文。 笔记的内容大概是原文的 1/5 ~ 1/3,所以你如果没有很多时间…...
webpack知识点总结(高级应用篇)
除开公共基础配置之外,我们意识到两点: 1. 开发环境(modedevelopment),追求强大的开发功能和效率,配置各种方便开 发的功能;2. 生产环境(modeproduction),追求更小更轻量的bundle(即打包产物); 而所谓高级应用,实际上就是进行 Webpack 优化…...
均匀与准均匀 B样条算法
B 样条曲线的定义 p ( t ) ∑ i 0 n P i F i , k ( t ) p(t) \sum_{i0}{n} P_i F_{i, k}(t) p(t)i0∑nPiFi,k(t) 方程中 n 1 n1 n1 个控制点, P i P_i Pi, i 0 , 1 , ⋯ n i0, 1, \cdots n i0,1,⋯n 要用到 n 1 n1 n1 个 k k k 次 B 样条基函数 …...
2023年12 月电子学会Python等级考试试卷(一级)答案解析
青少年软件编程(Python)等级考试试卷(一级) 分数:100 题数:37 一、单选题(共25题,共50分) 1. 下列程序运行的结果是?( ) print(hello) print(world) A. helloworld...
启发式算法解决TSP、0/1背包和电路板问题
1. Las Vegas 题目 设计一个 Las Vegas 随机算法,求解电路板布线问题。将该算法与分支限界算法结合,观察求解效率。 代码 python代码如下: # -*- coding: utf-8 -*- """ Date : 2024/1/4 Time : 16:21 Author : …...
阿里云新用户的定义与权益
随着云计算的普及,阿里云作为国内领先的云计算服务提供商,吸引了越来越多的用户。对于新用户来说,了解阿里云新用户的定义和相关权益非常重要,因为它关系到用户能否享受到更多的优惠和服务。 一、阿里云新用户的定义 阿里云新用户…...
go语言多线程操作
目录 引言 一、如何实现多线程 1. 线程的创建与管理: 2. 共享资源与同步: 3. 线程间通信: 4. 线程的生命周期管理: 5. 线程安全: 6. 考虑并发问题: 7. 性能与资源利用: 8. 特定语言或框架的工具和库: 二、go语言多线程 Goroutine 1. 轻量级: 2. 动态栈: 3. 调度:…...
GreatSQL社区2023全年技术文章总结
GreatSQL社区自成立以来一直致力于为广大的数据库爱好者提供一个交流与学习的平台。在2023年,我们见证了社区的蓬勃发展,见证了众多技术文章的诞生与分享。 此篇总结呈现GreatSQL社区2023年社区技术文章在CSDN发布的全部。这些文章涵盖了GreatSQL、MGR、…...
【论文阅读笔记】Stable View Synthesis 和 Enhanced Stable View Synthesis
目录 Stable View Synthesis摘要引言 Enhanced Stable View Synthesis 从Mip-NeRF360的对比实验中找到的两篇文献,使用了卷积神经网络进行渲染和新视角合成,特此记录一下 ToDo Stable View Synthesis paper:https://readpaper.com/pdf-ann…...
网络报文分析程序的设计与实现(2024)
1.题目描述 在上一题的基础上,参照教材中各层报文的头部结构,结合使用 wireshark 软件(下载地址 https://www.wireshark.org/download.html#releases)观察网络各层报文捕获,解析和分析的过程(如下 图所示&a…...
贯穿设计模式-享元模式思考
写享元模式的时候,会想使用ConcurrentHashMap来保证并发,没有使用双重锁会不会有问题?但是在synchronize代码块里面需要尽量避免throw异常,希望有经验的同学能够给出解答? 1月6号补充:没有使用双重锁会有问…...
牛客刷题:BC45 小乐乐改数字(中等)
自我介绍:一个脑子不好的大一学生,c语言接触还没到半年,若涉及到效率等问题,各位都可以在评论区提出见解,谢谢啦。 该账号介绍:此帐号会发布游戏(目前还只会简单小游戏),…...
设计模式学习2
代理模式:Proxy 动机 “增加一层间接层”是软件系统中对许多复杂问题的一种常见解决方案。在面向对象系统中,直接食用某些对象会带来很多问题,作为间接层的proxy对象便是解决这一问题的常见手段。 2.伪代码: class ISubject{ pu…...
Rust:如何判断位置结构的JSON串的成员的数据类型
如何判断位置结构的JSON串的成员的数据类型,给一个Rust的例子,其中包含对数组的判断? 在Rust中,你可以使用serde_json库来处理JSON数据,并通过serde_json::Value类型的方法来判断JSON串中成员的数据类型。以下是一个示…...
Kafka(五)生产者
目录 Kafka生产者1 配置生产者bootstrap.serverskey.serializervalue.serializerclient.id""acksallbuffer.memory33554432(32MB)compression.typenonebatch.size16384(16KB)max.in.flight.requests.per.connection5max.request.size1048576(1MB)receive.buffer.byte…...
【Leetcode】242.有效的字母异位词
一、题目 1、题目描述 给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。 注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。 示例1: 输入: s = "anagram", t = "nagaram" 输出: true示例2: 输入: …...
给网站做备案/搜索引擎seo是什么
1、下载源码包curl -O https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.2.1.tgz2、解压 放到 /usr/local/ 目录下tar -zxvf mongodb-linux-x86_64-rhel70-4.2.1.tgzmv mongodb-linux-x86_64-rhel70-4.2.1/ /usr/local/mongodb43、切换目录cd /usr/local/mongo…...
做微信公众号必备的网站/如何建立独立网站
直接上代码。自己下载吧。 代码下载转载于:https://www.cnblogs.com/puzi0315/archive/2012/05/28/2521485.html...
ui做的好的网站/企业培训课程名称
前言 写在前面,我最近状态一直都不是很好,每天到了公司不知道该做什么,因为一直想着多久能回去,多久能做什么这些事情,所以真的就是干什么都心不在焉,但是来北京的这28天,我其实也是很有收获的…...
三五互联网站管理登录地址是多少/东莞有限公司seo
配置druid时,要把druid.propertites文件放到resources文件夹中 不然就会报“instream parameter is null”...
做动态网站有哪些技术路线/长沙seo顾问
ASP.NET MVC小论 2008-12-04 11:11 by T2噬菌体, 8052 visits, 网摘, 收藏, 编辑 摘要:ASP.NET MVC作为微软官方的.NET平台下MVC解决方案,自诞生起就吸引了众多.NET平台开发人员的眼球。在经历了漫长Preview后,上个月微软终于发布了其beta版。…...
网站如何后台管理/有域名后如何建网站
随着工作的深入,越发发现需要系统的重新梳理Oracle SQL相关知识,这里新开篇幅,力求做到言简意赅。 1.SQL简介 SQL:Structured Query Language,结构化查询语句。 结构化查询语句,有时也被称为第四代语言。…...