Java开发之Redis(面试篇 持续更新)

文章目录

  • 前言
  • 一、redis使用场景
    • 1. 知识分布
    • 2. 缓存穿透
      • ① 问题引入
      • ② 举例说明
      • ③ 解决方案
      • ④ 实战面试
    • 3. 缓存击穿
      • ① 问题引入
      • ② 举例说明
      • ③ 解决方案
      • ④ 实战面试
    • 4. 缓存雪崩
      • ① 问题引入
      • ② 举例说明
      • ③ 解决方案
      • ④ 实战面试
    • 5. 缓存-双写一致性
      • ① 问题引入
      • ② 举例说明
      • ③ 解决方案
      • ④ 实战面试
  • 二、redis分布式锁
  • 引用声明


前言

本文主要记录redis的缓存穿透、缓存击穿、缓存雪崩、双写一致性、持久化、数据过期策略、数据淘汰策略、分布式锁等问题的分析与面试回答示例。


提示:以下是本篇文章正文内容,下面案例可供参考

一、redis使用场景

1. 知识分布

Java开发之Redis(面试篇 持续更新)_第1张图片
Java开发之Redis(面试篇 持续更新)_第2张图片

Java开发之Redis(面试篇 持续更新)_第3张图片

2. 缓存穿透

① 问题引入

Java开发之Redis(面试篇 持续更新)_第4张图片

② 举例说明

一个get请求路径:api/news/getById/1
从数据库中查询到了数据并加载到redis缓存,直接查询redis中的数据,查询到了就返回结果,否则查数据库,具体流程如下:
Java开发之Redis(面试篇 持续更新)_第5张图片
缓存穿透:查询一个不存在的数据,mysql查询不到数据也不会直接写入缓存,就会导致每次请求都查数据库,给数据库增加压力。

③ 解决方案

方案一:缓存空数据,查询返回的数据为空,仍把这个空结果进行缓存
优点:简单
缺点:消耗内存,可能数据库数据已经修改,但是redis中还是之前的空数据

方案二:布隆过滤器,拦截不存在的数据
优点:内存占用较少,没有多余的key
缺点:实现复杂,存在误判
Java开发之Redis(面试篇 持续更新)_第6张图片
补充:
在添加数据到数据库时,也需要添加到redis、布隆过滤器中
布隆过滤器依赖bitmap(位图):一个以(bit)位为单位的数组,只能存储二进制(0、1)

布隆过滤器的作用:用于检索一个元素是否在一个集合中。
比如添加一个id=1的数据,经过哈希函数计算,将0改为1,表示存在数据。
Java开发之Redis(面试篇 持续更新)_第7张图片
当id=1和id=2都存在,但是id=3不存在,经过hash函数计算得到的结果是存在,这就是误判。
误判率:数组越小误判率就越大,数组越大误判率就越小,但是同时带了了更多的内存消耗。
Java开发之Redis(面试篇 持续更新)_第8张图片
布隆过滤器的实现中我们可以控制误判率(5%之内)
Java开发之Redis(面试篇 持续更新)_第9张图片

④ 实战面试

Java开发之Redis(面试篇 持续更新)_第10张图片

3. 缓存击穿

① 问题引入

Java开发之Redis(面试篇 持续更新)_第11张图片

② 举例说明

缓存击穿: 当某一个热门的key设置了过期时间,当key过期的时候,恰好这个时间点对这个key有大量的并发请求过来,redis缓存重建的过程比较慢,这些并发请求可能会瞬间把数据库压垮。
Java开发之Redis(面试篇 持续更新)_第12张图片

③ 解决方案

**方案一:**互斥锁
优点:数据强一致
缺点:性能查
补充:当线程1在缓存的过程中,其他线程只能等待;当线程1把数据缓存成功,其他的线程就可以获取到数据

Java开发之Redis(面试篇 持续更新)_第13张图片

方案二: 逻辑过期
优点:高可用,保证查询效率
缺点:不能保证数据绝对一致
补充:当线程2没有将最新数据加入到缓存之前,所有的线程获取的都是过期数据,当线程2将数据更新完成后,所有的线程获取到最新数据。
Java开发之Redis(面试篇 持续更新)_第14张图片

④ 实战面试

Java开发之Redis(面试篇 持续更新)_第15张图片

4. 缓存雪崩

① 问题引入

Java开发之Redis(面试篇 持续更新)_第16张图片

② 举例说明

缓存雪崩: 是指在同一时段大量的缓存key同时失效或者Redis服务宕机导致大量请求到达数据库,带来巨大压力。
Java开发之Redis(面试篇 持续更新)_第17张图片

③ 解决方案

方案一:
情况:大量的缓存key同时失效
方法:给不同的key设置不同的过期时间,在原有的时间基础上再加一个随机时间值;
方案二:
情况:大量的缓存key同时失效
方法:给业务添加多级缓存;
方案三:
情况:Redis服务宕机
方法:利用Redis集群提高服务的可用性,比如哨兵模式、集群模式。
方案四:
情况:降级作为系统保底策略,适用于穿透、击穿、雪崩
方法:给缓存业务添加降级限流策略,比如nginx或者springcloud gateway

④ 实战面试

Java开发之Redis(面试篇 持续更新)_第18张图片

5. 缓存-双写一致性

① 问题引入

Java开发之Redis(面试篇 持续更新)_第19张图片

② 举例说明

双写一致性: 当修改了数据库的数据也要同时更新缓存的数据,缓存和数据库的数据要保持一致。
读操作:缓存命中,直接返回;缓存未命中查询数据库,写入缓存,设定超时时间。
Java开发之Redis(面试篇 持续更新)_第20张图片
写操作:延迟双删
Java开发之Redis(面试篇 持续更新)_第21张图片

  1. 先删除缓存还是先删除数据库?
    情况一:先删除缓存,再操作数据库,可能会出现脏数据
    Java开发之Redis(面试篇 持续更新)_第22张图片
    情况二:先操作数据库,再删除缓存,也可能会出现脏数据
    Java开发之Redis(面试篇 持续更新)_第23张图片
  2. 为什么要删除两次缓存?
    降低脏数据的出现
  3. 为什么要延时删除?
    数据库是主从分离的,延时把同步数据,也可能出现脏数据

③ 解决方案

**方案一:**分布式锁
优点:保证强一致性
缺点:性能低
Java开发之Redis(面试篇 持续更新)_第24张图片
方案二: 共享锁与排他锁(优化版)
优点:保证数据强一致性
共享锁:读锁readLock,加锁之后,其他线程可以共享读操作
Java开发之Redis(面试篇 持续更新)_第25张图片
排他锁:独占锁writeLock也叫,加锁之后,阻塞其他线程读写操作
Java开发之Redis(面试篇 持续更新)_第26张图片
方案三: MQ异步通知
优点:保证数据的一致性
Java开发之Redis(面试篇 持续更新)_第27张图片
方案四: Canal异步通知
Java开发之Redis(面试篇 持续更新)_第28张图片

④ 实战面试

分为两种情况进行回答,主要是业务需要是属于一致性要求高、延迟一致性
Java开发之Redis(面试篇 持续更新)_第29张图片
情况一:强一致性
Java开发之Redis(面试篇 持续更新)_第30张图片
情况二:延迟一致
Java开发之Redis(面试篇 持续更新)_第31张图片

二、redis分布式锁

引用声明

文章内容来源:https://www.bilibili.com/video/BV1yT411H7YK?p=7&spm_id_from=pageDriver&vd_source=98092b0aee05ae7c890b09fe07f13df4

你可能感兴趣的:(Java面试宝典,java,redis,面试)