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

2023-11-04

本文主要介绍了浅谈MySQL数据同步到 Redis 缓存的几种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着微点阅读小编来一起学习学习吧

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

4 延迟双删

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

执行更新sql

延迟一段时间

再次删除redis的数据

1

2

3

4

5

// 延迟双删伪代码

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 延迟双写

1

2

3

// 延迟双写伪代码

updateMysqlSql(obj);        // 更新mysql

addRedis(key);   // 再次删除该key的缓存

上述代码缺陷;

  • 高并发下,两条线程同时执行上面代码,并对mysql 修改,且修改内容不通,可能会导致Redis与Mysql数据不一致
  • T1线程执行完updateMysqlSql,释放了行锁,此时T2线程再执行updateMysqlSql 与 addRedis, 最后T1执行addRedis,这种情况会导致数据库改成了T2线程的数据,但Redis却是T1线程的数据

优化

1

2

3

4

5

// 完美延迟双写伪代码

开启事务

updateMysqlSql(obj);        // 更新mysql

addRedis(key);   // 再次删除该key的缓存

提交事务

上述代码改正:

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

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

6 结语

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

到此这篇关于浅谈MySQL数据同步到 Redis 缓存的几种方法的文章就介绍到这了,希望可以对你有所有帮助。

来源:微点阅读   https://www.weidianyuedu.com

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MySQL数据同步到 Redis 缓存的几种方法 的相关文章

  • 在 C# 中,当有人插入、删除或修改记录时,如何从 MySQL 获取事件?

    我正在 WPF Net 中开发一个程序 我需要知道何时有人对数据库的任何表进行更改 这个想法是在数据库发生更改时从数据库接收一个事件 我读了很多文章 但找不到解决我的问题的方法 亲切的问候 最好的解决方案是使用消息队列 在您的应用程序向数据
  • 如何在mysql中选择具有相同值集的列?

    我的桌子是 patients pid name city disease did dname has disease did pid 我想列出具有相同疾病组的患者 pid 和 did 分别是患者和疾病表中的主键 并且是 has diseas
  • MySQL - 从临时表插入

    这看起来非常简单 但我坚持使用简单的插入语句 见下文 begin work CREATE TEMPORARY TABLE IF NOT EXISTS insert table AS select r resource id fr file
  • 不允许在 php 中连接到此 MariaDB 服务器

    我尝试在 php 中连接远程服务器数据库 但出现以下错误 Host xx xxx xx xx is not allowed to connect to this MariaDB server in 我的连接代码是这样的 servername
  • 如果没有找到值,如何让 MySQL 中的 SUM 函数返回“0”?

    假设我在 MySQL 中有一个简单的函数 SELECT SUM Column 1 FROM Table WHERE Column 2 Test 如果没有条目Column 2 包含文本 Test 然后该函数返回NULL 而我希望它返回 0 我
  • 如何优化这个MySQL慢(非常慢)查询?

    我有一个 2 GB 的 mysql 表 包含 500k 行 我在没有负载的系统上运行以下查询 select from mytable where name in n1 n2 n3 n4 bunch more order by salary
  • mysql转储到derby

    我正在使用 derby 在 eclipse 中进行开发 是否可以从 MySQL 转储表并以某种方式将其用于 derby 我知道 ddl 和 dml 对于两个 dbms 来说是不同的 但我正在寻找一种除了转储 导出之外的合适方法 我可以找到两
  • PHP 和 MySQL - 高效处理多个一对多关系

    我正在寻求一些有关使用 MySQL 和 PHP 检索和显示数据的最佳方法的建议 我有 3 个表 所有一对多关系如下 Each SCHEDULE有很多覆盖每个覆盖都有很多地点 我想检索这些数据 以便它可以全部显示在单个 PHP 页面上 例如列
  • 无法在 Mac 上启动 MySQL

    使用 Brew 安装后 我无法运行 MySQL 我使用的是 OS X El Capitan 版本 10 11 3 和 MySQL Server 版本 5 7 11 当我启动服务器时 我收到 启动 MySQL 错误 服务器退出而不更新 PID
  • 如何在 MySQL 中测试 Select for Update

    我正在表演SELECT FOR UPDATE或 InnoDB 表的行级锁定 我的目的是只有一个请求可以读取同一行 因此 如果两个用户同时请求相同的数据 其中只有一个人获取数据 即第一个触发查询的人 但是我如何测试锁定是否已放置 因为我正在通
  • mysql 中的二进制、十六进制和八进制值

    我对在 mysql 数据库中使用二进制 十六进制和八进制系统非常感兴趣 首先 请给我一个建议 为什么我们在存储信息时需要它们 因为信息太多 或者为什么 另外 哪种类型的值必须存储在标记系统中 另外这里还有像 这是例子 gt SELECT 5
  • ORDER BY 字段内的 MySQL 子查询。 (没有内连接)

    有很多与此相关的问题 但都具有使用内部联接的相同答案 这 我认为 在这里是不可能的 如果我错了请告诉我 我现在正在做的是调用两个不同的 mysql 查询来获取结果 它工作完美 db gt query SELECT FROM meta WHE
  • 如果 Redis 已经是堆栈的一部分,为什么 Memcached 仍然与 Redis 一起使用?

    Redis 可以执行 Memcached 提供的所有操作 LRU 缓存 项目过期以及现在版本 3 x 中的集群 目前处于测试阶段 或通过 twemproxy 等工具执行 性能也类似 此外 Redis 增加了持久性 因此您无需在服务器重新启动
  • 如何通过Elasticsearch模糊匹配电子邮件或电话?

    我想通过 Elasticsearch 对电子邮件或电话进行模糊匹配 例如 匹配所有以以下结尾的电子邮件 gmail com or 匹配所有电话开头136 我知道我可以使用通配符 query wildcard email gmail com
  • Redis 会话序列化器 3.2 和 4.2 之间不匹配

    我有一个基于 Spring Cloud 的应用程序在多个 spring boot 服务器上运行 所有服务器使用 EnableRedisHttpSession共享相同的Spring Session 我现在想将第三方小部件集成到我的应用程序中
  • posts_search 中的自定义查询

    如何使用此查询作为我的自定义搜索查询 add filter posts search my search is perfect 20 2 function my search is perfect search wp query sWord
  • MYSQL从每个类别中随机选择一条记录

    我有一个数据库Items表看起来像这样 id name category int 有几十万条记录 每个item可以是 7 种不同的之一categories 对应于categories table id category 我想要一个从每个类别
  • PHP 与 MySQL 查询性能( if 、 函数 )

    我只看到这个artice http www onextrapixel com 2010 06 23 mysql has functions part 5 php vs mysql performance 我需要知道在这种情况下什么是最好的表
  • Mysql插入表后不显示右单引号(’)

    我有一个名为 测试 的表 我插入了一行 其中包含unicode字符右单引号 0x2019在名称字段中 SQL insert into Testing values Sno Name Address insert into Testing v
  • 在 android 中建立与 MySQL 的池连接

    我需要从我的 Android 应用程序访问 MySQL 数据库 现在所有的工作都通过 DriverManager getConnection url 等等 但我必须从多个线程访问数据库 所以我必须使用连接池 问题1 是 com mysql

随机推荐

  • 图像处理——滤波器的比较

    滤波器 方框滤波 boxFilter 均值滤波 blur 高斯滤波 GaussianBlur 中值滤波 medianBlur 线性滤波器 线性滤波器经常用于剔除输入信号中不想要的频率或者从许多频率中选择一个想要的频率 常见的有 低通 高通
  • linux命令 chmod 755的含义 及drwxr-xr-x 的含义

    linux drwxr xr x 第一位表示文件类型 d是目录文件 l是链接文件 是普通文件 p是管道 第2 4位表示这个文件的属主拥有的权限 r是读 w是写 x是执行 第5 7位表示和这个文件属主所在同一个组的用户所具有的权限 第8 10
  • docker 安装node

    docker 安装node 1 使用docker安装node 使用docker安装 docker pull node 拉取镜像 docker run id name c node node 创建容器 可以看到已经装好了 启动node doc
  • Linux系统编程-C++ I/O库

    文章目录 一 总述 二 输出缓冲 三 文件输入输出 四 string流 五 输入输出格式 总述 1 控制布尔值的格式 2 指定整型值的进制 3 在输出中指出进制 4 控制浮点数格式 4 1 指定打印精度 5 输出空白 六 未格式化的输入输出
  • java 数组中存储26个英文字母_利用数组打印26个英文字母

    可以考虑下面两种程序 1 public class Letter public static void main String args for char c a c lt z c System out print c 2 class AB
  • 如何实现一个定时器?看这一篇就够了

    本文主要介绍定时器作用 实现定时器数据结构选取 并详细介绍了跳表 红黑树 时间轮实现定时器的思路和方法 定时器作用 定时器在各种场景都需要用到 比如游戏的Buff实现 Redis中的过期任务 Linux中的定时任务等等 顾名思义 定时器的主
  • Qt常用部件介绍

    这里先给大家介绍 Designer 界面设计器 中例举的常用部件 以便对 Qt 的部件有一定认识 其具体用法后面再作介绍 布局管理组 Layouts 空间间隔组 弹簧 Spacers 按钮组 buttons 项目视图组 Item Views
  • 设计模式深入浅出--21.命令模式简单实例及其在JDK中的应用

    命令模式 定义 将 请求 封装成对象 以便使用不同的请求 命令模式解决了应用程序中对象的职责以及它们之间的通信方式 类型 行为型 适用场景 请求调用者和请求接收者需要解耦 使得调用者和接收者不直接交互 需要抽象出等待执行的行为 优点 降低解
  • 数据表格(QTableWidget)

    一 简介 QTableWidget是QT对话框设计中常用的显示数据表格的控件 QTableWidget单元格数据是QTableWidgetItem对象来实现的 整个表格都需要用逐个单元格对象QTableWidgetItem构建起来 二 详解
  • Presto 与 Hive 语法学习

    Presto 与 Hive 语法学习 文章目录 Presto 与 Hive 语法学习 1 Presto语法 1 1 数据类型 布尔值 整数 浮点 固定精度 字符串 日期和时间 结构 网络地址 UUID HyperLogLog KHyperL
  • muduo1——编程风格:面向对象的编程和基于对象的编程(上)

    muduo库其实不是面向对象的编程 而是基于对象的编程 那么在进入正式的muduo源码分析之前 先来看看这两种编程风格 一 面向对象编程风格 通过对一个线程类的封装来进行讲解 Thread是一个抽象类不能实例化对象 TestThread是派
  • Hp DL380服务器瘫痪如何恢复服务器数据(多图)

    服务器数据恢复故障简介 需要进行数据恢复的是一台HP DL380服务器 三块300GSAS硬盘组成raid阵列 磁盘故障导致整个RAID组瘫痪 其中一块硬盘状态灯为红色 数据库存储在D分区 备份存储在E分区 存储故障 造成D分区不可识别 E
  • Python 关键字global全局变量详解

    变量作用域 一般在函数体外定义的变量成为全局变量 在函数内部定义的变量称为局部变量 全局变量所有作用域都可用 局部变量只能在本函数可用 变量的使用顺序是 局部变量 gt 全局变量 也就是说 优先使用局部变量 那么问题来了 如果想在函数内使用
  • LabVIEW心率监测装置

    LabVIEW大作业 LabVIEW心率采集装置 本设计为我的LabVIEW课程大作业 利用proteus实验仿真软件设计一个了基于stc12c5a单片机的心率采集系统 并在PC机上的Windows环境下利用LabVIEW软件实现心率数据的
  • 开开心心带你学习MySQL数据库之节尾篇下

    真的勇士 那就是看清生活的真相之后 依然热爱生活 罗曼 罗兰 JDBC编程的基本工作 准备工作 1 下载 mysql驱动包 maven 中央仓库 2 导入到项目中复制到项目目录下 标志为 library 编写代码 1 创建数据源 描述数据库
  • (.htaccess文件和.user.ini文件)[SUCTF 2019]CheckIn1

    打开靶机 提交一个一句话木马文件 图片马 显示上传成功 但是使用蚁剑连接返回为空 再使用 htaccess文件绕过 参考博主原文链接 https blog csdn net m0 64444909 article details 12489
  • 设置ImageButton的点击效果

    我要设置一个ImageButton的点击效果 普通状态背景透明 按下状态有一个背景图 src是一个图片 如下所示
  • 解决.net中使用gmail.com邮箱进行Smtp发送信件时失败的问题

    我经常使用免费的gmail com邮箱 因为它容量较大 但我们在使用 net编程实现邮件发送时 常会出现我们意想不到的错误 最常见的就是 1 The operation has timed out 2 出现类似提示 The SMTP ser
  • QT编写的数字键盘

    https download csdn net download qq 20189555 88001237
  • MySQL数据同步到 Redis 缓存的几种方法

    本文主要介绍了浅谈MySQL数据同步到 Redis 缓存的几种方法 文中通过示例代码介绍的非常详细 对大家的学习或者工作具有一定的参考学习价值 需要的朋友们下面随着微点阅读小编来一起学习学习吧 1 Mysql查完数据 再同步写入到Redis