Redis 面试常见问答

2023-09-20 15:49:55

本文出自:https://thinkinjava.cn

作者:莫那 鲁道

1. 什么是缓存雪崩?怎么解决?

alt

一般而言,我们会利用缓存来缓冲对数据库的冲击,假如缓存无法正常工作,所有的请求便会直接发送至数据库,进而导致数据库崩溃,从而导致整个系统崩溃。

如何解决呢?

alt

2 种策略(同时使用):

  • 对缓存做高可用,防止缓存宕机

  • 使用断路器,如果缓存宕机,为了防止系统全部宕机,限制部分流量进入 DB,保证部分可用,其余的请求返回断路器的默认值。

2. 什么是缓存穿透?如何解决?

解释 1:缓存查询一个不存在的键,同时数据库也没有该键,如果黑客大量使用这种方式,将导致数据库宕机。

解决方案:我们可以采用一个默认值来避免,例如,当访问一个不存在的键时,然后再去查询数据库,如果仍然没有找到,则在缓存中放置一个占位符。下次请求到来时,检查该占位符,如果存在占位符,就不再查询数据库,以防止数据库宕机。

解释 2:大量请求查询一个刚刚失效的键,导致数据库压力倍增,可能会导致宕机,但实际上,这些请求都是查询相同的数据。

解决方案:可以在这些请求代码中添加双重检查锁。尽管这些请求的处理时间会变长,但总比数据库宕机要好。

3. 什么是缓存并发竞争?如何解决?

解释:多个客户端同时写入同一个键,如果顺序错乱,数据就会不正确。但我们无法控制写入的顺序。

解决方案:使用分布式锁,如 ZooKeeper,并加入数据的时间戳。在同一时刻,只有成功抢到锁的客户端才能进行写入操作,并且在写入时,需要比较当前数据的时间戳和缓存中数据的时间戳。

4. 什么是缓存与数据库双写不一致?如何解决?

解释:连续写入缓存和数据库,但在操作过程中发生并发操作,导致数据不一致。

通常情况下,更新缓存与数据库有以下几种顺序:

  • 先更新数据库,再更新缓存。

  • 先删除缓存,再更新数据库。

  • 先更新数据库,再删除缓存。

对这三种方式的优劣进行分析:

先更新数据库,再更新缓存。

这种方式存在的问题是:当有两个请求同时更新数据时,如果没有使用分布式锁,则无法控制最终缓存中的值将是多少。即存在并发写入时的问题。

先删除缓存,再更新数据库。

这种方式存在的问题是:如果在删除缓存之后,有客户端读取数据,可能会读取到旧数据,并且有可能将旧数据设置回缓存,导致缓存中的数据一直是旧数据。

针对这个问题有两种解决方案:

  • 使用"双删",即第一次删除后再次删除,将最后一步的删除操作设置为异步操作,以防止在客户端读取操作时设置了旧值。

  • 使用队列,在该键不存在时将其放入队列中,串行执行,必须等待数据库更新完成后才能读取数据。

总的来说,这些解决方案都比较麻烦。

先更新数据库,再删除缓存。

这是一种常用的方式,但很多人并不知道,这种方式称为Cache Aside Pattern,是由外国人发明的。如果先更新数据库再删除缓存,会出现在更新数据库之前可能会有一段时间数据不是最新的情况。

同时,如果在更新之前缓存正好失效,在写入客户端完成删除操作后又设置了旧值,这是一个非常巧合的情况。

有两个前提条件:缓存在写入之前失效,同时写入客户端删除操作结束后立即设置旧数据 - 即读取操作比写入慢。另外,某些写入操作可能会造成表锁定。

所以,这种情况很少发生,但如果发生了怎么办?使用"双删"!记录更新期间是否有客户端读取数据库,如果有,在数据库更新完成后执行延迟删除。

还有一种可能,如果在执行更新数据库之前准备执行删除缓存操作时服务挂了,导致删除操作失败怎么办?可以通过订阅数据库的binlog来进行删除操作。

顶尖架构师栈

关注回复关键字

【C01】超10G后端学习面试资源

【IDEA】最新IDEA激活工具和码及教程

【JetBrains软件名】 最新软件激活工具和码及教程

工具&码&教程

转载: https://mp.weixin.qq.com/s/mG3q5UpXcRQoxdvoZZ7Xmg

本文由 mdnice 多平台发布

更多推荐

单片机C语言实例:24、红外通讯

一、红外接收原理程序实例1:#include<reg52.h>//包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义sbitLED=P1^0;//用sbit关键字定义LED到P1.0端口,LED是自己任意定义且容易记忆的符号sbitIR_IN=P3^2;/*-------------------------

NLP(6)--Diffusion Model

目录一、Flow-BasedGeneralModel1、概述2、函数映射关系3、CouplingLayer4、Glow二、DiffusionModel1、概述2、前向过程3、反向过程4、训练获得噪声估计模型5、生成图片三、马尔科夫链一、Flow-BasedGeneralModel1、概述Flow-BasedGenera

浅谈C++|构造.析构函数篇

一对象的初始化和处理1.1构造函数和析构函数C++拥有构造函数和析构函数,这两个函数将会被编译器自动调用,完成对象初始化和清理工作。对象的初始化和清理工作是编译器强制要我们做的事情,因此如果我们不提供构造和析构,编译器提供的构造函数和析构函数是空实现。·构造函数:主要作用在于创建对象时为对象的成员属性赋值,构造函数由编

socket编程|TCP

一.套接字概念套接字(Socket)是一种用于网络通信的编程接口,它提供了一种机制,使得不同计算机上的应用程序能够通过网络进行通信和交换数据。套接字可以看作是应用程序和网络之间的端点,它定义了应用程序与网络之间的通信规则和数据格式。通过套接字,应用程序可以创建、连接、发送和接收数据,实现与其他计算机上的应用程序进行通信

【Linux】进程控制

文章目录一.进程创建1.fork函数初识2.fork函数返回值3.写时拷贝4.fork常规用法5.fork调用失败的原因二.进程终止1.进程退出场景2.进程退出码3.进程正常退出(1)return退出(2)exit函数(3)_exit函数(4)return、exit和_exit之间的区别与联系4.进程异常退出三.进程等

http客户端Feign使用

一、RestTemplate方式调用存在的问题先来看我们以前利用RestTemplate发起远程调用的代码:Stringurl="http://userservice/user/"+order.getUserId();Useruser=restTemplate.getForObject(url,User.class);

win系统环境搭建(七)——使用Nginx部署前后端分离项目

windows环境搭建专栏🔗点击跳转win系统环境搭建(七)——使用Nginx部署前后端分离项目本系列windows环境搭建开始讲解如何给win系统搭建环境,本人所用系统是腾讯云服务器的WindowsServer2022,你可以理解成就是你用的windows10系统。我会尽量从Linux的视角去操纵win系统,以达到

Redis 高可用之持久化

目录Redis高可用Redis持久化RDB持久化触发条件执行流程启动时加载修改配置文件AOF持久化配置执行流程命令追加(append)文件写入(write)和文件同步(sync)文件重写(rewrite)文件重写的流程RDB和AOF的优缺点Redis高可用在web服务器中,高可用是指服务器可以正常访问的时间,衡量的标准

SpringMVC之JSR303和拦截器

认识JSR303JSR303是一项Java标准规范,也叫做BeanValidation规范,提供了一种JavaBean数据验证的规范方式。在SpringMVC中,可以通过引入JSR303相关的依赖,来实现数据的校验。在使用JSR303进行校验时,需要在需要校验的JavaBean的属性上添加相应的注解,如@NotNull

线上论坛之单元测试

对线上论坛进行单元测试的测试报告源码地址:https://gitee.com/coisini-thirty-three/forum一、用户部分(UserServiceImplTest)1.创建普通用户测试名称createNormalUser()测试源码@TestvoidcreateNormalUser(){//构造用户

C++:AVL树

目录​​​​​​​一、关于AVL树二、AVL树的注意事项1、平衡因子的更新规则:2、旋转的处理①、右右:左单旋②、左左:右单旋③、左右:先左单旋再右单旋④、右左:先右单旋再左单旋三、AVL树模拟实现一、关于AVL树前面学过二叉搜索树,数据在有序或是接近有序时,二叉搜索树效率就非常低了,因此这里引入了AVL树,又叫高度平

热文推荐