Redis 知识点

Redis 是前端/后端面试中高频考察的中间件,核心围绕 数据结构、缓存策略、高可用、性能优化、实际应用 五大模块展开。以下是面试常问知识点的详细梳理,包含核心答案、注意事项及易错点:

一、基础概念与核心特性

1. 什么是 Redis?它的核心特性有哪些?

答案:

Redis(Remote Dictionary Server)是一款 开源的高性能键值对数据库,基于内存存储,支持持久化,提供丰富的数据结构。核心特性:

  • 高性能:内存操作,单线程模型(6.0+ 引入多线程 IO,但核心命令仍单线程),QPS 可达 10W+;
  • 多数据结构:String、Hash、List、Set、Sorted Set、BitMap、HyperLogLog、Geo 等;
  • 持久化:支持 RDB 和 AOF 两种方式;
  • 高可用:主从复制、哨兵(Sentinel)、集群(Cluster);
  • 多功能:缓存、消息队列(List/Stream)、分布式锁、计数器、限流等;
  • 跨平台:支持多种语言客户端,支持事务、过期删除、发布订阅等。

注意事项:

  • 易错点:误以为 Redis 是“纯内存数据库”就不支持持久化,实际支持 RDB/AOF 落地到磁盘;
  • 重点:单线程模型的优势(避免线程切换开销、无并发安全问题)和局限(长时间命令会阻塞,需避免 keys *hgetall 等慢命令)。

2. Redis 的数据类型及应用场景

答案:

数据类型 核心特性 典型应用场景
String 二进制安全,支持增删改查、自增(incr)、过期(expire) 缓存用户信息、计数器(文章阅读量)、分布式锁(set nx ex)
Hash 键值对集合,支持单个字段操作 缓存对象(用户详情:name/age/addr)、购物车(userId -> {productId: count})
List 双向链表,支持两端插入/删除(lpush/rpop)、范围查询 消息队列(简单FIFO)、最新列表(朋友圈动态)、分页查询
Set 无序集合,支持交集(sinter)、并集(sunion)、差集(sdiff) 好友关系(共同好友)、标签系统(用户标签去重)、抽奖(srandmember)
Sorted Set 有序集合,通过分数(score)排序,支持范围查询 排行榜(游戏积分、商品销量)、延时队列(score 为时间戳)、地理位置排序(Geo 基于此实现)
BitMap 位操作,节省空间(1字节=8位) 签到功能(1表示签到,0表示未签到)、用户在线状态(1=在线)
HyperLogLog 基数统计(去重计数),占用空间极小(约12KB) 网站UV统计(无需存储具体用户,仅统计人数)
Geo 基于 Sorted Set 实现,支持地理位置存储、距离计算 附近的人、外卖商家距离排序

注意事项:

  • 重点:区分 Set 和 Sorted Set 的适用场景(有序用 ZSet,无序用 Set);
  • 易错点:Hash 适合存储“字段较多的对象”,但如果字段数量极少(如仅2个),String 序列化(JSON)可能更高效;
  • 延伸:List 作为消息队列的局限(无ack机制、不支持重复消费),实际生产常用 Stream 或 RabbitMQ 替代。

3. Redis 的持久化机制(RDB vs AOF)

答案:

Redis 持久化的核心目的是 防止内存数据丢失,提供两种方案:

(1)RDB(Redis Database)
  • 原理:在指定时间间隔内,将内存中的数据集快照(Snapshot)写入磁盘(.rdb 文件);
  • 触发方式:
    • 手动触发:save(阻塞主线程,不推荐)、bgsave(fork子进程,主线程不阻塞);
    • 自动触发:配置文件中设置 save 900 1(900秒内1次修改)、save 300 10 等;
  • 优点:文件体积小、恢复速度快(直接加载快照);
  • 缺点:数据一致性差(可能丢失最后一次快照后的修改)、fork 子进程开销大(内存占用翻倍)。
(2)AOF(Append Only File)
  • 原理:记录每一条写命令(如 set、incr),以日志形式追加到 .aof 文件,恢复时重新执行命令;
  • 触发方式:
    • 同步策略:appendfsync always(每条命令同步,最安全但最慢)、everysec(每秒同步,默认,平衡安全和性能)、no(操作系统决定,最快但最不安全);
    • 重写机制:AOF 文件过大时,Redis 会 fork 子进程,生成简化版 AOF(合并重复命令,如 set a 1 + set a 2set a 2);
  • 优点:数据一致性高(最多丢失1秒数据)、日志可读;
  • 缺点:文件体积大、恢复速度慢。
(3)选型建议:
  • 生产环境:开启 AOF + RDB 混合模式(Redis 4.0+ 支持),AOF 保证数据一致性,RDB 用于快速恢复;
  • 仅缓存场景:可关闭持久化(节省磁盘IO),但需接受重启后数据丢失。

注意事项:

  • 易错点:认为 AOF 比 RDB 更“安全”就只开启 AOF,实际混合模式更优(AOF 恢复慢,RDB 可快速兜底);
  • 重点:fork 子进程时的“写时复制(COW)”机制——主线程修改数据时,会复制一份原始数据给子进程,避免子进程读取时数据被修改。

4. Redis 的过期键删除策略

答案:

Redis 采用 “惰性删除 + 定期删除” 结合的策略,避免内存溢出:

  • 惰性删除:访问过期键时才删除,节省CPU,但可能导致过期键长期占用内存(“内存泄漏”风险);
  • 定期删除:每隔一段时间(默认100ms),随机抽取部分过期键删除,平衡CPU和内存开销(不会遍历所有过期键,避免阻塞)。

补充:内存淘汰策略(当内存达到 maxmemory 时)

当内存不足时,Redis 会根据配置的淘汰策略删除键,常见策略:

  • volatile-lru:删除过期键中最近最少使用的;
  • allkeys-lru:删除所有键中最近最少使用的(推荐,适用于纯缓存场景);
  • volatile-ttl:删除过期键中剩余过期时间最短的;
  • noeviction:默认策略,不删除任何键,拒绝写操作(会报错 OOM)。

注意事项:

  • 重点:LRU(Least Recently Used)是“最近最少使用”,LFU(Least Frequently Used)是“最不常用”(Redis 4.0+ 支持),需区分两者;
  • 易错点:惰性删除可能导致“缓存穿透”(访问不存在的键,Redis 无数据,直接穿透到数据库),需配合布隆过滤器或缓存空值解决。

二、缓存相关核心问题(面试高频)

1. 缓存穿透、缓存击穿、缓存雪崩的区别与解决方案

答案:

问题类型 定义 解决方案
缓存穿透 访问不存在的键(如恶意攻击),Redis 无数据,请求直接穿透到数据库,导致数据库压力过大 1. 缓存空值(如 key 不存在,Redis 存 key: null,设置短期过期);
2. 布隆过滤器(提前过滤不存在的 key,避免请求到数据库);
3. 接口层参数校验(拦截非法 key,如用户 ID 为负数)
缓存击穿 热点 key 过期瞬间,大量请求同时访问,Redis 无数据,所有请求穿透到数据库,导致数据库雪崩 1. 热点 key 永不过期(或延长过期时间);
2. 互斥锁(如 Redis 的 set nx ex,同一时间只有一个请求能更新缓存,其他请求等待);
3. 预热缓存(系统启动时提前加载热点数据到 Redis)
缓存雪崩 大量 key 同时过期(或 Redis 集群宕机),导致大量请求穿透到数据库,数据库不堪重负 1. 过期时间随机化(给每个 key 的过期时间加随机值,避免同时过期);
2. 集群部署(主从复制 + 哨兵,避免单点故障);
3. 限流降级(数据库层面限流,避免被打垮);
4. 缓存预热 + 熔断机制(缓存失效时,暂时熔断数据库访问,返回默认值)

注意事项:

  • 重点:布隆过滤器的原理(基于位图的概率型数据结构,可快速判断 key 是否存在,存在“误判”但无“漏判”,误判率可通过参数调整);
  • 易错点:互斥锁解决缓存击穿时,需设置合理的锁超时时间(避免锁未释放导致死锁),且要处理锁释放失败的情况(如用 Lua 脚本保证原子性)。

2. 缓存一致性(缓存与数据库数据同步)

答案:

核心原则:“更新数据库后,同步更新缓存”,但需避免“缓存脏数据”,常见方案:

  • 方案1:Cache-Aside Pattern(旁路缓存模式)—— 推荐
    1. 读操作:先查缓存 → 缓存命中直接返回;缓存未命中 → 查数据库 → 写入缓存 → 返回;
    2. 写操作:先更数据库 → 再删缓存(而非更新缓存);
    • 理由:删除缓存比更新缓存更高效(避免复杂数据序列化),且能避免“并发写”导致的脏数据;
  • 方案2:Write-Through(写透)
    • 写操作:同时更新数据库和缓存,缓存不命中时直接写数据库,再同步到缓存;
    • 缺点:写性能差(两次IO),适用于读多写少场景;
  • 方案3:Write-Back(写回)
    • 写操作:先更新缓存,缓存异步同步到数据库(延迟写入);
    • 优点:写性能高;缺点:数据一致性风险(缓存宕机导致数据丢失),适用于非核心数据。

注意事项:

  • 重点:“先更数据库,再删缓存”可能存在的问题(数据库更新成功,缓存删除失败 → 脏数据),解决方案:
    1. 重试机制(删除缓存失败时,通过消息队列重试);
    2. 延迟双删(先删缓存 → 更数据库 → 延迟1秒再删缓存,解决并发场景下的脏数据);
  • 易错点:并发场景下,“先查缓存 → 缓存未命中 → 查数据库 → 写缓存”可能导致重复写缓存,可通过互斥锁避免。

3. Redis 分布式锁的实现

答案:

分布式锁的核心需求:互斥性、安全性、可用性,Redis 实现方案:

(1)基础实现(set nx ex 命令)
1
2
3
4
5
6
7
8
# 加锁:key=lockKey,value=唯一标识(如UUID),nx(不存在才设置),ex(过期时间)
SET lockKey UUID NX EX 30
# 解锁:通过Lua脚本保证原子性(避免误删其他线程的锁)
if redis.call("get", "lockKey") == "UUID" then
return redis.call("del", "lockKey")
else
return 0
end
(2)优化点(解决死锁、锁超时问题)
  • 唯一标识(UUID):避免线程A删除线程B的锁;
  • 过期时间(EX):避免线程宕机导致锁无法释放;
  • 锁续期(Watch Dog):如果业务执行时间超过锁过期时间,通过后台线程定期延长锁的过期时间(如 Redisson 框架的自动续期功能);
  • 重试机制:加锁失败时,通过自旋(循环)重试,避免立即返回失败。
(3)Redisson 分布式锁(推荐生产使用)

Redisson 是 Redis 的 Java 客户端,封装了分布式锁的实现,支持:

  • 可重入锁(ReentrantLock):同一线程可多次加锁;
  • 公平锁:按请求顺序获取锁;
  • 联锁(MultiLock):多个锁同时获取成功才生效;
  • 读写锁(ReadWriteLock):读锁共享,写锁互斥。

注意事项:

  • 易错点:未使用 Lua 脚本解锁,导致“先查锁 → 再删锁”的非原子操作(如线程A查锁存在,准备删除时,锁过期被线程B获取,线程A误删线程B的锁);
  • 重点:锁的过期时间需大于业务执行时间,否则会导致“锁提前释放”,需配合锁续期机制。

三、高可用与集群

1. Redis 主从复制(Master-Slave)

答案:

  • 原理:主节点(Master)负责写操作,从节点(Slave)负责读操作,主节点将数据同步到从节点,实现读写分离;
  • 同步过程:
    1. 从节点连接主节点,发送 SYNC 命令;
    2. 主节点执行 BGSAVE 生成 RDB 文件,同时记录后续写命令到缓冲区;
    3. 主节点将 RDB 文件发送给从节点,从节点加载 RDB 文件;
    4. 主节点将缓冲区的写命令发送给从节点,从节点执行命令,完成同步;
    5. 后续主节点的写命令会实时同步到从节点(增量同步)。
  • 优点:提高读性能(分担读压力)、实现数据备份(从节点可作为备份);
  • 缺点:不支持自动故障转移(主节点宕机后,需手动切换从节点为主节点)、主节点写压力集中。

注意事项:

  • 重点:主从复制的“复制偏移量”(主从节点通过偏移量判断数据是否一致)和“运行ID”(主节点重启后,运行ID变化,从节点会重新全量同步);
  • 易错点:从节点默认是“只读”的(slave-read-only yes),不能执行写操作,否则会报错。

2. Redis 哨兵(Sentinel)

答案:

  • 作用:基于主从复制,实现 自动故障转移(主节点宕机后,自动选举从节点为主节点),提高可用性;
  • 核心功能:
    1. 监控:监控主从节点的健康状态;
    2. 通知:当节点故障时,通过邮件、短信等方式通知管理员;
    3. 自动故障转移:主节点宕机后,选举新主节点,更新其他从节点的主节点地址;
  • 部署建议:哨兵节点至少部署3个(奇数个,避免脑裂),且不能与主从节点部署在同一台服务器。

注意事项:

  • 重点:哨兵选举新主节点的规则(优先选择“复制偏移量最大”的从节点,保证数据最完整);
  • 易错点:“脑裂”问题(主节点网络分区后,哨兵误判主节点宕机,选举新主节点,此时原主节点恢复,出现两个主节点),解决方案:
    1. 配置 min-replicas-to-write 1(主节点至少有1个从节点连接时,才允许写操作);
    2. 配置 min-replicas-max-lag 10(从节点与主节点的延迟不超过10秒)。

3. Redis 集群(Cluster)

答案:

  • 背景:主从复制 + 哨兵只能解决“高可用”,无法解决“水平扩容”(单节点内存有限),Cluster 实现分布式存储,将数据分片到多个节点;
  • 核心特性:
    1. 分片机制:采用哈希槽(Hash Slot)分片,共 16384 个槽,每个节点负责部分槽;
    2. 路由规则:key 通过 CRC16(key) % 16384 计算槽位,客户端根据槽位路由到对应节点;
    3. 高可用:每个主节点至少有1个从节点,主节点宕机后,从节点自动切换为主节点;
    4. 容错性:集群中超过半数的主节点正常,集群即可运行。
  • 部署建议:至少3个主节点,每个主节点1个从节点,共6个节点。

注意事项:

  • 重点:哈希槽的迁移(扩容/缩容时,将槽位从旧节点迁移到新节点,不影响集群运行);
  • 易错点:Cluster 不支持多 key 操作(如 MSET key1 key2),除非所有 key 落在同一个槽位(可通过 {prefix} 给 key 加前缀,保证哈希槽一致);
  • 延伸:Redis 集群与主从复制 + 哨兵的区别(Cluster 侧重“水平扩容”,哨兵侧重“高可用故障转移”)。

四、性能优化与实践

1. Redis 性能优化手段

答案:

  • 内存优化:
    1. 选择合适的数据类型(如用 BitMap 代替 String 存储布尔值,用 HyperLogLog 代替 Set 统计基数);
    2. 合理设置过期时间(避免内存溢出);
    3. 开启内存压缩(Redis 6.0+ 支持 lz4 压缩,减少内存占用);
  • 命令优化:
    1. 避免慢命令(keys *hgetallsmembers,可用 scanhscansscan 分批查询);
    2. 批量操作(用 pipeline 代替多次单命令,减少网络往返开销);
    3. 原子命令替代 Lua 脚本(如 incr 代替 Lua 自增,减少脚本执行开销);
  • 部署优化:
    1. 读写分离(主从复制,读请求路由到从节点);
    2. 集群分片(水平扩容,分担存储和计算压力);
    3. 避免网络瓶颈(Redis 服务器与应用服务器部署在同一机房,使用 TCP 长连接);
  • 配置优化:
    1. 调整 maxmemory-policyallkeys-lru(缓存场景);
    2. 关闭持久化(纯缓存场景);
    3. 调整 io-threads(Redis 6.0+,多线程 IO,提升网络读写性能)。

注意事项:

  • 重点:pipeline 的使用场景(批量读写,如批量插入1000条数据),但需注意 pipeline 是“批量发送,批量响应”,并非原子操作;
  • 易错点:scan 命令的“游标”机制(返回 0 表示遍历完成),且 scan 可能返回重复数据,需客户端去重。

2. Redis 常见问题排查(面试常问“如何定位 Redis 性能问题”)

答案:

  • 工具:
    1. redis-cli info:查看 Redis 状态(如 info stats 查看 QPS、info memory 查看内存使用);
    2. redis-cli --stat:实时监控 Redis 吞吐量、延迟;
    3. redis-cli slowlog get:查看慢查询日志(默认记录执行时间超过 10 毫秒的命令);
  • 排查方向:
    1. 高 CPU 使用率:可能是慢命令(如 keys *)、频繁的过期键删除,需优化命令或调整过期删除策略;
    2. 高内存使用率:可能是键未设置过期时间、数据类型选择不当,需清理过期键或优化数据结构;
    3. 高延迟:可能是网络瓶颈、持久化开销大(如 AOF 同步策略为 always),需优化网络或调整持久化配置;
    4. 连接数过高:可能是应用端未释放连接,需检查连接池配置(如最大连接数、超时时间)。

五、总结:面试重点与备考建议

  1. 核心重点:数据类型及应用场景、缓存三大问题(穿透/击穿/雪崩)、缓存一致性、分布式锁、持久化、主从/哨兵/集群;
  2. 易错点:单线程模型的局限、RDB/AOF 的选型、分布式锁的原子性、Cluster 的槽位机制;
  3. 备考建议
    • 结合实际场景记忆(如“购物车用 Hash”“排行榜用 ZSet”);
    • 动手实践(搭建主从复制、哨兵集群,用 Redis 实现分布式锁);
    • 理解底层原理(如 LRU 实现、哈希槽分片、写时复制),而非死记硬背。

通过以上知识点的梳理,可覆盖 Redis 面试 90% 以上的高频问题,重点关注“是什么、为什么、怎么用、有什么问题、怎么解决”的逻辑链,确保回答既有理论又有实践。


Redis 知识点
https://zjw93615.github.io/2025/12/06/Redis/Redis知识点/
作者
嘉炜
发布于
2025年12月6日
许可协议