我的编程空间,编程开发者的网络收藏夹
学习永远不晚

浅谈Redis跟MySQL的双写问题解决方案

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

浅谈Redis跟MySQL的双写问题解决方案

项目中有遇到这个问题,跟MySQL中的数据不一致,研究一番发现这里面细节并不简单,特此记录一下。

写在前面

严格意义上任何非原子操作都不可能保证一致性,除非用阻塞读写实现强一致性,所以缓存架构我们追求的目标是最终一致性。
缓存就是通过牺牲强一致性来提高性能的。

这是由CAP理论决定的。缓存系统适用的场景就是非强一致性的场景,它属于CAP中的AP。

以下3 种缓存读写策略各有优劣,不存在最佳。

三种读写缓存策略

Cache-Aside Pattern(旁路缓存模式)

Cache-Aside Pattern,即旁路缓存模式,它的提出是为了尽可能地解决缓存与数据库的数据不一致问题。

在这里插入图片描述

:从缓存读取数据,读到直接返回。如果读取不到的话,从数据库加载,写入缓存后,再返回响应。
:更新的时候,先更新数据库,然后再删除缓存

在这里插入图片描述

Read-Through/Write-Through(读写穿透)

Read/Write Through Pattern 中服务端把 cache 视为主要数据存储,从中读取数据并将数据写入其中。cache 服务负责将此数据读取和写入 DB,从而减轻了应用程序的职责。

因为我们经常使用的分布式缓存 Redis 并没有提供 cache 将数据写入DB的功能,所以使用并不多。

:先查 cache,cache 中不存在,直接更新 DB。cache 中存在,则先更新 cache,然后 cache 服务自己更新 DB(同步更新 cache和DB)。

:从 cache 中读取数据,读取到就直接返回 。读取不到的话,先从 DB 加载,写入到 cache 后返回响应。

Write Behind Pattern(异步缓存写入)

Write Behind Pattern 和 Read/Write Through Pattern 很相似,两者都是由 cache 服务来负责 cache 和 DB 的读写。

但是,两个又有很大的不同:Read/Write Through 是同步更新 cache 和 DB,而 Write Behind Caching 则是只更新缓存,不直接更新 DB,而是改为异步批量的方式来更新 DB。

很明显,这种方式对数据一致性带来了更大的挑战,比如cache数据可能还没异步更新DB的话,cache服务可能就挂掉了,反而会带来更大的灾难。

这种策略在我们平时开发过程中也非常非常少见,但是不代表它的应用场景少,比如消息队列中消息的异步写入磁盘、MySQL 的 InnoDB Buffer Pool 机制都用到了这种策略。

Write Behind Pattern 下 DB 的写性能非常高,非常适合一些数据经常变化又对数据一致性要求没那么高的场景,比如浏览量、点赞量。

旁路缓存模式解析

Cache Aside Pattern 的一些疑问

旁路缓存模式是我们平时中使用最多的。下面根据上面介绍的旁路缓存模式,我们可以有以下几个疑问。

为什么写操作是删除缓存,而不是更新缓存

:线程A先发起一个写操作,第一步先更新数据库。线程B再发起一个写操作,第二步更新了数据库,由于网络等原因,线程B先更新了缓存,线程A更新缓存。

这时候,缓存保存的是A的数据(老数据),数据库保存的是B的数据(新数据),数据不一致了,脏数据出现啦。如果是删除缓存取代更新缓存则不会出现这个脏数据问题。

实际上要写操作的时候更新缓存也是可以的,不过我们需要加一个锁/分布式锁来保证更新cache的时候不存在线程安全问题。

在写数据的过程中,为什么要先更新DB在删除缓存

:比如说请求1 是写操作,要是先删除缓存A,请求2是读操作,先读缓存A,发现缓存被删除了(被请求1删除了),然后去读数据库,但是此时请求1还没来得及把数据及时更新,那么请求2读的就是旧数据,并且请求2还会把读到的旧数据放到缓存中,造成了数据的不一致。

其实要先删缓存,再更新数据库也是可以,如采用延时双删策略
休眠1秒,再次淘汰缓存 这么做,可以将1秒内所造成的缓存脏数据,再次删除。不一定是1秒,看你业务决定的,不过不推荐这种做法,因为在这1秒内可能发生因素很多,它的不确定性太大。

在写数据的过程中,先更新DB,后删除cache就没有问题了么?

答: 理论上来说还是可能会出现数据不一致性的问题,不过概率非常小。

假设这会有两个请求,一个请求A做查询操作,一个请求B做更新操作,那么会有如下情形产生

(1)缓存刚好失效
(2)请求A查询数据库,得一个旧值
(3)请求B将新值写入数据库
(4)请求B删除缓存
(5)请求A将查到的旧值写入缓存 ok,如果发生上述情况,确实是会发生脏数据。

然而,发生这种情况的概率并不高

发生上述情况有一个先天性条件,就是步骤(3)的写数据库操作比步骤(2)的读数据库操作耗时更短,才有可能使得步骤(4)先于步骤(5)。

可是,仔细想想,数据库的读操作的速度远快于写操作的(不然做读写分离干嘛,做读写分离的意义就是因为读操作比较快,耗资源少),因此步骤(3)耗时比步骤(2)更短,这一情形很难出现。

还有其他造成不一致的原因么?

答: 如果删除缓存过程中失败了就会造成不一致问题

如何解决?
使用Canal去订阅数据库的binlog,获得需要操作的数据。另起一个程序,获得这个订阅程序传来的信息,进行删除缓存操作。

Cache Aside Pattern 的缺陷

缺陷1:首次请求数据一定不在 cache 的问题

解决办法:可以将热点数据提前放入cache 中。

缺陷2:写操作比较频繁的话导致cache中的数据会被频繁被删除,这样会影响缓存命中率 。

数据库和缓存数据强一致场景 :更新DB的时候同样更新cache,不过我们需要加一个锁/分布式锁来保证更新cache的时候不存在线程安全问题。可以短暂地允许数据库和缓存数据不一致的场景 :更新DB的时候同样更新cache,但是给缓存加一个比较短的过期时间,这样的话就可以保证即使数据不一致的话影响也比较小。

到此这篇关于浅谈Redis跟MySQL的双写问题解决方案的文章就介绍到这了,更多相关Redis MySQL双写内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

浅谈Redis跟MySQL的双写问题解决方案

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Redis跟MySQL的双写问题怎么解决

本文小编为大家详细介绍“Redis跟MySQL的双写问题怎么解决”,内容详细,步骤清晰,细节处理妥当,希望这篇“Redis跟MySQL的双写问题怎么解决”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。写在前面严格意
2023-06-29

Redis与MySQL的双写一致性问题怎么解决

本篇内容介绍了“Redis与MySQL的双写一致性问题怎么解决”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Redis与MySQL双写一致性
2023-07-05

Redis大Key问题的解决方案

目录什么是大Key问题负面影响产生原因找出大Key解决方案什么是大Key问题Redis中某些键(key)所对应的值(value)特别大,或者集合类数据结构(如hash、set、zset、list)中存储的元素数量过多,这就是大Key问题。
Redis大Key问题的解决方案
2024-09-26

Mysql和redis缓存不一致问题的解决方案

目录一.问题描述二.解决方案1.给缓存数据设置过期时间2.缓存延时双删3.删除缓存重试机制4.读取biglog异步删除缓存三.总结一.问题描述Redis、mysql双写缓存不一致:在更新缓存方面,对于更新完数据库,是更新缓存呢,还是删除缓
2022-08-16

MYSQL中文乱码问题的解决方案

目录一、乱码的原因:二、查看数据库的编码方式三、解决的办法有俩种:四、本人在项目遇到乱码问题是以下方法解决的总结一、乱码的原因:1、 client客户端的编码不是utf82、server端的编码不是utf83、database数据库的
2022-06-13

Redis Hash序列化存储的问题及解决方案

目录SDR序列化方式有多种对Redis的存储设置是我自己写的更改序列化方法更改序列化方式继续使用JdkSerializationRedisSerializer这里说的是Spring Data Redis(一下简称SDR)设置Hash存储的序
2022-11-19

常见的MySQL锁问题及其解决方案

MySQL 锁的常见问题与解决方案MySQL 是一种常用的关系型数据库管理系统,它使用锁来实现并发控制,保证数据的一致性和完整性。然而,MySQL 锁的使用也会带来一些问题。本文将介绍一些常见的 MySQL 锁的问题,并提供相应的解决方案。
常见的MySQL锁问题及其解决方案
2023-12-21

MySQL深分页问题的原因及解决方案

目录前言第一部分:深分页问题的背景和影响什么是深分页?深分页的影响实际场景中的问题第二部分:mysql 索引结构和查询执行流程MySQL 索引概述查询执行流程深分页查询的问题案例分析第三部分:深分页性能下降的原因1. 索引扫描的局限性2.
MySQL深分页问题的原因及解决方案
2024-09-29

MYSQL的binary解决mysql数据大小写敏感问题的方法

BINARY不是函数,是类型转换运算符,它用来强制它后面的字符串为一个二进制字符串,可以理解为在字符串比较的时候区分大小写
2022-11-15

Win7和Ubuntu12.04 双系统重装win7引导不见问题的解决方案

重装系统,导致原来的Ubuntu12.04和win7双系统的引导不见了,所以在此进行一下说明,如何修复. 1. win7和ubuntu12.04双系统引导修复 问题描述: 在重装Win7后,启动后发现原来ubuntu 12.04(U盘安装)
2023-06-02

MySQL中事务处理的常见问题和解决方案

MySQL中事务处理的常见问题和解决方案在数据库操作中,事务处理是非常重要的,它可以确保数据库操作的一致性和完整性。然而,在MySQL中进行事务处理时,常常会遇到一些问题。本文将介绍常见的MySQL事务处理问题,并提供相应的解决方案。问题一
2023-10-22

浅析MySQL中主从延迟问题的原因与解决方法

MySQL主从延迟指主库与从库的数据复制时间差。造成延迟的原因有网络延迟、硬件瓶颈、SQL线程饱和、IO密集操作、锁竞争等。解决方法包括优化网络延迟、硬件性能,优化SQL线程、减少IO密集操作,优化锁竞争,确保binlog格式兼容,管理slave_pending_jobs队列,以及其他优化措施。
浅析MySQL中主从延迟问题的原因与解决方法
2024-04-02

Redis 实现分布式锁时需要考虑的问题解决方案

目录引言第一部分:什么是分布式锁?1.1 分布式锁的定义1.2 分布式锁的特性1.3 分布式锁的应用场景第二部分:Redis 实现分布式锁的基本原理2.1 Redis 的原子性操作2.2 锁的自动释放机制2.3 Redis 分布式锁的基本流
Redis 实现分布式锁时需要考虑的问题解决方案
2024-09-29

编程热搜

目录