Redis---缓存双写一致性

news2024/11/26 13:47:15

目录

一、什么是缓存双写一致性呢?

 1.1 双检加锁机制

 二、数据库和缓存一致性的更新策略

2.1、先更新数据库,后更新缓存

 2.2 、先更新缓存,后更新数据库

 2.3、先删除缓存,在更新数据库

延时双删的策略:

 2.4.先更新数据库,在删除缓存(常用)

2.5、实际中是不可能做到强一致性的,那么怎么做到最终一致性呢?

三、canal中间件

3.1   canal工作原理

3.2 MySQL的主从复制 


一、什么是缓存双写一致性呢?

  • 如果redis中有数据

    • 需要和数据库中的值相同
  • 如果redis中无数据

    • 数据库中的值是最新值,且准备回写redis

缓存按照操作分

  • 只读缓存    (就没有同步这一说法了)
  • 读写缓存
    • 同步直写策略   (比如比较紧急的事情,冲了vip得立即生效
      • 写数据库后也同步写 redis 缓存,缓存中的数据和数据库中的一致
      • 对于读写缓存来说,要想保证缓存和数据库中的数据一致
  • 异步缓写策略   (一般都是用这种)
    • 正常业务运行中,mysql数据变动了,但是可以在业务上容许出现一定时间后才作用于redis,比如仓库、物流系统
    • 异常情况出现了,不得不将失败的动作重新修补,有可能需要借助kafka或者RabbitMQ等消息中间件,实现重写重试

 1.1 双检加锁机制

加锁前从redis中查一次,加锁后再查一次。

多个线程同时去查询数据库的这条数据,那么我们可以在第一个查询数据的请求上使用一个 互斥锁来锁住它

其他的线程走到这一步拿不到锁就等着,等第一个线程查询到了数据,然后做缓存。

后面的线程进来发现已经有缓存了,就直接走缓存。 

 二、数据库和缓存一致性的更新策略

一般都是以MySQL为准。

给缓存设置过期时间,定期清理缓存并回写,是保证最终一致性的解决方案。

我们可以对存入缓存的数据设置过期时间,所有的写操作以数据库为准,对缓存操作只是尽最大努力即可。也就是说如果数据库写成功,缓存更新失败,那么只要到达过期时间,则后面的读请求自然会从数据库中读取新值然后回填缓存,达到一致性,切记,要以mysql的数据库写入库为准

2.1、先更新数据库,后更新缓存

异常一:        回写失败会出现脏数据

 异常二:       高并发下会出现数据覆盖

 2.2 、先更新缓存,后更新数据库

我们一般是不用这种的,因为我们一般都把MySQL作为根基

异常:       高并发下会出现数据覆盖

 2.3、先删除缓存,在更新数据库

当有两个线程:一个线程负责删Redis,修改MySQL,  另一个来查找redis

 如果数据库更新失败或者不及时就会发生异常

(1)请求A进行写操作,删除redis缓存后,工作正在进行中,更新mysql......A还没有彻底更新完mysql,还没commit

(2)请求B开工查询,查询redis发现缓存不存在(被A从redis中删除了)

(3)请求B继续,去数据库查询得到了mysql中的旧值(A还没有更新完)

(4)请求B将旧值回写redis缓存

(5)请求A将新值写入mysql数据库 

上述情况就会导致不一致的情形出现。 

时间
线程A
线程B
出现的问题
t1
请求A进行写操作,删除缓存成功后,工作正在mysql进行中......
t2
1 缓存中读取不到,立刻读mysql,由于A还没有对mysql更新完,读到的是旧值
2 还把从mysql读取的旧值,写回了redis
1 A还没有更新完mysql,导致B读到了旧值
2 线程B遵守回写机制,把旧值写回redis,导致其它请求读取的还是旧值,A白干了。
t3
A更新完mysql数据库的值,over
redis是被B写回的旧值,
mysql是被A更新的新值。
出现了,数据不一致问题。

总结一下:

先删除缓存,再更新数据库
如果数据库更新失败或超时或返回不及时,导致B线程请求访问缓存时发现redis里面没数据,缓存缺失,B再去读取mysql时, 从数据库中读取到旧值,还写回redis,导致A白干了,o(╥﹏╥)o

改怎么解决呢?

延时双删的策略:

 这个删除该休眠多久呢?

 因为这种同步淘汰机制加上了sleep,导致MySQL吞吐量降低怎么办?

 

 2.4.先更新数据库,在删除缓存(常用)

 这一种方法的弊端相对比较少

时间
线程A
线程B
出现的问题
t1
更新数据库中的值......
t2
 缓存中立刻命中,此时B读取的是缓存旧值。
A还没有来得及删除缓存的值,导致B缓存命中读到旧值。
t3
更新缓存的数据,over
先更新数据库,再删除缓存
假如缓存删除失败或者来不及,导致请求再次访问redis时缓存命中, 读取到的是缓存旧值。

2.5、实际中是不可能做到强一致性的,那么怎么做到最终一致性呢?

需要用到消息队列:kafka或者RabbitMQ

但是还是都需要是先更新数据库,再删除缓存,这样最多也就是数据暂时不一致,不会导致雪崩、击穿啥的出现。

1 可以把要删除的缓存值或者是要更新的数据库值暂存到消息队列中(例如使用Kafka/RabbitMQ等)。
2 当程序没有能够成功地删除缓存值或者是更新数据库值时,可以从消息队列中重新读取这些值,然后再次进行删除或更新。
3 如果能够成功地删除或更新,我们就要把这些值从消息队列中去除,以免重复操作,此时,我们也可以保证数据库和缓存的数据一致了,否则还需要再次进行重试
4 如果重试超过的一定次数后还是没有成功,我们就需要向业务层发送报错信息了,通知运维人员。

三、canal中间件

能够立刻感知到MySQL改变的有一个MySQL的binlog文件

我们需要一种技术来充当两者之前的吹哨人

这里有阿里研发的一种中间件canal

3.1   canal工作原理

1. canal 模仿MySQL的dump协议,假装自己是MySQL的slave,向MySQL发送dump协议

2. MySQLmaster收到dump请求之后,便会给canal推送自身bin  log 变化给canal

3. cannal收到bin  log 消息并解析。

3.2 MySQL的主从复制 

 

MySQL的主从复制将经过如下步骤:

1、当 master 主服务器上的数据发生改变时,则将其改变写入二进制事件日志文件中;

2、salve 从服务器会在一定时间间隔内对 master 主服务器上的二进制日志进行探测,探测其是否发生过改变,

如果探测到 master 主服务器的二进制事件日志发生了改变,则开始一个 I/O Thread 请求 master 二进制事件日志;

3、同时 master 主服务器为每个 I/O Thread 启动一个dump  Thread,用于向其发送二进制事件日志;

4、slave 从服务器将接收到的二进制事件日志保存至自己本地的中继日志文件中;

5、salve 从服务器将启动 SQL Thread 从中继日志中读取二进制日志,在本地重放,使得其数据和主服务器保持一致;

6、最后 I/O Thread 和 SQL Thread 将进入睡眠状态,等待下一次被唤醒;

 

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

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

相关文章

手把手一起完成Python上位机与下位机USB通信

前言 最近在使用Python设计上位机,下位机是ZYNQ7000,两者通过USB进行数据传输。该文章是USB通信过程的踩坑记录 一、安装所需库 首先,安装pyusb和libusb两个库,命令如下: pip install pyusbpip install libusb如图…

CUDA笔记2

1.硬件理解 1.1对应 1.2 不一定是同时执行 例如只有13个sm,每个sm有128个core,而我们创建了1百万个threads,就要同步执行 因此&#xff0c;我们倾向于在block的x维设置为32的倍数,防止浪费warp warp id打印 #include <stdio.h> #include <stdlib.h>#include &qu…

Acwing 849. Dijkstra求最短路 I

Acwing 849. Dijkstra求最短路 I 链接:849. Dijkstra求最短路 I - AcWing题库 /*题解:dijkstra算法模板对于单源最短路径dijkstra1.每次找到当前距离源最近的节点 作为确定距离的点2.通过这个点看能否让其他的节点来松弛其他点到源的距离重复12操作*/ #include<algorithm&g…

完美解决win10系统cmd命令无法使用ssh

最近我在远程访问服务器的时候&#xff0c;在winR运行cmd的时候&#xff0c;输入ssh来获得本地和服务器映射&#xff0c;无法实现。提示&#xff1a;’SSH’ 不是内部或外部命令&#xff0c;也不是可运行的程序 或批处理文件。 下面的方法可以完美解决这个问题&#xff1a; 目…

四大运营商的优缺点,你的选择是对的吗?

随着2022年中国广电获得基础运营商服务牌照&#xff0c;中国从三大运营商变成了四大运营商&#xff1a;中国移动&#xff0c;中国联通&#xff0c;中国电信&#xff0c;中国广电。这四大运营商到底都有什么优缺点呢&#xff1f;大家一直在用的运营商手机卡&#xff0c;大家了解…

REE刷TLB时会把安全的TLB刷掉吗

思考: REE刷TLB时会把安全的TLB刷掉吗? TEE刷TLB时能否刷安全的TLB?例如页表管理着的共享内存,它的翻译缓存到了TLB. 首先,纠正一下用词,这里的"刷",来自某些操作系统中的"flush",在TLB底层的操作指令中,是没有flush或clean的,关于TLB的操作指令…

基于linux下的高并发服务器开发(第一章)- 静态库的使用1.5

1、创建lesson05文件夹&#xff0c;mkdir lesson05,然后创建子文件夹calc和library 在calc文件夹下有文件add.c&#xff0c;div.c&#xff0c;mult.c &#xff0c; sub.c &#xff0c;head.h&#xff0c;main.c在library文件夹下有文件夹include&#xff0c;lib&#xff0c;sr…

目标跟踪基础:数据关联算法

本文来自公众号“AI大道理” —————— 数据关联是多目标跟踪任务中的关键步骤&#xff0c;其目的主要是为了进行帧与帧之间的多个目标的匹配。 1、数据关联 数据关联其实就是一个沿着时间轴&#xff0c;将来自同一个物体的不同时刻的信号串联起来的过程。 数据关联通常在…

探索基于300W-LP的3D人脸关键点检测

目录 前言一、&#xff13;D 关键点可视化二、使用步骤1.300W-LP转为YOLO数据格式2.修改数据入口3.开始训练 总结 前言 300WLP数据集提供来丰富的人脸线索&#xff0c;包括&#xff12;D或&#xff13;D的关键点信息&#xff0c;Head Angle和&#xff13;DMM的参数等&#xff…

【岗位】IT行业岗位知识图谱--大数据工程师、机器学习、嵌入式、架构师

目录 1. 大数据工程师技能图谱2. 机器学习技能图谱3. 架构师技能图谱4. 嵌入式开发必备技能5. 嵌入式体系结构 1. 大数据工程师技能图谱 2. 机器学习技能图谱 3. 架构师技能图谱 4. 嵌入式开发必备技能 5. 嵌入式体系结构 **点赞、关注、评论、收藏哦**

7.7.8clip/简单量化

一、 clip函数&#xff1a;限制一个array的上下界 给定一个范围[min, max]&#xff0c;数组中值不在这个范围内的&#xff0c;会被限定为这个范围的边界。如给定范围[0, 1]&#xff0c;数组中元素值小于0的&#xff0c;值会变为0&#xff0c;数组中元素值大于1的&#xff0c;要…

【云存储】主流分布式文件系统介绍

目录 1、引言 2、云存储与分布式文件系统 2.1、云存储 2.2、分布式文件系统 3、Google的三大云计算与云存储论文 3.1、The Google File System&#xff08;谷歌文件系统&#xff09; 3.2、MapReduce&#xff1a;Simplified Data Processing on Large Clusters&#xff0…

云原生之深入解析Kubernetes CNI插件的选型和应用场景

一、常见网络插件 在学习容器网络的时候&#xff0c;肯定都听说过 Docker 的 bridge 网络、Vethpair、VxLAN 等术语&#xff0c;从 Docker 到 Kubernetes 后&#xff0c;学习 Flannel、Calico 等主流网络插件&#xff0c;分别代表了 Overlay 和 Underlay 的两种网络传输模式&a…

【VirtualBox】安装 VirtualBox 提示 needsthe Microsoft Visual C++ 2019

概述 一个好的文章能够帮助开发者完成更便捷、更快速的开发。书山有路勤为径&#xff0c;学海无涯苦作舟。我是秋知叶i、期望每一个阅读了我的文章的开发者都能够有所成长。 一、开发环境 开发环境&#xff1a;windows10虚拟机&#xff1a;VirtualBox 7.0.8 二、报错 ubun…

多条件见多值查询的 Excel 公式和 python 函数

问题 Python草堂 群的一位群友问&#xff1a;excel 数据表&#xff0c;用 vlookup 函数怎样实现多条件查询多值&#xff0c;多值排到一行上。如下图所示&#xff1a; 左边是数据清单&#xff0c;希望根据两个条件&#xff1a;产品、日期&#xff0c;查询数量&#xff0c;列到…

Element-UI el-table属性row-class-name用法

文章目录 前言官方示例自定义条件样式设置背景颜色样式stripe属性 设置背景颜色样式设置字体颜色总结 前言 可以通过指定 Table 组件的 row-class-name 属性来为 Table 中的某一行添加 class&#xff0c;表明该行处于某种状态。 官方示例 代码如下&#xff1a; <el-table…

体验版小程序为何无法访问云端服务器后端接口(请求失败...(已完美解决附加图片))?

文章目录 前言解决方案一解决方案二第一步第二步 前言 体验版小程序访问不到后端&#xff0c;接口请求失败&#xff0c;这个及其头疼的今天这个坑被我踩到了&#xff0c;呜呜呜~ 今天再发体验版小程序时&#xff0c;在微信开发者工具上面是可以正常访问后端的&#xff0c;但是线…

【sql注入-堆叠注入】多语句执行、结合其他注入

目录 堆叠注入 一、语法介绍 二、漏洞示例 三、常见形式 网络安全O 堆叠注入 一、语法介绍&#xff1a; 版本&#xff1a; 可以影响几乎所有的关系型数据库 原理&#xff1a; 将多条语句堆叠在一起进行查询&#xff0c;且可以执行多条SQL语句 语句之间以分号(;)隔开&#…

人气爆棚!广西、湖南、山西等地领导莅临数据宝考察交流

摘要&#xff1a;近期&#xff0c;数据宝发展如火如荼&#xff0c;企业展厅“忙不停”&#xff0c;见证众多思想碰撞、交流提升&#xff0c;迎来了各省领导莅临参观指导。 01 数字广西集团、青秀区政府领导一行莅临数据宝上海分公司实地走访 近日&#xff0c;数字广西集团党…

深入理解Linux网络——内核与用户进程协作之同步阻塞方案(BIO)

文章目录 一、相关实际问题二、socket的直接创建三、内核和用户进程协作之阻塞方式1&#xff09;等待接收消息2&#xff09;软中断模块3&#xff09;同步队列阻塞总结 在上一部分中讲述了网络包是如何从网卡送到协议栈的&#xff08;详见深入理解Linux网络——内核是如何接收到…