Day05:缓存双写一致性

news2024/12/27 3:05:50

redis做为缓存,mysql的数据如何与redis进行同步呢?(双写一致性–强一致)
一种是一致性要求比较高同步方案,另一种是允许延迟一致异步通知

什么是双写一致性?

双写一致性:当修改了数据库的数据也要同时更新缓存的数据,缓存和数据库的数据要保持一致
在这里插入图片描述
读操作:缓存命中,直接返回;缓存未命中查询数据库,写入缓存,设置超时时间。

写操作:延迟双删

什么是延迟双删?

延迟双删是先删除缓存,数据库修改完成之后,再延迟删除一次缓存,就是为了降低脏数据的出现。一般情况下数据库是主从模式,它是读写分离的。延时删除的目的就是为了让主数据库将数据同步到从数据库,这个延时也会出现问题因为多长时间不好控制,在延时的过程中也可能出现脏数据,做不到绝对的强一致。
在这里插入图片描述
先删除缓存,再修改数据库:
初始时缓存和数据库中的数据都是10,线程1执行删除缓存操作。线程2查询缓存未命中,查询数据库为10 ,然后写入到缓存中,此时缓存的数据为10。线程1再执行修改数据库操作,那么数据库中的数据就为20。此时出现了数据的不一致性也就是脏数据的情况。
在这里插入图片描述
先修改数据库再删除缓存:
初始数据库和缓存中的数据都是10,如果缓存过期了,也就是缓存中没有数据。线程1查询缓存未命中,就会查询数据库中的数据10。在线程1还没有同步到缓存之前,线程切换到线程2。线程2直接去更新数据库中的数据为20,然后再去删除缓存。线程1再将原来的10写入到缓存中。
在这里插入图片描述
先删除缓存还是先修改数据库都会出现问题。

解决缓存双写一致性方法:

方法一:加读写锁

使用读写锁的方式虽然何以保持数据的强一致性,但是性能相对低。读写锁方式比较适合业务必须强一致的情况下。
在写数据和读数据的时候添加分布式锁(互斥锁),只能有一个线程读或写,操作完成之后解锁成功才能让其他线程读写,这就能绝对保证数据的一致性,但是性能很低。由于存入缓存的数据都是读多写少,可以利用读写锁控制。当读数据的时候添加共享锁,允许其他线程读,但是不允许其他线程写。当写数据的时候添加排他锁,阻塞其他线程的读和写的操作
在这里插入图片描述
读写锁在redisson中已经提供了,首先通过getReadWriteLock获取读写锁,然后调用其readLock或者writeLock方法拿到读锁或者写锁。
在这里插入图片描述

方法二:异步通知

异步通知保证数据的最终一致性,允许短暂的不一致,在开发中该方法是主流的。
方式一:使用MQ中间件:
当修改数据写入数据到MySQL数据库后,就会发布消息给MQ,在缓存服务cache-service中监听MQ,最终再去更新缓存。消息发出后什么时候接收到消息,什么时候同步缓存肯定是有延迟的,需要保证MQ的可靠性。
在这里插入图片描述
方式二:使用Canal中间件
Canal是阿里的一个中间件,它主要是基于mysql的主从来实现同步。当有数据修改写入到数据库后,数据库一旦发生变化就会将这个变化记录到BINLOG二进制文件中。canal通过binlog日志文件与数据的变化,当需要的表数据发生变化后,就可以在缓存服务获取变化之后的数据,然后更新到缓存。
在这里插入图片描述

利用canal中间件,不需要修改业务代码,它是伪装了mysql的一个从节点,读取binlog数据更新缓存。如果业务能接收短暂的延迟,canal这种实现方式就可以。正常情况下是感受不到延迟的,除非在大量并发下才能感受到到延迟。

总结:

redis做为缓存,mysql的数据如何与redis进行同步?
方法一:异步方案
例如:把文章的热点数据存入到缓存中,虽然是热点数据,但是实时性要求并没那么高,所以采用异步的方案。
允许延时一致的业务,采用异步通知。
使用MQ的中间件完成数据的同步,当mysql的数据更新之后,会法发送一条消息通知给MQ。缓存服务cache-service需要接收这个消息,把数据同步到缓存中。这需要保证MQ的可靠性。
采用阿里的canal组件实现数据同步,不需要修改业务代码,部署一个canal服务。canal服务把自己伪装成mysql的一个从节点,当mysql数据更新以后,canal会读取binlog数据,然后通过canal的客户端获取到数据,更新缓存即可。
方法二:读写锁
例如:把抢劵的库存存入到缓存中,这个需要实时的进行数据同步,为了保证数据的强一致性,需要采用redisson提供的读写锁来保证数据的同步。
在读的时候添加共享锁,可以保证读读不互斥,读写互斥。更新数据的时候,添加排他锁,它是读写,读读都互斥,这样保证写数据的同时不会让其他线程读脏数据。这里面需要注意的是读方法和写方法上需要使用同一把锁才行。
排他锁是如何保证读写、读读互斥的?
排他锁底层使用的也是setnx,保证了同时只能有一个线程操作锁住的方法。
什么是延时双删?为什么不使用延时双删?
延时双删,如果是写操作,我们先把缓存中的数据删除,然后更新数据库,最后再延时删除缓存中的数据,其中这个延时多久不太好确定,在延时的过程中可能会出现脏数据,并不能保证数据的强一致性,所以不采用它。

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

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

相关文章

vue3+typescript自定义input组件

官方文档:https://cn.vuejs.org/guide/components/events#%E5%AE%9A%E4%B9%89%E8%87%AA%E5%AE%9A%E4%B9%89%E4%BA%8B%E4%BB%B6 触发与监听事件​ 在组件的模板表达式中,可以直接使用 $emit 方法触发自定义事件 (例如:在 v-on 的处理函数中)…

代码之丑第一期-缩进

各位小伙伴们,大家好!咱今天就算是正式开张了。实不相瞒,第一期的内容早已写好,但唯独这开篇方式,笔者想了好些时间,包括但不限于如下风格: 斗破苍穹式(已经三刷):代码优雅之力,三段!级别:低级!百年孤独式(困扰于错综复杂的人物关系,放弃):多年以后,面对吐槽…

idea2024加载flowable6.8.1.36遇到的问题-idea启动flowable问题flowable源码启动问题

代码下载地址: https://gitee.com/hanpenghu_admin_admin/flowable6.8.1.git 1.首先是通过顶层目录maven clean install 发现很多子模块并不会install本地mavenStore库,这导致了,一堆相互依赖的模块报错找不到,所以需要根据报错…

Vue.js 中 v-for 指令的三种常见用法详解及key、value、id的作用

作者:CSDN-PleaSure乐事 欢迎大家阅读我的博客 希望大家喜欢 使用环境:WebStorm 目录 遍历数组 介绍 代码 遍历对象数组 介绍 代码 遍历对象本身 介绍 代码 效果呈现 key、value、id的作用 1. value 2. key 3. id 在 Vue.js 中&#xff0c…

【论文投稿】国产游戏技术:迈向全球引领者的征途

【IEEE出版南方科技大学】第十一届电气工程与自动化国际会议(IFEEA 2024)_艾思科蓝_学术一站式服务平台 更多学术会议论文投稿请看:https://ais.cn/u/nuyAF3 目录 国产游戏技术能否引领全球? 一、国产游戏技术的崛起之路 1.1 初期探索与积…

React的ts文件中通过createElement拼接一段内容出来

比如接口返回一个值 const values [23.00, 40.00/kg];想做到如下效果, 如果单纯的用render渲染会很简单, 但是在ts文件中处理,所以采用了createElement拼接 代码如下: format: (values: string[]) > {if (!values || !val…

江协科技最新OLED保姆级移植hal库

江协科技最新OLED移植到hal库保姆级步骤 源码工程存档 工程和源码下载(密码 1i8y) 原因 江协科技的开源OLED封装的非常完美, 可以满足我们日常的大部分开发, 如果可以用在hal库 ,将是如虎添翼, 为我们开发调试又增加一个新的瑞士军刀, 所以我们接下来手把手的去官网移植源码…

HarmonyOS:使用Emitter进行线程间通信

Emitter主要提供线程间发送和处理事件的能力,包括对持续订阅事件或单次订阅事件的处理、取消订阅事件、发送事件到事件队列等。 一、Emitter的开发步骤如下: 订阅事件 import { emitter } from kit.BasicServicesKit; import { promptAction } from kit.…

Wi-Fi 进化论:从过去到未来(6/10)

Wi-Fi(发音: /ˈwaɪfaɪ/),在中文里又称作“移动热点”,是Wi-Fi联盟制造商的商标作为产品的品牌认证,是基于IEEE 802.11标准的无线局域网通信技术 [6]。基于两套系统的密切相关,也常有人把Wi-F…

【C++初阶】第5课—动态内存管理

文章目录 1. 内存分布2. C语言动态内存管理3. C内存管理方式3.1 new/delete操作内置类型3.2 new和delete操作自定义类型 4. operator new和operator delete函数5. new和delete的实现原理6. malloc/free和new/delete的区别7. 定位new表达式(了解即可) 1. 内存分布 先来做一个关于…

学习threejs,设置envMap环境贴图创建反光效果

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:threejs gis工程师 文章目录 一、🍀前言1.1 ☘️THREE.CubeTextureLoader 立…

Matlab Simulink HDL Coder FPGA开发初体验—计数器

目录 一、Simulink设计及仿真二、Verilog HDL代码转换1、参数配置2、HDL代码生成 三、ModelSim仿真分析1、使用自己编写的Testbench文件进行仿真2、使用HDL Coder生成的Testbench文件进行仿真 前言 Simulink HDL Coder‌是一款将Simulink和Stateflow模型转化为可综合的Verilog和…

【C语言】扫雷游戏(一)

我们先设计一个简单的9*9棋盘并有10个雷的扫雷游戏。 1,可以用数组存放,如果有雷就用1表示,没雷就用0表示。 2,排查(2,5)这个坐标时,我们访问周围的⼀圈8个位置黄色统计周围雷的个数是1。排查(8,6)这个坐标时&#xf…

实现点名神器的pyqt6实现

利用python gui创建点名神器,包含加分、导出加分记录、清除加分记录。 点名页面 首先导入学生信息 导入成功 开始点名 点击停止 点过之后,点击加分 加完分 查看加分记录 可以直接进入导出记录和清除历史。 此文到此结束,想要源码的请私聊我&a…

【UE5 C++】判断两点连线是否穿过球体

目录 前言 原理 代码 测试 结果 前言 通过数学原理判断空间中任意两点的连线是否穿过球体,再通过射线检测检验算法的正确性。 原理 (1)设球体球心的坐标为 ,半径为r; (2)设线段中A点的坐…

【AI】数据,算力,算法和应用(3)

三、算法 算法这个词,我们都不陌生。 从接触计算机,就知道有“算法”这样一个神秘的名词存在。象征着专业、权威、神秘、高难等等。 算法是一组有序的解决问题的规则和指令,用于解决特定问题的一系列步骤。算法可以被看作是解决问题的方法…

计算机的错误计算(一百七十一)

摘要 探讨 MATLAB 中秦九韶(Horner)多项式的错误计算。 例1. 用秦九韶(Horner)算法计算(一百零七)例1中多项式 直接贴图吧: 这样,MATLAB 给出的仍然是错误结果,因为准…

Ubuntu20.04运行R-VIO2

目录 1.环境配置2.构建项目3. 运行 VIO 模式4.结果图 1.环境配置 CMakeLists.txt中 C 使用 14、opencv使用4 2.构建项目 克隆代码库: 在终端中执行以下命令克隆项目:git clone https://github.com/rpng/R-VIO2.git编译项目: 使用 catkin_m…

【Maven系列】深入解析 Maven 常用命令

前言 在当今的软件开发过程中,项目管理是至关重要的一环。项目管理包括了项目构建、依赖管理以及发布部署等诸多方面。而在Java生态系统中,Maven已经成为了最受欢迎的项目管理工具之一。Maven 是一套用于构建、依赖管理和项目管理的工具,主要…

深度学习的python基础(1)

一.tensor创建 1.张量的定义 张量在形式上就是多维数组,例如标量就是0维张量,向量就是一维张量,矩阵就是二维张量,而三维张量就可以想象RGB图片,每个channel是一个二维的矩阵,共有三个channel&#xff0…