教你如何应对面试官提问你Redis 缓存数据库一致性时

Redis 缓存数据库一致性手撕面答 一种懒加载的思想,因为每次更改数据之后,不一定立马就有人来用。若更新的次数远大于读取的次数,此时会频繁更新缓存,但一直没人使用,若缓存更新的成本很高的话,此时会非常浪费性能资源。 阅读详情

引言

自Redis入门篇过后,已经好久没更Redis了,接下来应该从实战篇,原理篇,面试篇几个层次来展开,本篇主要是实战篇中的数据库缓存一致性问题,以问题形式展开,应对面试场景作答【melo称其为"手撕面答"】,尽量简短,某些部分可能不会进行详细介绍。

为什么是删除缓存而不是更新缓存?

懒加载

一种懒加载的思想,因为每次更改数据之后,不一定立马就有人来用。 若更新的次数远大于读取的次数,此时会频繁更新缓存,但一直没人使用,若缓存更新的成本很高的话,此时会非常浪费性能资源。

并发更新的情况

ABBA 【A的操作过程中,穿插了B的完整过程】

  1. A更新数据库为1

  2. B更新数据库为2

  3. B更新缓存为2

  4. A更新缓存为1

最后导致数据库最终是2,但缓存是1,也就是B的缓存更新丢失了

​

为什么要先更新数据库,再删除缓存

若先删除缓存,再更新数据库的话:

  1. A线程删除缓存

  2. B线程查询数据,缓存中没有了,会去计算数据库,设置缓存【此时计算出来的缓存是旧数据,是数据库更新之前的数据】

  3. A线程再更新数据库

接下来的查询,一直走的是缓存,也就是旧数据,这样就出现了数据库和缓存中数据不一致的情况

若先更新数据库,再删除缓存的话

  1. A线程更新数据库

  2. B线程查询数据,此时还未删除缓存,缓存中还有,得到的就是旧的缓存数据【此时就出现了数据库和缓存中数据不一致的情况】

  3. A线程再删除缓存

A读B写【先更后删可能会有数据不一致的情况,但很少见】

  1. A读取,发现缓存刚好过期了

  2. A查询出数据库的旧值,在设置缓存之前

  3. B更新数据库,并删除了缓存

  4. A用旧值,设置了缓存【缓存中是旧的数据,数据库是新的】

但由于缓存的写入要快于MySQL的写入,一般不可能在2跟4之间,穿插一个3操作【3还操作了数据库】

  • 如果顺序是【2,4,3】的话,A设置了缓存之后也没关系,因为后续B还会再次删除缓存

  • 之后的查询,发现缓存过期会去数据库中查询得到最新的数据

如何解决A读B写时先更后删的极端情况?

延时双删

  1. A读取,发现缓存失效了,此时去查询数据库【查出旧值】

  2. B更新数据库

  3. B设置新缓存

  4. A设置缓存为旧值

到这一步,如果之后的查询,查到的都会是旧的缓存,所以我们可以

  1. 延时500毫秒

延时500毫秒是为了让B能够更新完数据库,我们再次查询数据库才能获得最新的值,来设置缓存

  1. 删除缓存

先删除缓存,后更新数据库如果也出现类似上边的问题怎么办?

假设一个场景:

  • 请求A进行写操作,删除缓存

  • 请求B查询发现缓存不存在

  • 请求B去数据库查询得到旧值

  • 请求B将旧值写入缓存

  • 请求A将新值写入数据库

这时候缓存中的数据就是脏数据,如果缓存没有设置过期时间的话,就导致这个数据在下一次修改之前返回给用户的都是脏数据。

 

从后者操作可能失败的角度来看,选择哪种策略更好一点?

先更新后删除缓存的话,后者失败,情况是这样的:

  1. A更新数据库,然后缓存没有删除成功

  2. B查询,直接走了缓存【旧数据】

这就出现了缓存跟数据库不一致的情况

先删除缓存后更新数据库的话,后者失败,情况是这样的:

  1. A删除缓存,然后没能更新数据库

  2. B查询,发现缓存没有,则去查询数据库,设置到缓存里边

此时并不会出现缓存跟数据库不一致的情况,因为A还没来得及更新,这样数据库跟缓存中,一直都是旧的数据,但至少不会出现数据不一致的问题

  • 所以如果从这个角度来看的话,先删除缓存,后更新数据库才是更优解。

如何解决后者失败的情况呢?

使用消息队列重试

  1. 请求 A 先对数据库进行更新操作,同时吧

  2. 在对 Redis 进行删除操作的时候发现报错,删除失败

  3. 此时将Redis 的 key 作为消息体发送到消息队列中

  4. 系统接收到消息队列发送的消息后再次对 Redis 进行删除操作

​

 

但是这个方案会有一个缺点就是会对业务代码造成大量的侵入,深深的耦合在一起。

有没有必要更新成功后就投递到mq呢?而不是等到redis删除失败了再投递到mq

如果考虑Java项目进程在更新数据库之后就宕机了的话,那无论哪种都没法避免缓存删除的失败 如果硬抠的话,更新成功后,到删除redis还有一段间隙,这个间隙先投递到mq,会更有保障一点,但相应的编码规则也更麻烦了点

  1. 更新数据库成功,投递到mq表示要删除 某个key

  2. 业务继续执行,删除redis: 删除成功的话,需要删除掉mq里边的消息,防止重复消费 删除失败的话,就需要消费者拉取mq,再次删除缓存,实现重试机制,当然,如果重试超过的一定次数,还是没有成功,我们就需要向业务层发送报错信息了。后续的处理可能就先丢到死信队列里边了。

可以发现编码确实麻烦了些,因为要考虑重复消费的问题。那么如何解决呢?Java崩了,咱下游还有 mysql 和 mq 没崩呢!也就因此引出了下文的订阅binlog日志的方法

订阅binlog日志

原理:更新数据库成功,就会产生一条变更日志,记录在 binlog 里。

于是我们就可以通过订阅 binlog 日志,拿到具体要操作的数据,然后再执行缓存删除,阿里巴巴开源的 Canal 中间件就是基于这个实现的。

具体流程:

  1. canal模拟mysql slave的交互协议,伪装自己为mysql slave,向mysql master发送dump协议;

  2. mysql master收到dump请求,开始推送binary log给slave(也就是canal);

  3. canal解析binary log对象(原始为byte流);

  4. canal将解析后的对象,根据业务场景,分发到比如 MySQL 、RocketMQ 或者 ES 中。

​

 

总结

 

如何解决数据一致性问题?如何保证缓存与数据库的双写一致性? 如何保证缓存与数据库的双写一致性?   面试题 如何保证缓存与数据库的双写一致性? 面试官心理分析 你只要用缓存,就可能会涉及到缓存与数据库双存储双写,你只要是双写,就一定会有数据一致性的问题,那么你如何解决一致性问题? 面试题剖析 一般来说,如果允许缓存可以稍微的跟数据库偶尔有不一致的情况,也就是说如果你的系统不是严格要求 “缓存+数据库” 必须保持一致性的话,最好不要做这个方... 阅读详情

相关推荐

面试官:如何保障数据库和redis缓存的一致性

随着互联网的高速发展,使用互联网产品的人也越来越多,团队不可避免得也会面对越来越复杂的高并发业务场景(如下图),比如热点视频/文章的观看(读场景),热点视频/文章的评论,点赞等(写场景)。 众所周知,数据库是把数据存储在磁盘上,访问时需要进行IO操作,在请求量小的情况下,耗时还比较低。但随着数据量的增大,访问量的集中,整个数据库负担加重,响应就会变慢,请求延时上升。进而导致用户侧...

ln152315的专栏 3393

Cache Aside Pattern缓存+数据库读写模式的分析

1、Cache Aside Pattern (1)读的时候,先读缓存,缓存没有的话,那么就读数据库,然后取出数据后放入缓存,同时返回响应 (2)更新的时候,先删除缓存,然后再更新数据库 2、为什么是删除缓存,而不是更新缓存呢? 原因很简单,很多时候,复杂点的缓存的场景,因为缓存有的时候,不简单是数据库中直接取出来的值 商品详情页的系统,修改库存,只是修改了某个表的某些字段,但是要真正把这个影响的最...

lihuan666的博客 399

大厂面试官问我:Redis缓存如果扛不住,该怎么办?【后端八股文十一:Redis缓存八股文合集(1)】

Redis优化缓存结构 (1)使用Redis和Cache 多级缓存; (2)Caffine+Redis+ES 做三级缓存; (3)使用 Redis 实现分布式缓存,另外配合 Nginx 缓存 + 本地 Caffeine 缓存 + CDN 缓存 + 浏览器缓存共同实现多级缓存来保证系统的性能。 (4)使用mq转发(来自京东技术:营销权益平台春晚技术探究): 本地缓存的构建的两种方式: 一级缓存:本地+mysql+推模式更新。 两级缓存:本地+r2m+mysql+推模式更新。

qq_33445788的博客 2340

Cache-Aside缓存模式写请求时,为何是删除缓存,而不是更新缓存

Cache-Aside缓存模式写请求时,为何是删除缓存,而不是更新缓存

oldboy1999的博客 1121

链路聚合Eth-trunk以及华为交换机配置实例

链路聚合简介 以太网链路聚合Eth-Trunk简称链路聚合,它通过将多条以太网物理链路捆绑在一起成为一条逻辑链路,从而实现增加链路带宽的目的。同时,这些捆绑在一起的链路通过相互间的动态备份,可以有效地提高链路的可靠性。 目的: 随着网络规模不断扩大,用户对骨干链路的带宽和可靠性提出越来越高的要求。在传统技术中,常用更换高速率的接口板或更换支持高速率接口板的设备的方式来增加带宽,但这种方案需要付出高额的费用,而且不够灵活。 采用链路聚合技术可以在不进行硬件升级的条件下,通过将多个物理接口捆绑为一个逻辑接口

ChaseAug的博客 2万+

中兴B860AV2.1-A刷机避坑指南:晶晨免拆神器+安卓7.1.2固件实测

本文提供中兴B860AV2.1-A机顶盒的详细刷机教程,重点介绍使用晶晨免拆神器配合安卓7.1.2线刷固件包的实操步骤。内容涵盖刷机前的硬件确认、工具准备、软件设置、烧录全过程监控及常见问题解决,旨在帮助用户安全、高效地完成刷机,规避变砖风险,释放设备潜力。

pytorch8learner的博客 750

Canal 实战 | SpringBoot 整合 Canal + RabbitMQ 实现监听 MySQL 数据库同步更新 Redis 缓存

前言:如何保证redis与mysql数据一致性呢? 网上大部份答案都是延迟双删, 现在我就将另外一个解方案分享给大家,我自己也在最近项目中应有上来了。 1、开启 biglog 日志 (根据自己mysql配置文件位置更改) vim /etc/my.cnf 添加配置 [mysqld] log-bin=mysql-bin # 开启binlog binlog-format=ROW # 选择ROW模式 server_id=1 # 配置MySQL replaction需要定义,不和Canal的slaveI

weixin_38982591的博客 7344

从“跳变”到“连续”:深入理解霍尔传感器插值与PLL角度估算的优劣与选择

本文深入解析霍尔传感器角度估算技术,对比线性插值法和锁相环(PLL)跟踪法的优劣,为电机控制领域的工程师提供实用指南。通过STM32F407和CubeMX的实例,详细探讨两种方法的实现细节、性能对比及优化策略,帮助在不同应用场景下做出最优选择。

weixin_30855761的博客 563

大厂面试官喜欢这样问Redis,双写一致性、并发竞争、线程模型,我整理好了

你知道的越多,你不知道的越多 点赞再看,养成习惯 前言 Redis在互联网技术存储方面使用如此广泛,几乎所有的后端技术面试官都要在Redis的使用和原理方面对小伙伴们进行360°的刁难。作为一个在互联网公司面一次拿一次offer的面霸(请允许我使用一下夸张的修辞手法),打败了无数竞争对手,每次都只能看到无数落寞的身影失望的离开,略感愧疚,在一个寂寞难耐的夜晚,我痛定思痛,决定开始写《吊...

敖丙 3万+

人工智能渗透测试:自动化安全评估

渗透测试认证的价值包括提高可信度和技能水平,并帮助客户确保由经过认证的个人对其系统进行全面的手动调查。B2B 交互变得越来越复杂,特别是功能丰富的超级应用程序,需要采取强有力的安全预防措施,而自动化渗透测试应用程序则是一种未被发现的武器。渗透测试中的人工智能通过提高效率、自动收集信息、发现隐藏的漏洞、开发个性化攻击和减少误报来提高 B2B 集成的安全性。这包括风险简报、补救建议和战略建议。渗透测试由五个阶段组成,是网络安全中的关键防御措施,它模拟现实世界的攻击,以识别系统缺陷并在漏洞被利用之前解决它们。

weixin_48967543的博客 2367

R语言广义加型模型(GAM)的运用例子及实现教程

一旦拟合了广义加型模型,我们可以查看模型摘要和诊断,以评估模型的质量和拟合情况。# 查看模型摘要响应变量:mpg(汽车的燃油效率)拟合函数:mpg ~ s(hp) + s(wt)

Mrrunsen的博客 3447

面试官:Redis 缓存一致性问题怎么解决,这样回答简直完美。

关于 Redis 的其他的一些面试问题,比如常见的缓存穿透、雪崩、击穿、热点的问题,但是还有一个比较麻烦的问题就是如何保证缓存一致性。 2020整理收集的一线互联网公司面试真题(都整理成文档),有很多干货,包含netty,spring,线程,spring cloud等详细讲解,也有详细的学习规划图,面试题整理等,我感觉在面试这块讲的非常清楚:获取面试资料只需:点击这里领取!!!暗号:优快云 对于缓存和数据库的操作,主要有以下两种方式。 先删缓存,再更新数据库 先删除缓存,数据库还没有更新成功,此时如果读取

a3961401的博客 7786

pytorch 51 GroundingDINO模型导出tensorrt并使用c++进行部署,53ms一张图

博主基于https://github.com/hpc203/GroundingDINO-onnxrun项目分享的onnx c++推理代码,修改为GroundingDINO模型的tensorrt推理代码。对于600x400的输入,在3060显卡下,cuda 12.1,TensorRT-10.4.0,window环境下53ms处理完一张图片。

a486259的博客 1221

面试官:谈谈Redis缓存和MySQL数据一致性问题

前言 原创公众号:bigsai 对于缓存穿透、缓存雪崩和缓存击穿常常出现在面试中,今天来看看它到底是啥吧? redis缓存穿透 理解 重在穿透吧,也就是访问透过redis直接经过mysql,通常是一个不存在的key,在数据库查询为null。每次请求落在数据库、并且高并发。数据库扛不住会挂掉。 解决方案 可以将查到的null设成该key的缓存对象。 当然,也可以根据明显错误的key在逻辑层就就行验证。 同时,你也可以分析用户行为,是否为故意请求或者爬虫、攻击者。针对用户访问做限制。 其他等等

bigsai 5361

如何在Dify中安装运行pandas、numpy库(离线、在线均支持,可提供远程指导)

pandas和numpy这两个库是数据科学和数据分析中经常使用的工具包,原生的Dify无法直接使用这两个库,需要手动安装后才可以使用。本文将介绍如何在Dify中安装pandas和numpy,并在代码执行节点中运行使用pandas和numpy。Dify的代码执行节点中的python逻辑,实际是运行在Dify沙盒中的,因此我们在沙盒中安装pandas和numpy就可以了。如果您有在Dify中添加pandas、numpy的应用需求,欢迎关注作者进行交流。

litlit023的专栏 5635

Unity与iOS原生交互实战指南

C#(DllImport) → C 接口(extern "C") → Objective‑C / SwiftObjective‑C → UnitySendMessage → C#(GameObject + public 方法)在写.mm文件;在里面写;C# 用声明;调用它,参数就是 string / 数值等;在.mm里做你想做的 iOS 原生操作。在 Unity 里准备一个常驻 GameObject,比如;上面挂一个脚本,写;在 iOS 插件中用;

本博客聚焦游戏开发技巧、创业实战心得及大学热门课程干货。这里既有技术深度,也有思维广度,无论你是开发者、创业者还是高校学子,都能在这里找到适合自己的成长之路! 1359

如何保证Redis和数据库的数据一致性

如何保证Redis和数据库的数据一致性

聂可以的博客 3752

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

面试官常拷打:如何下保证MySQL数据库与Redis缓存数据一致性?

⚠️注意:每一种方案的背后都有利与弊,每一个方案细节都可能被面试官挖出来拷打,面试现场我们都应该沉着冷静。面试官拷打的目的,抛开是面试官为了炫耀自己牛逼之外,更多的是希望看到应聘者看待问题的角度和解决问题的思路。看完就算是优化后的方案,发现其实没有所谓的最优解,只有根据自己项目业务特点和技术条件的来选择合适的方案。背后是业务复杂度、性能、可用资源以及对数据一致性的容忍度等维度的一个综合衡量。

qq_31857297的博客 1481

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

面试官:MySQL 数据库和 Redis 缓存的数据一致性如何得到保证?

问题面试当中总会被问题这么一个问题:如何保证 Redis 缓存和数据库一致性?但依旧有很多的疑问:到底是更新缓存还是删除缓存?到底选择先更新数据库,再删除缓存,还是先删除缓存,再更新数据库?前言在项目业务的初期阶段,由于流量极其有限,无论是处理读取请求还是写入请求,直接对数据库进行操作是高效且直接的方式。此时的架构模型十分简洁,无需引入复杂的中间件或分布式系统,直接通过应用程序与数据库之间的交互来满足业务需求。此时架构模型是这样的。

Z99263的博客 1394

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

【Redis知识点总结】(四)——如何保证缓存与数据库中的数据一致性

最后总结一下比较靠谱的几种做法。如果是强一致性的场景,是不适合使用缓存的,那么最好就不要使用缓存了。如果遇到了即要求强一致性,又追求高性能的场景,那就太变态了。如果是对一致性要求较高,但又不是强一致性,那可以使用canal同步的方案,正常情况下canal读取binlog同步数据到redis这个过程,处理是非常快的。如果对一致性要求不高,可以采用先更新数据库,后删除缓存的机制,并且在查询数据库加载数据到缓存时,给缓存设置一个过期时间。

weixin_43889578的博客 1437

Redis--如何保障缓存数据库一致性?(面试高频问题)

缓存与数据库一致性如何解决?根据业务背景不同会有不一样的解决办法。

你只管努力,其他的交给天意。 1888

总算搞懂了!困扰我的Redis缓存与DB一致性问题

使用缓存的时候,我们需要关注Redis与DB数据的一致性。如果Redis缓存与DB数据不一致,就可能导致用户一直只能获取到数据错误的缓存,严重影响用户体验。那如何让Redis与DB数据一致性呢?

weixin_71690375的博客 698

如何保证Redis与MySQL的数据同步?(如何保障缓存与DB的双写一致性?)

【代码】如何保证Redis与MySQL的数据同步?(如何保障缓存与DB的双写一致性?

lyh2004_08的博客 1177

滴滴二面:怎么解决 Redis 缓存和数据库的一致性问题?

再加上缓存 TTL 兜底,即使所有重试都失败了,缓存过期后也会从 DB 加载最新值。:只有 "读请求写缓存" 的速度比 "写请求更新 DB + 删除缓存" 还慢时才会出问题,而写 DB 一般比读 DB 慢得多(涉及锁、磁盘 IO),所以实际中几乎不会发生。线程 A 先更新了数据库(20),但还没来得及更新缓存时,线程 B 已经完成了数据库和缓存的更新(30)。:面试官不仅仅是想知道 "先删缓存" 还是 "后删缓存",更是想知道你是否能分析出每种方案在并发场景下的数据不一致问题,以及背后的时序原因。

犬小哈 969

如何保障缓存和数据库的一致性(超详细案例)

高并发和海量数据下的缓存和数据库一致性实战方案,看完起飞

程序员囧辉 9832

面试官:熟悉Redis?请讲讲Redis缓存穿透、缓存击穿、缓存雪崩有什么区别

key对应的数据在数据源并不存在,每次针对此key的请求从缓存获取不到,请求都会压到数据源,从而可能压垮数据源。比如用一个不存在的用户id获取用户信息,不论缓存还是数据库都没有,若黑客利用此漏洞进行攻击可能压垮数据库。在某一时刻,突然有大量的请求去请求应用服务器,一般情况下,应用服务器会去Redis查询缓存数据,查到则返回数据,查不到,则去数据库差数据。

我这么骄傲的一个人。 1517
上一篇: 还在用main方法测试吗,带你来认识什么才是专业的SpringBoot项目测试方法
下一篇: 5000字详细解说什么是面向对象编程的三⼤特性—封装、继承、多态
Java_LingFeng
博客等级 码龄4年 505粉丝 259原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值