Redis 和 Mysql 数据库数据如何保持一致性
Redis 和 Mysql 数据库数据如何保持一致性
保持Redis和MySQL数据库数据一致性是一个常见且重要的问题,特别是在使用Redis作为MySQL数据库的缓存层时。以下是几种常用的保证二者数据一致性的策略和方法:
-
双写一致性(同步更新):
-
先更新MySQL,后更新Redis:
- 在业务代码中,首先执行对MySQL的写操作,待该操作成功后,立即更新Redis中的对应缓存数据。这种方式简单直接,但存在短暂窗口期内数据不一致的风险,即在MySQL更新后、Redis更新前,如果有请求读取缓存,可能会获取到旧数据。

-
先更新Redis,后更新MySQL:
- 反之,先更新Redis,然后更新MySQL。这种方式同样存在类似的风险,即在Redis更新后、MySQL更新前,如果有请求直接查询数据库(如缓存未命中或被主动刷新),可能会看到新缓存数据与旧数据库数据之间的不一致。

-
-
异步更新:
- 使用消息队列:
- 当MySQL数据更新时,将更新事件发送到消息队列(如RabbitMQ、Kafka等)。消费者服务监听队列,接收到消息后异步地更新Redis缓存。这种方法可以缓解同步更新时的性能压力,但增加了系统的复杂性,并且需要处理消息丢失、重复消费等问题以保证最终一致性。
- 使用消息队列:
-
基于MySQL Binlog的更新:
- 订阅Binlog:
- 利用工具(如Canal、Maxwell、Debezium等)订阅MySQL的二进制日志(Binlog),当MySQL数据发生变化时,这些工具能够实时捕获并解析Binlog事件,然后将更新信息推送到Redis,自动更新缓存。这种方法可以近乎实时地保持数据一致性,且对业务代码无侵入,但需要额外部署和维护Binlog订阅服务。
- 订阅Binlog:
-
使用版本号或时间戳:
- 在数据模型中引入版本号或时间戳字段,每次更新时同时更新MySQL和Redis中的相应字段。在读取数据时,可以通过比较版本号或时间戳来判断缓存是否过期,从而决定是否从数据库重新加载数据。这种方法有助于解决缓存与数据库数据版本冲突问题,但需要在业务逻辑中处理版本比较逻辑。
-
Redis事务:
- Redis本身支持事务(MULTI/EXEC命令),可以在一个事务中执行一系列操作,保证这些操作的原子性。对于涉及MySQL和Redis的更新操作,可以尝试将它们封装在Redis事务中执行,但需要注意的是,这并不能跨越Redis和MySQL两个不同的系统实现真正的分布式事务,只能保证Redis内部操作的原子性。
-
普通双删策略:

1、线程A先删除缓存,再更新数据库,再删除缓存
2、线程B查询缓存没有数据,在线程A更新数据库之前,查询到旧数据,此时系统时间片切换到线程A执行删除缓存,之后又轮到线程B放入缓存旧数据
3、线程C针对于线程A,查询缓存没有数据,查询到旧数据,放入缓存旧数据
都不能满足缓存和数据一致性。 -
延迟双删策略:
- 在更新MySQL后,立即删除Redis缓存,然后设置一个短时延(如几毫秒)后再次删除缓存。这样可以尽量减少在第一次删除缓存到MySQL更新生效期间,新数据被缓存的可能性。

1、线程A先删除缓存,之后更新数据库
2、线程B和线程C发现缓存没数据,查询数据库。线程B查询到的是旧数据,线程C查询到的是新数据。之后纷纷放入缓存
3、线程A延时3-5秒(时间一般要大于SQL执行时间+线程切换执行时间100ms足够),再将缓存删除。之后其他线程再查询缓存,发现没数据,再次查询数据库及放入缓存都是新数据
极端情况就是线程D,所以延时双删还是不一定能保证缓存及数据一致。
-
延迟双删策略:
1、在发现缓存没有数据后,在执行查询数据库前,对该Key进行加锁,查询数据库并放入缓存后再解锁,这样可以避免缓存击穿问题,当某个redis数据不存在时,大量线程并发查询数据库。
2、在需要执行双删前,对该Key进行加锁,之后执行删除缓存,更新数据库,放入新数据到缓存,在解锁。保证缓存和数据一致性。
3、加锁的Key都需要设置过期时间,避免因为宕机造成死锁。
综合考虑,选择哪种方法取决于具体的应用场景、数据一致性要求、系统复杂性接受程度以及运维成本等因素。实践中,常采用组合策略,如结合使用消息队列与Binlog订阅,或者在业务代码中直接同步更新的同时,辅以定期的数据校验与修复机制,以提高数据一致性的保障程度。
相关文章:
Redis 和 Mysql 数据库数据如何保持一致性
Redis 和 Mysql 数据库数据如何保持一致性 保持Redis和MySQL数据库数据一致性是一个常见且重要的问题,特别是在使用Redis作为MySQL数据库的缓存层时。以下是几种常用的保证二者数据一致性的策略和方法: 双写一致性(同步更新)&…...
探索7个MAMP本地开发环境的高效替代软件
什么是本地开发环境 本地开发环境是Web开发环境中的一种类型,它是指开发者自己的计算机上配置的一套用于开发和测试网站或应用程序的软件集合。这套环境使得开发者可以在本地计算机上构建和测试网站,而无需实时部署到服务器。 创建本地开发环境有两种方…...
靡语IT:Bootstrap 简介
1.1 Bootstrap 简介:什么是 Bootstrap? Bootstrap 是一个用于快速开发 Web 应用程序和网站的前端框架。Bootstrap是前端开发中比较受欢迎的框架,简洁且灵活。它基于HTML、CSS和JavaScript,HTML定义页面元素,CSS定义页面布局&…...
亚马逊店铺引流:海外云手机的利用方法
在电商业务蓬勃发展的当下,亚马逊已经成为全球最大的电商平台之一,拥有庞大的用户群和交易量。在激烈的市场竞争中,如何有效地吸引流量成为亚马逊店铺经营者所关注的重点。海外云手机作为一项新兴技术工具,为亚马逊店铺的流量引导…...
10 Python进阶:MongoDB
MongoDb介绍 MongoDB是一个基于分布式架构的文档数据库,它使用JSON样式的数据存储,支持动态查询,完全索引。MongoDB是NoSQL数据库的一种,主要用于处理大型、半结构化或无结构化的数据。以下是MongoDB数据库的一些关键特点和优势&a…...
Leetcode 142. 环形链表 II和Leetcode 242. 有效的字母异位词
文章目录 Leetcode 142. 环形链表 II题目描述C语言题解解题思路 Leetcode 242. 有效的字母异位词题目描述C语言题解和思路解题思路 Leetcode 142. 环形链表 II 题目描述 给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返…...
【嵌入式DIY实例】-MODBUS串行通信
MODBUS串行通信 文章目录 MODBUS串行通信1、什么是RS-4852、MAX485 TTL转RS485转换器3、硬件准备4、代码实现4.1 主机和从机之间简单通信4.2 主/从机之间LED控制在本文中,我们将介绍如何使用 MAX485 MODBUS 在Arduino之间进行串行通信。 我们将使用 Arduino nano 板和 MODBUS …...
入门用Hive构建数据仓库
在当今数据爆炸的时代,构建高效的数据仓库是企业实现数据驱动决策的关键。Apache Hive 是一个基于 Hadoop 的数据仓库工具,可以轻松地进行数据存储、查询和分析。本文将介绍什么是 Hive、为什么选择 Hive 构建数据仓库、如何搭建 Hive 环境以及如何在 Hi…...
【计算机网络】会话层
负责维护两个会话主机之间链接的建立、管理和终止,以及数据的交换。 会话控制:决策该由谁来传递数据 令牌管理:禁止双方同时执行一个关键动作 同步功能:在一个长的传输过程中设置一些断点,以便系统崩溃后能恢复至崩…...
springboot实现七牛云的文件上传下载
一:依赖包 <dependency><groupId>com.qiniu</groupId><artifactId>qiniu-java-sdk</artifactId><qiniu-java-sdk.version>7.7.0</qiniu-java-sdk.version></dependency>二:具体实现 RestController RequestMapping…...
【RISC-V 指令集】RISC-V 向量V扩展指令集介绍(六)- 向量内存一致性模型
1. 引言 以下是《riscv-v-spec-1.0.pdf》文档的关键内容: 这是一份关于向量扩展的详细技术文档,内容覆盖了向量指令集的多个关键方面,如向量寄存器状态映射、向量指令格式、向量加载和存储操作、向量内存对齐约束、向量内存一致性模型、向量…...
Lvgl9 WindowsSimulator Visual Studio2017
因为在操作过程中遇到了一些错误,所以将操作及解决问题的过程记录下来。 一、下载lv_port_pc_visual_studio github链接:GitHub - lvgl/lv_port_pc_visual_studio: Visual Studio projects for LVGL embedded graphics library. Recommended on Windows. Linux su…...
【STL】链表(list)
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。 链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个…...
node.js常用指令
1、node:启动 Node.js REPL(交互式解释器)。 node 2、node [文件名]:执行指定的 JavaScript 文件。 node app.js 3、npm init:初始化一个新的 Node.js 项目,生成 package.json 文件。 此命令会创建一个…...
Flutter第六弹 基础列表ListView
目标: 1)Flutter有哪些常用的列表组建 2)怎么定制列表项Item? 一、ListView简介 使用标准的 ListView 构造方法非常适合只有少量数据的列表。我们还将使用内置的 ListTile widget 来给我们的条目提供可视化结构。ListView支持…...
【考研经验贴】24考研860软件工程佛系上岸经验分享【丰富简历、初复试攻略、导师志愿、资料汇总】
😊你好,我是小航,一个正在变秃、变强的文艺倾年。 🔔本文讲解24考研860软件工程佛系上岸经验分享【丰富简历、初复试攻略、导师志愿、资料汇总】,期待与你一同探索、学习、进步,一起卷起来叭! 目…...
15-1-Flex布局
个人主页:学习前端的小z 个人专栏:HTML5和CSS3悦读 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结,欢迎大家在评论区交流讨论! 文章目录 Flex布局1 Flex容器和Flex项目2 Flex 容器属性2.1 主轴的方向2.2 主轴对齐方式…...
深入浅出 -- 系统架构之负载均衡Nginx的性能优化
一、Nginx性能优化 到这里文章的篇幅较长了,最后再来聊一下关于Nginx的性能优化,主要就简单说说收益最高的几个优化项,在这块就不再展开叙述了,毕竟影响性能都有多方面原因导致的,比如网络、服务器硬件、操作系统、后端…...
AI大模型下的策略模式与模板方法模式对比解析
🌈 个人主页:danci_ 🔥 系列专栏:《设计模式》《MYSQL应用》 💪🏻 制定明确可量化的目标,坚持默默的做事。 🚀 转载自热榜文章:设计模式深度解析:AI大模型下…...
前端| 富文本显示不全的解决方法
背景 前置条件:编辑器wangEditor vue项目 在pc端进行了富文本操作, 将word内容复制到编辑器中, 进行发布, pc端正常, 在手机端展示的时候 显示不全 分析 根据h5端编辑器内容的数据展示, 看到有一些样式造…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
sqlserver 根据指定字符 解析拼接字符串
DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...
【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...
七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
