Redis 入门到面试高频:数据结构、缓存流程、穿透击穿雪崩一篇讲清

在 Java 后端项目里,Redis 几乎是绕不开的技术。

很多人刚开始学 Redis 时,只知道它“快”“可以做缓存”,但到了面试或者项目落地时,问题就会变得更具体:

  • Redis 到底是什么?
  • 为什么项目里要用 Redis?
  • Redis 为什么这么快?
  • Redis 单线程为什么还能抗高并发?
  • String、Hash、List、Set、ZSet 分别适合什么场景?
  • 缓存穿透、击穿、雪崩有什么区别?
  • Redis 和 MySQL 一起用时,查询流程是什么?

这篇文章就按 Java 后端常见面试和项目使用场景,把 Redis 的基础知识系统梳理一遍。


一、Redis 是什么?

Redis 是一个基于内存的高性能 Key-Value 数据库,也属于 NoSQL 数据库的一种。

它的读写性能很高,并且支持多种数据结构,所以在后端项目中经常用来做:

场景说明
缓存缓存热点数据,减少 MySQL 压力
分布式锁控制分布式系统中的并发操作
计数器点赞数、阅读数、访问量
排行榜用户积分榜、热搜榜
验证码短时间保存短信验证码
限流控制接口访问频率
消息队列简单异步任务
Session 共享多服务之间共享登录状态

面试可以这样回答:

Redis 是一个基于内存的 NoSQL 数据库,读写性能很高,支持多种数据结构,常用于缓存热点数据、分布式锁、限流、排行榜等场景。


二、为什么项目里要用 Redis?

MySQL 更适合存储核心业务数据,但如果所有高并发读请求都直接打到 MySQL,数据库压力会很大。

比如商品详情页:

10000 个请求都查询同一个商品

如果每次都查 MySQL,压力会非常高。

加上 Redis 后,流程变成:

请求 -> Redis Redis 有数据 -> 直接返回 Redis 没数据 -> 查询 MySQL -> 写入 Redis -> 返回

这样热点数据大部分请求都可以从 Redis 返回。


Redis 主要解决三个问题:

减少 MySQL 压力 提升接口响应速度 承载高并发读请求


三、Redis 为什么快?

Redis 快,常见原因有 4 个。

原因说明
基于内存大多数操作都在内存中完成
单线程执行命令避免频繁线程切换和锁竞争
IO 多路复用一个线程可以处理大量连接
数据结构高效内部结构针对不同场景做了优化

需要注意的是:
Redis 的“单线程”主要指 命令执行是单线程,不是整个 Redis 只有一个线程。

面试可以这样答:

Redis 快主要是因为数据在内存中,命令执行模型简单,采用单线程避免锁竞争,并使用 IO 多路复用处理网络连接。


四、Redis 单线程为什么还能支持高并发?

因为 Redis 的操作大多数是内存操作,本身执行速度非常快。

同时 Redis 使用 IO 多路复用,一个线程可以同时监听多个客户端连接。

简单理解:

客户端1 \ 客户端2 -> IO 多路复用 -> Redis 单线程执行命令 客户端3 /

流程图如下:

它不需要为每个连接都创建一个线程,也能处理大量请求。

不过也正因为命令执行主要是单线程,所以要避免执行耗时命令,比如大 key 删除、全量扫描等,否则可能阻塞后续请求。


五、Redis 是不是所有操作都是单线程?

不是。

早期 Redis 的核心命令执行是单线程,但后续版本引入了一些后台线程,例如:

异步删除 持久化 网络 IO 处理优化

不过在面试中可以这样表达:

Redis 的命令执行主要是单线程,所以单条命令要避免执行太久,否则会阻塞后续请求。

这句话比较稳,不会把 Redis 简单说成“完全单线程”。


六、Redis 常见数据结构有哪些?

Redis 最常见的 5 种基础数据结构是:

String、Hash、List、Set、ZSet

除此之外,还有:

Bitmap、HyperLogLog、Stream、Geo

对于实习和初中级面试来说,先把五种基础结构和对应场景掌握好就够用了。


七、String 类型适合什么场景?

String 是 Redis 最基础的数据类型,可以存字符串、数字、JSON 字符串。

常见场景:

场景示例
验证码短时间保存短信验证码
Token登录状态
缓存对象 JSON商品详情、用户信息
计数器点赞数、阅读数
分布式锁使用 set nx ex

验证码示例:

key: login:code:13800138000 value: 739421 expire: 5 分钟

计数器示例:

incr article:read:1001

incr 是原子操作,适合阅读数、点赞数这类计数场景。


八、Hash 类型适合什么场景?

Hash 类似 Java 里的 Map,适合存对象的多个字段。

例如:

key: user:1001 field: name value: 张三 field: age value: 20 field: city value: 北京

修改某个字段:

hset user:1001 age 21

相比直接存 JSON,Hash 的好处是可以单独修改某个字段,不需要把整个对象反序列化再写回去。

适合场景:

用户对象 商品对象 购物车信息 配置项


九、List 类型适合什么场景?

List 是有序列表,可以从两端插入和弹出。

常见场景:

场景说明
简单消息队列左进右出或右进左出
最新动态按插入顺序保存
任务列表保存待处理任务

示例:

lpush queue:order task1 rpop queue:order

不过要注意:
如果项目里真正要做消息队列,更推荐使用 RabbitMQ、RocketMQ、Kafka 这类专业 MQ。

Redis List 可以做简单队列,但可靠性、确认机制、堆积处理等能力不如专业 MQ 完整。


十、Set 类型适合什么场景?

Set 是无序不重复集合。

常见场景:

用户标签 点赞去重 共同好友 黑名单 抽奖去重

比如文章点赞:

sadd article:like:1001 user:1 sadd article:like:1001 user:2

判断用户是否点过赞:

sismember article:like:1001 user:1

Set 的核心特点就是天然去重。

比如一个用户重复点赞,Set 中也只会保存一份。


十一、ZSet 类型适合什么场景?

ZSet 是有序集合,每个元素都有一个分数 score。

常见场景:

场景说明
排行榜按积分、热度排序
热搜榜按搜索次数排序
延迟队列score 存执行时间
权重排序按权重取数据

排行榜示例:

zadd rank:score 100 user1

zadd rank:score 200 user2

zrevrange rank:score 0 9

zrevrange rank:score 0 9 可以取出分数最高的前 10 名。

面试里如果问 Redis 排行榜,基本就是回答 ZSet。


十二、Redis 缓存对象一般怎么设计 key?

Redis 的 key 要有业务含义,并且层次清晰。

常见写法:

user:1001

product:detail:2001

order:list:user:1001

login:code:13800138000

不建议使用这种随意的 key:

abc123、data001、test_key

好的 key 有几个好处:

方便排查问题 方便设置过期时间 方便按业务维度管理 方便多人协作维护

一般可以按这个格式设计:

业务名:数据类型:唯一标识

例如:

product:detail:2001


十三、缓存数据一般要不要设置过期时间?

一般建议设置。

如果不设置过期时间,Redis 中的数据可能越来越多,最终占满内存。

常见过期时间参考:

数据类型过期时间
验证码5 分钟
登录 Token7 天
商品详情缓存30 分钟
首页推荐5 分钟
热点榜单几分钟到几十分钟

当然,不是所有 key 都必须过期。

比如某些长期有效的配置缓存,可以不过期,但要有主动更新机制。
过期时间一定要结合业务决定,而不是所有数据都统一设置一个时间。


十四、什么是缓存穿透?

缓存穿透指的是:

查询一个 Redis 和 MySQL 都不存在的数据,导致每次请求都会打到 MySQL。

比如恶意请求:

product_id = -1 product_id = 999999999

流程是:

查 Redis:没有 查 MySQL:也没有 不写缓存 下次再来:还是查 MySQL

如果大量这种请求进来,MySQL 压力会非常大。

十五、缓存穿透怎么解决?

常见方案有三种:

方案说明
缓存空值MySQL 查不到时,也把空结果写入 Redis
布隆过滤器提前判断数据是否可能存在
参数校验过滤明显非法的请求参数

缓存空值示例:

key: product:999999

value: null

expire: 1 分钟

这样下次同样请求过来,就可以直接从 Redis 返回空,不会继续打到 MySQL。

布隆过滤器流程:

布隆过滤器适合数据量较大、非法请求较多的场景。


十六、什么是缓存击穿?

缓存击穿指的是:

某个热点 key 过期的一瞬间,大量请求同时打到 MySQL。

比如热门商品:

product:detail:1001

平时请求都走 Redis。
突然这个 key 过期了,10000 个请求同时发现 Redis 没有,于是一起去查 MySQL。

结果就是数据库压力瞬间暴涨。

缓存击穿的关键点是:

一个热点 key 失效


十七、缓存击穿怎么解决?

常见方案:

方案说明
热点 key 不设置过期时间后台异步刷新缓存
互斥锁只允许一个请求查库并重建缓存
逻辑过期缓存不过期,数据中保存逻辑过期时间

互斥锁思路:

这样不会让所有请求同时打到 MySQL。

逻辑过期常用于热点数据:
Redis key 本身不过期,但 value 中带一个过期时间。发现逻辑过期后,由一个线程异步刷新缓存,其他请求先返回旧数据。


十八、什么是缓存雪崩?

缓存雪崩指的是:

大量缓存 key 在同一时间失效,导致请求集中打到 MySQL。

比如很多 key 都设置了同样的过期时间:

expire = 30 分钟

如果它们同时过期,MySQL 会突然承受大量请求。

缓存击穿和雪崩区别:

问题特点
缓存击穿一个热点 key 失效
缓存雪崩大量 key 同时失效

十九、缓存雪崩怎么解决?

常见方案:

方案说明
过期时间加随机值避免大量 key 同时过期
热点数据提前预热系统启动或活动前提前加载缓存
多级缓存本地缓存 + Redis
限流降级防止数据库被打垮
Redis 高可用避免 Redis 整体不可用

比如过期时间不要都写死 30 分钟,可以改成:

30 分钟 + 随机 0 到 5 分钟

这样可以把过期时间打散。

二十、Redis 和 MySQL 一起用时,基本查询流程是什么?

最常见的是 Cache Aside 模式,也叫旁路缓存。

查询流程:

先查 Redis Redis 有数据:直接返回 Redis 没数据:查 MySQL MySQL 查到后写入 Redis 返回结果

图解如下:

面试可以这样答:

项目中一般使用旁路缓存模式。读请求先查 Redis,缓存未命中再查 MySQL,并把结果写入 Redis。这样可以减少数据库压力,提高热点数据访问速度。


二十一、五种基础数据结构怎么选?

最后做一个小总结。

数据结构特点常见场景
String简单 key-value验证码、Token、计数器、缓存 JSON
Hashfield-value 结构用户对象、商品对象、购物车
List有序列表,两端操作简单队列、最新动态
Set无序不重复点赞去重、标签、共同好友
ZSet不重复且带 score排行榜、热搜、延迟队列

可以用下面这个流程简单判断:

总结

Redis 可以按一条线来记:

Redis 是基于内存的高性能 Key-Value 数据库, Java 后端常用它做缓存、验证码、排行榜、计数器、分布式锁等。 Redis 快的原因主要是内存操作、单线程命令执行、IO 多路复用和高效数据结构。 String 适合验证码、计数器、缓存对象; Hash 适合对象字段; List 适合简单队列; Set 适合去重; ZSet 适合排行榜。 缓存系统常见问题有穿透、击穿、雪崩: 穿透是查不存在的数据,可以用缓存空值、布隆过滤器解决; 击穿是热点 key 失效,可以用互斥锁、逻辑过期解决; 雪崩是大量 key 同时失效,可以用随机过期时间、限流降级、多级缓存解决。

Redis 不是简单地“加一层缓存”就完事了。
真正用好 Redis,要同时考虑数据结构选择、key 设计、过期时间、缓存一致性和异常场景。掌握这些内容,再去看分布式锁、缓存更新策略、Redis 持久化和集群,就会顺很多。

📌 码字不易,技术干货深度复盘!

如果这篇文章帮你看清了 MyBatis-Plus 查询的底层底细,别忘了 点赞、关注、收藏 三连走一波!支持作者不迷路,更多底层源码干货持续输出中!🚀

让我们一起学习面试知识,拿到自己想要的offer!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值