Redis 八股面试题
Redis 的数据类型
五种基本数据类型:
String
List
Set
Hash
ZSet
(有序集合)
三种特殊数据类型:
Stream
(消息队列)HyperLogLog
(基数统计)Bitmap
(位图)Geospatial
(地理位置)
Redis 为什么快?
-
基于内存操作,比磁盘快很多
-
redis
数据类型(结构)性能很高 -
redis
执行命令是单线程的,避免了上下文切换带来的性能问题,也不用考虑锁的问题
使用 String 还是 Hash 存储对象数据更好?
-
当对象结构简单,而且操作是整体操作的时候使用
String
更适合 -
如果需要操作对象的字段或者节省内存,选择
Hash
更合适
购物车信息用 String 还是 Hash 存储更好?
- 购物车中的商品频繁修改和变动, 使用
Hash
存储
使用 Redis 的哪种数据结构实现点赞功能
-
使用
Set
实现,Set
适用于点赞,关注/粉丝,去重(签到,注册等)场景 -
Set
支持快速添加/删除,还能自动去重
如何使用 Redis 实现一个排行榜
- 使用
Sorted Set
(有序集合) - 相关的一些命令:
ZRANGE
(从小到大排序)、ZREVRANGE
(从大到小排序)、ZREVRANK
(指定元素排名)
Set 的应用场景
Set
是无序集合,集合中的元素没有先后顺序但都唯一,类似于Java
中的HashSet
常见应用场景:
-
存放的数据不能重复的场景:网站
UV
统计、文章点赞、动态点赞等等 -
获取交集、并集和差集:共同好友(交集), 好友推荐(差集)、音乐推荐(差集)、订阅号推荐(差集+交集)等
-
需要随机获取元素的场景:抽奖系统、随机点名等
Redis 除了做缓存, 还能做什么?
- 分布式锁
- 消息队列
- 计数器与限流器
- 延时队列
- 分布式
session
Redis 是单线程的,但是为什么还那么快?
- 单线程, 避免了线程切换和锁竞争开销
- 核心原因:
- 基于内存操作, 读写速度快
IO
多路复用:用epoll/kqueue
等机制处理多客户端连接,单线程高效处理并发请求- 高效数据结构:如跳表(Sorted Set)、压缩列表(Hash)等,操作复杂度低
- 无阻塞命令:核心命令(如
GET
、SET
)执行时间短,避免单线程阻塞
Redis 持久化机制
-
RDB(快照)
, 定期将内存中数据生成快照写入二进制文件(.rdb
),重启时快速加载,适合大数据量的恢复 -
AOF(追加日志)
, 每执行一次写操作,就把该命令追加到文件里(appendonly.aof
),数据持久性最好 -
混合持久化(Redis 4.0+):
RDB + AOF
Redis事务
-
用于保证一组命令的原子性(要么全部执行,要么全部不执行),不支持回滚操作
-
redis
事务的实现使用MULTI
(事务的开始)和EXEC
(事务的结束)命令 -
输入
MULTI
命令后,redis
返回OK
表示事务开启,然后输入需要在本次事务中执行的所有命令,每次输入命令不会立即执行,而是返回QUEUED
,表示命令已经并排入事务队列,最后输入EXEC
命令后,才会依次执行这些命令.
``
- 核心命令:
MULTI
:开启事务- 命令序列:如
SET key1 val1
、INCR key2
等(入队,未执行) EXEC
:执行事务内所有命令DISCARD
:取消事务WATCH key
:监视 key,若事务执行前 key 被修改,则事务中断(乐观锁机制)
缓存
问题 | 定义 | 解决方案 |
---|---|---|
缓存击穿 | 热点数据的缓存突然过期,大量请求直接冲击数据库 | 1.互斥锁 2.逻辑过期(缓存永不过期,后台异步更新) |
缓存穿透 | 查询不存在的数据,请求绕过缓存直接访问数据库 | 1.布隆过滤器 2.缓存空值 |
缓存雪崩 | 大量Key 同时过期,或缓存集群宕机,导致所有请求直接访问数据库 | 1.随机过期时间,分散key过期时间 2.使用多级缓存 3.使用Redis 集群部署,主从 + 哨兵模式 |
什么是布隆过滤器?
-
一种概率型数据结构,通过多个哈希函数将数据映射到位图(
bitmap
),用于快速判断元素是否 “可能存在” -
特点:
- 优点:空间效率高,查询速度快
- 缺点:可能误判,不支持删除操作
Redis 分布式锁如何实现?
方法一: 基于 Redis
的 SET
命令实现
加锁:
SET lock:order:1001 "UUID:threadId" NX PX 30000
-
NX
:当key
不存在时才设置(保证互斥) -
PX 30000
:设置 30 秒过期时间(避免死锁)
解锁:通过 Lua
脚本原子性判断并删除锁
方法二: 使用 Redisson
框架
如何合理控制分布式锁的有效时长
-
基础原则:设置略大于业务执行时间的过期时间(如业务需 5 秒,设 10~15 秒)
-
动态续期:使用
Redisson
的Watch Dog
机制,若线程未执行完,每隔1/3
过期时间自动延长锁有效期
Redis 双写问题是什么?如何解决?
-
定义:同时更新数据库和缓存时,因为并发操作、网络延迟或执行顺序不当等导致缓存与数据库数据不一致
-
解决:
- 先更数据库,再删缓存
- 延迟双删:删除缓存后延迟
100ms
再次删除,避免并发更新时的脏数据 - 最终一致性:通过消息队列或定时任务同步缓存与数据库差异
Redis 的数据过期策略有哪些?
- 惰性删除:访问
key
时才检查是否过期,过期则删除 - 定期删除:每隔一段时间随机检查部分过期 key 并删除
- 内存淘汰:当内存达到
maxmemory
阈值时,触发淘汰策略
Redis 的数据淘汰策略有哪些?
- volatile-lru:从设置了过期时间的 key 中,淘汰最近最少使用的
- allkeys-lru:从所有 key 中,淘汰最近最少使用的(最常用)
- volatile-lfu:从过期 key 中,淘汰最不经常使用的
- allkeys-lfu:从所有 key 中,淘汰最不经常使用的
- volatile-random:从过期 key 中随机淘汰
- allkeys-random:从所有 key 中随机淘汰
- volatile-ttl:淘汰过期时间最近的 key
- noeviction:默认策略,不淘汰任何 key,写操作返回错误
Redis集群方案
-
主从模式:一个
master
节点,多个slave
节点,master
节点宕机,slave
自动变成主节点 -
哨兵模式:在主从集群基础上添加哨兵节点或哨兵集群,用于监控
master
节点健康状态,通过投票机制选择slave
成为主节点 -
分片集群:多个
master
节点, 不同master
保存不同的数据,master
之间通过ping
相互监测健康状态。客户端请求任意一个节点都会转发到正确节点,因为每个master都被映射到0-16384个插槽上,集群的key是根据key的hash值与插槽绑定
什么是 Redis 主从同步?
主从同步第一次是全量同步, slave
第一次请求 master
节点根据 replid
判断是否是第一次同步,是的话 master
会生成 RDB
发送给 slave
增量同步, 后续主节点的写操作会通过复制缓冲区同步到从节点
好处:提高读吞吐量,主节点故障时从节点可切换为主节点
Redis 分片集群中数据是怎么存储和读取的?
- 存储:
- 集群将 16384 个哈希槽分配给各主节点(如 3 主节点分别负责 0-5460、5461-10922、10923-16383 槽)
- 写入 key 时,通过
CRC16(key) % 16384
计算槽位,自动路由到对应主节点
- 读取:
- 客户端首次连接时获取集群槽位映射表,后续直接定位节点
- 若槽位迁移(如扩容),节点返回
MOVED
重定向,客户端更新映射表后重试
Redis 集群脑裂是什么?如何解决?
- 定义:主从集群中,主节点网络波动导致哨兵误判其下线,选举从节点为新主,原主节点恢复后出现 “双主”(脑裂),数据写入旧主会丢失
- 解决方法:
- 配置
min-replicas-to-write 1
:主节点必须至少有 1 个从节点连接正常才允许写操作 - 配置
min-replicas-max-lag 10
:从节点同步延迟超过 10 秒,主节点拒绝写操作
- 配置
怎么保证 Redis 的高并发高可用?
- 高并发:
- 分片集群(Redis Cluster)分散读写压力
- 合理使用管道(Pipeline)和批量命令(如
MSET
)减少网络交互 - 优化数据结构(如用
Hash
替代多个String
)
- 高可用:
- 主从 + 哨兵模式,自动故障转移
- 数据持久化(RDB+AOF)防止数据丢失
- 限流保护(如用
redis-cell
模块)避免突发流量压垮集群