Redis 和 Mysql 如何保证两者数据一致性

文章目录

    • 概述
    • 解决方案
    • 消息队列+异步重试 基于 RocketMQ 的可靠性消息通信,来实现最终一致
    • Canal 组件,监控 Mysql 中 binlog 的日志,把更新后的数据同步到 Redis 里面
    • 延时双删
    • 弱一致性和强一致性
    • Canal详解

概述

在分布式系统中,保证Redis和MySQL之间的数据一致性是一个复杂且重要的问题。由于Redis是内存数据库,而MySQL是磁盘数据库,它们的特性和持久化方式不同,因此需要特殊的注意和处理来确保数据的一致性。
以下是一些常见的方法来保证Redis和MySQL之间的数据一致性:

  1. 双写模式:在进行写操作时,先将数据写入MySQL,然后再将数据写入Redis。这种方式可以保证MySQL中的数据一定会被同步到Redis中,但是对于读操作来说效率较低。
  2. 异步更新:在进行写操作时,只将数据写入MySQL,然后异步地将数据写入Redis。这种方式可以提高写入操作的效率,但是可能会导致Redis中的数据与MySQL中的数据存在一定的延迟。
  3. 通过消息队列实现数据同步:可以使用消息队列(如Kafka、RabbitMQ等)来实现MySQL和Redis之间的数据同步。当MySQL中的数据发生变化时,将变化的数据写入消息队列,然后Redis订阅消息队列,根据消息内容更新自己的数据。这种方式可以实现异步更新,并且解耦了MySQL和Redis之间的直接依赖。
  4. 定期全量同步:定期从MySQL中读取全量数据,然后覆盖Redis中的数据。这种方式可以保证Redis中的数据与MySQL中的数据完全一致,但是对于大数据量的情况下可能会影响性能。
  5. 使用分布式事务:在一些场景下,可以使用分布式事务来保证Redis和MySQL之间的数据一致性。例如,可以使用基于XA协议的分布式事务管理器(如Seata)来协调Redis和MySQL之间的数据更新操作。
    需要根据具体的业务场景和需求选择合适的数据一致性方案,并进行相应的设计和实现。同时,还需要考虑各种异常情况下的处理,如网络故障、节点宕机等,以确保系统在异常情况下依然能够保持数据一致性。

解决方案

1.基于 MQ 异步同步更新,消息队列+异步重试-比如基于 RocketMQ 的可靠性消息通信,来实现最终一致
2.还可以直接通过 Canal (阿里的一款开源框架)组件,监控 Mysql 中 binlog 的日志,把更新后的数据同步到 Redis 里面。
3.延时双删
缓存延时双删
删除缓存重试机制
读取biglog异步删除缓存
一般情况下,Redis 用来实现应用和数据库之间读操作的缓存层,主要目的是减少数据库 IO,还可以提升数据的 IO 性能。这是它的整体架构
当应用程序需要去读取某个数据的时候,首先会先尝试去 Redis 里面加载,如果命中就直接返回。如果没有命中,就从数据库查询,查询到数据后再把这个数据缓存到 Redis 里面。
在这样一个架构中,会出现一个问题,就是一份数据,同时保存在数据库和 Redis里面,当数据发生变化的时候,需要同时更新 Redis 和 Mysql,由于更新是有先后顺序的,并且它不像 Mysql 中的多表事务操作,可以满足 ACID 特性。所以就会出现数据一致性问题。
在这种情况下,能够选择的方法只有几种
先更新数据库,再更新缓存
先删除缓存,再更新数据库
如果先更新数据库,再更新缓存,如果缓存更新失败,就会导致数据库和 Redis中的数据不一致。
如果是先删除缓存,更新数据库,理想情况是应用下次访问 Redis 的时候,发现 Redis 里面的数据是空的,就从数据库加载保存到 Redis 里面,那么数据是一致的。但是在极端情况下,由于删除 Redis 和更新数据库这两个操作并不是原子的,所以这个过程如果有其他线程来访问,还是会存在数据不一致问题
如果需要在极端情况下仍然保证 Redis 和 Mysql 的数据一致性,就只能采用最终一致性方案。

消息队列+异步重试 基于 RocketMQ 的可靠性消息通信,来实现最终一致

因为延时双删可能会存在第二步的删除缓存失败,导致的数据不一致问题。可以使用这个方案优化:删除失败就多删除几次呀,保证删除缓存成功就可以了呀~ 所以可以引入删除缓存重试机制
在这里插入图片描述

删除缓存重试流程

  1. 写请求更新数据库
  2. 缓存因为某些原因,删除失败
  3. 把删除失败的key放到消息队列
  4. 消费消息队列的消息,获取要删除的key
  5. 重试删除缓存操作

Canal 组件,监控 Mysql 中 binlog 的日志,把更新后的数据同步到 Redis 里面

因为这里是基于最终一致性来实现的,如果业务场景不能接受数据的短期不一致性,那就不能使用这个方案来做
异步更新缓存(基于订阅binlog的同步机制)
MySQL binlog增量订阅消费+消息队列+增量数据更新到redis读Redis
热数据基本都在Redis写MySQL:增删改都是操作MySQL更新Redis数据:MySQ的数据操作binlog,来更新到Redis:
1)数据操作主要分为两大块:一个是全量(将全部数据一次写入到redis)一个是增量(实时更新)。
这里说的是增量,指的是mysql的update、insert、delate变更数据。
2)读取binlog后分析 ,利用消息队列,推送更新各台的redis缓存数据。
这样一旦MySQL中产生了新的写入、更新、删除等操作,就可以把binlog相关的消息推送至Redis,Redis再根据binlog中的记录,对Redis进行更新。
其实这种机制,很类似MySQL的主从备份机制,因为MySQL的主备也是通过binlog来实现的数据一致性。
这里可以结合使用canal(阿里的一款开源框架),通过该框架可以对MySQL的binlog进行订阅,而canal正是模仿了mysql的slave数据库的备份请求,使得Redis的数据更新达到了相同的效果。
当然,这里的消息推送工具你也可以采用别的第三方:kafka、rabbitMQ等来实现推送更新Redis

重试删除缓存机制还可以吧,就是会造成好多业务代码入侵。其实,还可以这样优化:通过数据库的binlog来异步淘汰key。
在这里插入图片描述

以mysql为例吧
● 可以使用阿里的canal将binlog日志采集发送到MQ队列里面
● 然后通过ACK机制确认处理这条更新消息,删除缓存,保证数据缓存一致性

延时双删

redis.delKey(X)
db.update(X)
Thread.sleep(N)
redis.delKey(X)

先删除缓存,再更新数据库,当更新数据后休眠一段时间再删除一次缓存。
这个休眠时间 = 读业务逻辑数据的耗时 + 几百毫秒。为了确保读请求结束,写请求可以删除读请求可能带来的缓存脏数据。
这种方案还算可以,只有休眠那一会(比如就那1秒),可能有脏数据,一般业务也会接受的。但是如果第二次删除缓存失败呢?缓存和数据库的数据还是可能不一致,对吧?给Key设置一个自然的expire过期时间,让它自动过期怎样?那业务要接受过期时间内,数据的不一致咯?还是有其他更佳方案呢?

弱一致性和强一致性

数据同步过程中,会存在短暂的延迟,这属于正常的现象。
在分布式架构中很难实现数据强一致性
弱一致性: 主从之间数据允许不一致性;
强一致性: 主从之间数据必须一致性; 如果实现 成本是非常高,会设计到 一些锁的技术,
最终一致性:短暂的数据延迟是允许的,但是最终数据是需要一致; —在分布式中做数据同步需要经过网络传输的,网络传输数据需要一定的时间, 所以数据短暂的延迟是允许的,但是最终数据一定达成一致。
延迟是很难避免的,优化 减少延迟的时间。 公司中数据 同步延迟 优化在 10-30 毫秒。

Canal详解

Canal 是阿里巴巴开源的数据库变更捕获(CDC)解决方案,主要用于监控数据库的变更,并将这些变更推送到其他数据存储、消息队列等目标端。以下是对 Canal 的详细解释:

  1. 工作原理:
    ○ Canal通过连接数据库的binlog日志,实时解析binlog日志中的数据变更(如insert、update、delete等操作),将这些变更解析成数据库行记录的格式,并推送到外部系统。
    ○ Canal分为客户端和服务端两部分。客户端(Agent)位于数据库服务器上,负责与数据库的binlog日志进行交互,并将解析后的数据变更推送给服务端。服务端(Server)接收客户端推送的数据变更,并将其发送到目标存储或消息队列。
  2. 特点:
    ○ 实时性:Canal能够实时捕获数据库的变更,几乎可以做到毫秒级的实时性。
    ○ 可靠性:Canal保证数据变更的完整性和准确性,可以应对数据库主从切换、网络闪断等异常情况。
    ○ 高性能:Canal使用了一系列性能优化措施,如异步化处理、多线程并发等,保证了高性能的数据变更捕获和传输。
  3. 应用场景:
    ○ 数据同步:将数据库的变更同步到其他数据存储(如另一个数据库、Hadoop、Elasticsearch等)。
    ○ 实时监控:实时监控数据库的变更情况,用于数据审计、报警等用途。
    ○ 缓存更新:将数据库的变更用于更新缓存,提高系统性能和响应速度。
    ○ 搜索引擎索引更新:将数据库的变更同步到搜索引擎(如Elasticsearch)中,用于实时更新索引。
  4. 支持的数据库:
    ○ Canal目前主要支持MySQL数据库,包括MySQL的各种版本,如MySQL5.x、MySQL8.x等。
  5. 架构图:
    ○ Canal的架构包括客户端(Agent)和服务端(Server)两部分,客户端负责与数据库的binlog交互,服务端负责接收客户端推送的数据变更并处理。
    ○ 具体的架构图可以参考官方文档或源码。
    总的来说,Canal是一个功能强大的数据库变更捕获解决方案,可以实现实时的数据库变更监控和同步,广泛应用于数据同步、实时监控等场景。

方案二:还可以直接通过 Canal 组件,监控 Mysql 中 binlog 的日志,把更新后的数据同步到 Redis 里面。

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

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

相关文章

失之毫厘差之千里之load和loads

起源 最近在读pandas库的一些文档的时候,顺便也会将文档上的一些demo在编辑器中进行运行测试,其中在读到pandas处理Json数据这一节的时候,我还是像往常一样,将文档提供的demo写一遍,结果在运行的时候,直接…

【React篇】组件错误边界处理(组件错误引起的页面白屏)

我们知道在生产环境react错误会导致整个页面崩溃,显示为空白页面。 比如下图的错误,导致了左侧页面直接白屏: 由于某一个组件报错导致整个页面崩溃是很严重的问题,那么我们应该如何去降低代码报错带来的影响呢? 我们…

用HAL库改写江科大的stm32入门-6-3 PWM驱动LED呼吸灯

接线图: 2 :实验目的: 利用pwm实现呼吸灯。 关键PWM定时器设置: 代码部分: int main(void) {/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*…

【再探】设计模式—访问者模式、策略模式及状态模式

访问者模式是用于访问复杂数据结构的元素,对不同的元素执行不同的操作。策略模式是对于具有多种实现的算法,在运行过程中可动态选择使用哪种具体的实现。状态模式是用于具有不同状态的对象,状态之间可以转换,且不同状态下对象的行…

使用shell命令开启隧道转发的方式

1.适用场景 中转电脑可以通公网,也可以通内网,想把内网映射出去,公网其他电脑就可以通过该隧道远程访问内网的情况 2.命令 开隧道(21235是自定义的转发端口): ssh -R 21235:内网地址:ssh端口 用户名公网服…

【C语言】基于C语言实现的贪吃蛇游戏

【C语言】基于C语言实现的贪吃蛇游戏 🔥个人主页:大白的编程日记 🔥专栏:C语言学习之路 文章目录 【C语言】基于C语言实现的贪吃蛇游戏前言一.最终实现效果一.Win32 API介绍1.1Win32 API1.2控制台程序1.3控制台屏幕上的坐标COORD…

编程学习 (C规划) 6 {24_4_18} 七 ( 简单扫雷游戏)

首先我们要清楚扫雷大概是如何实现的: 1.布置雷 2.扫雷(排查雷) (1)如果这个位置是雷就炸了,游戏结束 (2)如果不是雷,就告诉周围有几个雷 3.把所有不是雷的位置都找…

蓝桥杯单片机第五届国赛题目

前言:针对串口的练手,此处只作代码记录,不进行分析和展示 目录 题目代码底层驱动主程序核心代码 题目 代码 注:EEPROM的五组后丢弃用一个记录次数的变量进行循环即可,我没有写这一部分代码。 底层驱动 IIC unsign…

[深度学习]yolov10+deepsort+pyqt5实现目标追踪

YOLOv10DeepSORTPyQt5实现目标追踪系统 在现代智能监控系统中,目标追踪技术扮演着至关重要的角色。结合YOLOv10(一种先进的实时目标检测算法)与DeepSORT(一种多目标追踪算法),并通过PyQt5构建用户界面&…

java——网络原理初识

T04BF 👋专栏: 算法|JAVA|MySQL|C语言 🫵 小比特 大梦想 目录 1.网络通信概念初识1.1 IP地址1.2端口号1.3协议1.3.1协议分层协议分层带来的好处主要有两个方面 1.3.2 TCP/IP五层 (或四层模型)1.3.3 协议的层和层之间是怎么配合工作的 1.网络通信概念初识…

再度“痛失”TOP5的小米手机,能否接好这碗AI“大活水”?

国产手机终端需求持续修复,国产品牌商是最大受益者。 近日,中国信通院发布2024年4月国内手机市场运行分析报告。报告显示,今年4月,国内市场手机出货量同比增长了28.8%。按品牌来看,国产品牌手机4月出货量占同期手机出…

港口利器:ModbusTCP转CAN轻松连接,提升跨运车效率!

BXKJ系列嵌入式通信模块,宛如一把神奇的钥匙,打开了与特定工业网络沟通的神秘之门。这些模块的可互换性,赋予了用户自由连接至任何所需网络的无限可能。它们与众多主流现场总线和工业以太网网络无缝对接,包括但不限于Profibus、De…

JVM哪些区域可能出现内存溢出,哪些地方需要GC?

GC顾名思义也就是垃圾回收,有人的地方就有江湖,那有数据的地方也理应有垃圾回收,所以思考一下,沿着之前提到过的JVM内存分区,堆,栈,程序计数器,方法区 堆、栈、方法区…

信息学奥赛初赛天天练-17-阅读理解-浮点数精准输出与海伦公式的巧妙应用

PDF文档公众号回复关键字:20240531 1 2023 CSP-J 阅读程序1 阅读程序(程序输入不超过数组成字符串定义的范围:判断题正确填√,错误填;除特殊说明外,判断题1.5分,选择题3分,共计40分&#xff0…

C51单片机开发--库函数

知不足而奋进 望远山而前行 目录 系列文章目录 文章目录 前言 目标 内容 开发过程回顾 使用库函数点灯 什么是库函数? 面向库函数和面向寄存器开发 使用delay模块延时 总结 前言 在嵌入式系统开发中,使用库函数是提高开发效率、简化编程的重要手段之一…

Codeforces Round 949 (Div. 2) (A~C)

1981A - Turtle and Piggy Are Playing a Game 贪心,每次取x 2,求最大分数 // Problem: B. Turtle and an Infinite Sequence // Contest: Codeforces - Codeforces Round 949 (Div. 2) // URL: https://codeforces.com/contest/1981/problem/B // Me…

使用CS抓取WIN2012明文密码

目录 实验概述: 开始实验: 实验准备: 打开CS: 生成木马控制wind2012: 抓取明文密码: 实验概述: win2012及win10版本是不允许将明文密码储存在内存中的,此时我们…

【模型架构】学习RNN、LSTM、TextCNN和Transformer以及PyTorch代码实现

一、前言 在自然语言处理(NLP)领域,模型架构的不断发展极大地推动了技术的进步。从早期的循环神经网络(RNN)到长短期记忆网络(LSTM)、Transformer再到当下火热的Mamba(放在下一节&a…

高并发项目-分布式Session解决方案

分布式Session解决方案 1.保存Session,进入商品列表页面 1.保存Session 1.编写工具类 1.MD5Util.java package com.sxs.seckill.utils;import org.apache.commons.codec.digest.DigestUtils;/*** Description: MD5加密工具类** Author sun* Create 2024/5/5 14…

云原生架构相关技术_1.容器技术

1.容器技术的背景与价值 容器作为标准化软件单元,它将应用及其所有依赖项打包,使应用不再受环境限制,在不同计算环境间快速、可靠地运行。容器部署模式与其他模式的比较如下图1所示。 图1 传统、虚拟化、容器部署模式比较 Docker容器基于操作…