MySQL数据同步到 Redis 缓存的几种方法

1 Mysql查完数据,再同步写入到Redis中

  1. 缺点1:会对接口造成延迟,因为同步写入redis本身就有延迟,并且还要做重试,如果redis写入失败,还需要重试,那就更费时间了。

  1. 缺点2:不解耦,如果redis崩了,那直接卡线程了

  1. 缺点3:如果人为该数据库,那就没法同步了, 除非再人为删除对应的Redis,但删除Redis这个过程也有个时间差

2 Mysql查完数据,通过发送MQ,在消费者线程去同步Redis

  1. 缺点1:多了层MQ,也就是会有很大的概率导致同步延迟问题.

  1. 缺点2:要对MQ的可用性做预防

  1. 缺点3:如果人为该数据库,那就没法同步了

  1. 优点1:可以大幅减少接口的延迟返回的问题

  1. 优点2:MQ本身有重试机制,无需人工去写重试代码

  1. 优点3:解耦,把查询Mysql和同步Redis完全分离,互不干扰

3 订阅Mysql的Binlog文件(可借助Canal来进行)

  1. CanalServer会伪装成MysqlServer从库,去订阅MysqlServer主库的Binlog文件

  1. Canal启动的时候会配置对应的消息MQ(RabbitMQ, RocketMQ, Kafka), 监听到Binlog文件有变化是,会把变化的sql语句转换成json格式,并作为消息内容发送到MQ中

  1. 项目中只要监听对应MQ,就能拿到Binlog改动的内容,Json数据中有明确的操作类型(CURD), 以及对应的数据。把对应数据同步到redis即可

  1. 缺点1:canal订阅Binlog的整个操作过程是单线程的,所以面临超高并发的情况下,性能可能不太出色。当然可以部署多个Canal 与 多个消费者,但是要注意消息重复消费问题,做好幂等性校验

  1. 优点1:即使人为改数据库,也会监听到,并且也会同步

  1. 优点2:异步同步,不会对接口返回有格外延迟

4 延迟双删

  1. 在执行修改sql之前,先将redis的数据删除

  1. 执行更新sql

  1. 延迟一段时间

  1. 再次删除redis的数据

// 延迟双删伪代码
deleteRedisCache(key);   // 删除redis缓存
updateMysqlSql(obj);        // 更新mysql
Thread.sleep(100);           // 延迟一段时间
deleteRedisCache(key);   // 再次删除该key的缓存

缺点:这个延迟时间不好把控,到底延迟多久,这个很难去评估

扩展: 如果不使用延迟双删,仅仅是delete缓存,然后改mysql数据。只有这两步会出现什么问题呢?

5. 单个请求,单线程没问题,高并发多线程下会出问题

6. 如果Thread1线程要更新数据,此时Thread1线程把redis清理了

7. 此时Thread2线程来了,但Thread1还没有更新mysql完毕

8. Thread2查询redis肯定是null,此时Thread2就要查mysql了,然后再把查到的数据写到缓存

9. 由于Thread1还没来得及修改mysql数据,所以此时Thread2查出来的数据是【旧数据】,Thread2把旧数据又写入Redis 了

10. 此时Thread3线程来了,查询Redis发现有数据,则直接拿缓存数据了,此时【Thread3查出来的是旧数据】,直接带着旧数据返回了,这就是问题所在

11. 而延迟双删的第二次删除作用就是防止Thread2把旧数据又写入了,有了延迟双删,Thread3查询Redis的时候还是null,就会从mysql 去拿最新数据了

12. 所以正常的这个延迟时间,应该是Thread2查缓存到拿mysql数据,到再保存到redis这整个时间,作为Thread1的延迟时间,但是这个Thread2这个过程的时间会受到很多因素影响,因此很难断定究竟会是多久

5 延迟双写

// 延迟双写伪代码
updateMysqlSql(obj);        // 更新mysql
addRedis(key);   // 再次删除该key的缓存

上述代码缺陷;

  1. 高并发下,两条线程同时执行上面代码,并对mysql 修改,且修改内容不通,可能会导致Redis与Mysql数据不一致

  1. T1线程执行完updateMysqlSql,释放了行锁,此时T2线程再执行updateMysqlSql 与 addRedis, 最后T1执行addRedis,这种情况会导致数据库改成了T2线程的数据,但Redis却是T1线程的数据

优化
// 完美延迟双写伪代码
开启事务
updateMysqlSql(obj);        // 更新mysql
addRedis(key);   // 再次删除该key的缓存
提交事务

上述代码改正:

  1. 把两句代码放到一个事务里面,只有T1执行完Mysql 与 Redis的时候,T2才能开始执行,就可以保证数据一致性。推荐使用分布式锁

  1. 双写缺点:Mysql 与 Redis是单线程的。性能方面不行,因此不推荐使用

6 总结

推荐使用Canal的方式,进行异步同步。其次是MQ方式

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

九种跨域方式实现原理(完整版)

前言 前后端数据交互经常会碰到请求跨域,什么是跨域,以及有哪几种跨域方式,这是本文要探讨的内容。 一、什么是跨域? 1.什么是同源策略及其限制内容? 同源策略是一种约定,它是浏览器最核心也最基本的安…

如何发布自己的npm包

一、什么是npm npm是随同nodejs一起安装的javascript包管理工具,能解决nodejs代码部署上的很多问题,常见的使用场景有以下几种: ①.允许用户从npm服务器下载别人编写的第三方包到本地使用。 ②.允许用户从npm服务器下载并安装别人编写的命令…

K_A18_001 基于STM32等单片机采集MQ2传感参数串口与OLED0.96双显示

K_A18_001 基于STM32等单片机采集MQ2传感参数串口与OLED0.96双显示一、资源说明二、基本参数参数引脚说明三、驱动说明IIC地址/采集通道选择/时序对应程序:四、部分代码说明1、接线引脚定义1.1、STC89C52RCMQ2传感参模块1.2、STM32F103C8T6MQ2传感参模块五、基础知识学习与相关…

Vue3之插槽(Slot)

何为插槽 我们都知道在父子组件间可以通过v-bind,v-model搭配props 的方式传递值,但是我们传递的值都是以一些数字,字符串为主,但是假如我们要传递一个div或者其他的dom元素甚至是组件,那v-bind和v-model搭配props的方式就行不通…

让你少写多做的 ES6 技巧

Array.of 关于奇怪的 Array 函数: 众所周知,我们可以通过Array函数来做以下事情。 初始化一个指定长度的数组。 设置数组的初始值。 // 1. Initialize an array of the specified length const array1 Array(3) // [ , , ] // 2. Set the initial value…

Spring Cloud学习笔记【负载均衡-Ribbon】

文章目录什么是Spring Cloud RibbonLB(负载均衡)是什么Ribbon本地负载均衡客户端 VS Nginx服务端负载均衡区别?Ribbon架构工作流程Ribbon Demo搭建IRule规则Ribbon负载均衡轮询算法的原理配置自定义IRule新建MyRuleConfig配置类启动类添加Rib…

SQLMap 源码阅读

0x01 前言 还是代码功底太差,所以想尝试阅读 sqlmap 源码一下,并且自己用 golang 重构,到后面会进行 ysoserial 的改写;以及 xray 的重构,当然那个应该会很多参考 cel-go 项目 0x02 环境准备 sqlmap 的项目地址&…

学习java——②面向对象的三大特征

目录 面向对象的三大基本特征 封装 封装demo 继承 继承demo 多态 面向对象的三大基本特征 我们说面向对象的开发范式,其实是对现实世界的理解和抽象的方法,那么,具体如何将现实世界抽象成代码呢?这就需要运用到面向对象的三大…

从ChatGPT与New Bing看程序员为什么要学习算法?

文章目录为什么要学习数据结构和算法?ChatGPT与NEW Bing 的回答想要通关大厂面试,就不能让数据结构和算法拖了后腿业务开发工程师,你真的愿意做一辈子CRUD boy吗?对编程还有追求?不想被行业淘汰?那就不要只…

2023年网络安全比赛--CMS网站渗透中职组(超详细)

一、竞赛时间 180分钟 共计3小时 二、竞赛阶段 1.使用渗透机对服务器信息收集,并将服务器中网站服务端口号作为flag提交; 2.使用渗透机对服务器信息收集,将网站的名称作为flag提交; 3.使用渗透机对服务器渗透,将可渗透页面的名称作为flag提交; 4.使用渗透机对服务器渗透,…

一个Bug让人类科技倒退几十年?

大家好,我是良许。 前几天在直播的时候,问了直播间的小伙伴有没人知道「千年虫」这种神奇的「生物」的,居然没有一人能够答得上来的。 所以,今天就跟大家科普一下这个人类历史上最大的 Bug 。 1. 全世界的恐慌 一个Bug会让人类…

jQuery《一篇搞定》

今日内容 一、JQuery 零、 复习昨日 1 写出至少15个标签 2 写出至少7个css属性font-size,color,font-familytext-algin,background-color,background-image,background-sizewidth,heighttop,bottom ,left ,rightpositionfloatbordermarginpadding 3 写出input标签的type的不…

flex布局左边宽度固定,右边宽度动态扩展问题

我们希望在一个固定宽度的容器中&#xff0c;分左右两边&#xff0c;左边宽度固定大小&#xff0c;右边占满&#xff0c;使用flex布局时&#xff0c;如下&#xff1a; 对应代码如下&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta…

LeetCode - 198 打家劫舍

目录 题目来源 题目描述 示例 提示 题目解析 算法源码 题目来源 198. 打家劫舍 - 力扣&#xff08;LeetCode&#xff09; 题目描述 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装…

【华为机试真题 Python实现】2023年1、2月高频机试题

文章目录2023年1季度最新机试题机考注意事项1. 建议提前刷题2. 关于考试设备3. 关于语言环境3.1. 编译器信息3.2. ACM 模式使用sys使用input&#xff08;推荐&#xff09;3. 关于题目分值及得分计算方式4. 关于做题流程5. 关于作弊2023年1季度最新机试题 两个专栏现在有200博文…

2023还有人不知道kubernetes?| 初步理解kubernetes

文章目录Kubernetes(K8s)一、Openstack&VM1、**认识虚拟化****1.1**、什么是虚拟化**1.2、虚拟化分类**2、OpenStack与KVM、VMWare2.1、OpenStack2.2、KVM2.3、VMWare二、容器&编排技术1、容器发展史1.1、Chroot1.2、FreeBSD Jails1.3、Solaris Zones1.4、LXC1.5、Dock…

深度学习 Day26——使用Pytorch实现猴痘病识别

深度学习 Day26——使用Pytorch实现猴痘病识别 文章目录深度学习 Day26——使用Pytorch实现猴痘病识别一、前言二、我的环境三、前期工作1、设置GPU导入依赖项2、导入猴痘病数据集3、划分数据集四、构建CNN网络五、训练模型1、设置超参数2、编写训练函数3、编写测试函数4、正式…

【LeetCode】1544. 整理字符串、LCP 44. 开幕式焰火

作者&#xff1a;小卢 专栏&#xff1a;《Leetcode》 喜欢的话&#xff1a;世间因为少年的挺身而出&#xff0c;而更加瑰丽。 ——《人民日报》 目录 1544. 整理字符串 LCP 44. 开幕式焰火 1544. 整理字符串 1544. 整理字符串 题目描述…

金三银四、金九银十 面试宝典 Spring、MyBatis、SpringMVC面试题 超级无敌全的面试题汇总(超万字的面试题,让你的SSM框架无可挑剔)

Spring、MyBatis、SpringMVC 框架 - 面试宝典 又到了 金三银四、金九银十 的时候了&#xff0c;是时候收藏一波面试题了&#xff0c;面试题可以不学&#xff0c;但不能没有&#xff01;&#x1f941;&#x1f941;&#x1f941; 一个合格的 计算机打工人 &#xff0c;收藏夹里…

正则表达式高阶技巧之匹配模式(使用python实现)

匹配模式介绍不区分大小写模式模式的指定方式应用单行模式多行模式注释模式其它模式修饰符的作用范围介绍 我们在正则中所说得匹配模式&#xff08;match mode&#xff09;&#xff0c;指的是匹配时使用的规则。设置特定的匹配模式&#xff0c;可能会改变对正则表达式的识别&a…
最新文章