【面试题】Redis缓存设计

news/2024/11/8 0:37:48/

文章目录

  • Redis缓存出现的问题
    • 🙎‍♂️面试官:什么是缓存雪崩?
    • 🙎‍♂️面试官:怎样解决缓存雪崩?
    • 🙎‍♂️面试官:什么是缓存击穿?
    • 🙎‍♂️面试官:怎样解决缓存击穿?
    • 🙎‍♂️面试官:什么是缓存穿透?
    • 🙎‍♂️面试官:怎样解决缓存穿透?
    • 🙎‍♂️面试官:说说常见的缓存更新策略?/ 数据一致性问题了解吗?
    • 🙎‍♂️面试官:为什么是先更新数据库,再删除缓存中的数据,不能颠倒吗?
    • 🙎‍♂️面试官:怎样保证更新数据库和删除缓存两个操作都能成功?
    • 🙎‍♂️面试官:Cache Aside 策略是万能的吗?
    • 🙎‍♂️面试官:「更新数据库 + 更新缓存」的方案会出现数据不一致,如何防止?

在这里插入图片描述

Redis缓存出现的问题

Redis是缓存数据库,我们经常需要把MySQL中的数据缓存到Redis中,来提高查询效率。

但是随之而来也会出现一些问题,比如缓存雪崩、缓存击穿、缓存穿透,以及数据库缓存一致性问题。

🙎‍♂️面试官:什么是缓存雪崩?

🙋‍♂答:

简名达意。雪崩,就是大量缓存数据在同一时间失效,或者Redis宕机。此时有大量的用户请求无法在Redis处理。直接访问数据库,导致数据库压力剧增,可能造成数据库宕机、等一系列连锁反应,最终整个系统崩溃,这就是缓存雪崩的问题。

🙎‍♂️面试官:怎样解决缓存雪崩?

🙋‍♂答:

针对大量数据同时过期而引发的缓存雪崩问题,常见的应对方法有下面这几种:

  • 均匀设置过期时间
    由于缓存雪崩是同一时间大量数据失效,那么给这些数据的过期时间加上一个随机数,这样就保证数据不会在同一时间过期。
  • 双缓存策略
    设置两个缓存,当主缓存失效,访问备用缓存的数据。当然,备用缓存的数据过期时间要相应的长一些。
  • 构建多级缓存
    增加本地缓存,在存储层前加一级屏障,保持服务的整体可用。

针对 Redis 故障宕机而引发的缓存雪崩问题,常见的应对方法有下面这几种:

  1. 通过主从节点的方式构建Redis高可用集群。
  2. 启用服务熔断或者请求限流机制。
    • 服务熔断,就是宕机就停止服务,直接返回错误。
    • 请求限流,就是只将少部分请求发送到数据库进行处理,再多的请求就在入口直接拒绝服务。

🙎‍♂️面试官:什么是缓存击穿?

🙋‍♂答:

缓存击穿可以认为是缓存雪崩的子集。

击穿,指的是某个热点数据过期,大量请求访问该热点数据,就无法从缓存中获取,导致MySQL服务器压力剧增,可能引发宕机等一系列问题,最终导致系统崩溃,就是缓存击穿的问题。

🙎‍♂️面试官:怎样解决缓存击穿?

🙋‍♂答:

对于缓存击穿,可以采取两种方案:

  • 互斥锁方案:防止大量请求访问热点数据。
    SET KEY VALUE [EX seconds] [PX milliseconds] [NX|XX]
    EX seconds − 设置指定的到期时间(以秒为单位)。
    PX milliseconds - 设置指定的到期时间(以毫秒为单位)。
    NX - 仅在键不存在时设置键。
    XX - 只有在键已存在时才设置。
    
    返回boolean为true表示语句执行成功,那么线程就拿到了锁,并且进一步对数据库进行操作。返回为false表示加锁失败,该线程要等待锁释放或者返回默认值或空值。
  • 后台线程异步更新。不给热点数据设置过期时间,当内存删除策略删除热点数据后,主线程先返回空值,之后通知后台线程异步更新缓存;具体实现可以采用定时任务/消息队列的方式来实现。

🙎‍♂️面试官:什么是缓存穿透?

🙋‍♂答:

缓存穿透,就是大量请求访问缓存和数据库中不存在的数据。当有这样的请求到来,服务器的压力剧增,这就是缓存穿透的问题。

一般都是业务误操作或者黑客攻击才会发生这种情况。

🙎‍♂️面试官:怎样解决缓存穿透?

🙋‍♂答:

  • 限制非法请求。在API入口处,判断请求参数是否合法,如果判断出是恶意请求,就直接返回空值,避免进一步访问缓存和数据库。
  • 设置空值或默认值。当发现缓存穿透的情况时,可以针对数据设置空值,这样后续请求就可以从缓存中查找到数据,而不用进入数据库查询。
  • 使用布隆过滤器。Redis 自身是支持布隆过滤器的。布隆过滤器可以用于检索该数据是否存在于数据库中。它的优点是空间效率和查询时间都比一般的算法要好的多。从而避免缓存穿透。在写入数据库数据时,使用布隆过滤器进行标记。

🙎‍♂️面试官:说说常见的缓存更新策略?/ 数据一致性问题了解吗?

🙋‍♂答:

使用缓存更新策略可以防止出现数据库与缓存数据不一致的情况。

最常用的缓存更新策略是Cache Aside策略。该策略的具体内容如下:

  • 在向数据库读取数据时,先从缓存中获取数据,如果缓存中没有数据,就从服务器获取数据。然后将数据写入到缓存,并且返回给用户。
  • 在向数据库写入数据时,先更新数据库中的数据,再删除缓存中的数据。【懒加载的思想】

Read/Write Through 策略。该策略原则是应用程序只和缓存交互,而更新的操作交给缓存自己代理。Redis不提供这种功能,所以不常用。

Write Back 策略。该策略的原则是先更新缓存,将缓存设置为脏,之后由缓存自己批量异步更新数据库。Redis没有异步更新数据库的功能,所以不常用。

🙎‍♂️面试官:为什么是先更新数据库,再删除缓存中的数据,不能颠倒吗?

🙋‍♂答:

这样才可以保证数据库和缓存的一致性。

缓存的写入速度普遍要快于更新数据库的操作,实际很难出现请求A的写策略更新完数据库又删除缓存后,请求B的读策略才更新缓存。一旦请求A删除了缓存,请求B就需要去数据库中读取数据,更新到缓存中,最终返回。

🙎‍♂️面试官:怎样保证更新数据库和删除缓存两个操作都能成功?

🙋‍♂答:

使用消息队列的重试机制。
消息队列RocketMQ版支持消息重试功能,即Consumer消费某条消息失败或消费超时,消息队列RocketMQ版会根据消息重试机制重新投递消息。消费的消息就可以是删除缓存的操作。确保两个操作都能成功。

kafka消息队列没有重试机制。

🙎‍♂️面试官:Cache Aside 策略是万能的吗?

🙋‍♂答:

Cache Aside 策略也是存在局限性的。先更新数据库,后删除缓存。这样在写多的场景下,缓存中的数据会被频繁的清理,进而造成缓存命中率过低。

如果业务对于缓存的命中率有要求,就需要使用「更新数据库 + 更新缓存」的方案,因为更新缓存不会存在未命中的情况。

🙎‍♂️面试官:「更新数据库 + 更新缓存」的方案会出现数据不一致,如何防止?

🙋‍♂答:

  • 在更新缓存时增加分布式锁,防止多个请求更新同一份缓存。但是不支持并发操作,效率会降低。
  • 更新缓存后给缓存增加较短过期时间,即使数据不一致,也会在短时间过期。

完。

来源:Redis设计与实践、小林Coding


http://www.ppmy.cn/news/87584.html

相关文章

计算机网络:HTTP状态码有哪些?分别对应什么意思?

HTTP码有哪些?分别对应什么意思? HTTP状态码是指客户端向服务器发出请求时,服务器返回的HTTP协议状态码。 根据HTTP/1.1协议,HTTP状态码分为5类,常见的状态码包括: 1xx:信息响应类&#xff0…

Python+Pandas数据清洗的步骤

一、导语二、常见步骤1. 导入 Pandas:2. 加载数据:3. 观察数据:4. 处理缺失值:5. 处理重复值:6. 数据类型转换:7. 处理异常值:8. 数据重塑:9. 数据归一化/标准化:10. 保存…

【MySQL】(12)用户管理

文章目录 用户信息创建用户用户权限给用户授权回收权限 删除用户修改密码 用户信息 MySQL 中的用户信息,都存储在系统数据库 mysql 中的 user 表中 MariaDB [mysql]> select host, user, authentication_string from user; ----------------------------------…

一文掌握python列表的所有使用方法(零基础学python(一))

列表 Python 中的列表是一种可变的数据类型,它可以存储多个值,并且可以随时添加、删除或修改其中的元素。以下是 Python 列表的基本操作和示例代码: 创建列表 可以使用方括号 [] 来创建一个空列表,也可以在方括号中添加元素来创建一个非空列表。例如: empty_list = [] …

Three.js深度冲突(模型闪烁)与解决方案

Mesh面重合渲染测试 下面代码创建两个重合的矩形平面Mesh,通过浏览器预览,当你旋转三维场景的时候,你会发现模型渲染的时候产生闪烁。 这种现象,主要是两个Mesh重合,电脑GPU分不清谁在前谁在后,这种现象&a…

【使用教程】NIMC2000控制器EtherCAT通讯下SDO位置清零

NIMC2000控制器是一种高性能的运动控制器,可通过EtherCAT通讯进行控制。在使用过程中,有时需要将位置清零,这可以通过SDO命令实现。 首先,需要确保NIMC2000控制器已经通过EtherCAT连接到了主机。然后,使用SDO命令将位…

Student实体类实现HashSet集合,唯一性

Student类如下所示: package com.test.Test07;import java.util.Objects;public class Student {private int age;private String name;public int getAge() {return age;}public void setAge(int age) {this.age age;}public String getName() {return name;}pub…

澳洲学生用ChatGPT代写?澳洲多所高校使用全新反击工具检测

朋友们听句劝 ChatGPT可太危险了 ChatGPT有多火?据2月1日瑞银发布的一项研究报告显示,仅仅发布两个月,ChatGPT月活跃用户已达1亿,这是历史上增长速度最快的应用。要知道达成1亿用户的时间,Instagram用了2.5年&#xf…