【Redis】Redis面试高频考点汇总Day15(2026年)

写在前面

经过前面14天的学习,我们已经全面掌握了Redis的核心知识。今天是Redis系列的最后一篇,我们将系统梳理Redis面试高频考点,帮助大家查漏补缺,顺利通过面试。

文章目录

    • 写在前面
    • 一、Redis基础面试题
      • [1.1 Redis是什么?有什么特点?](#1.1 Redis是什么?有什么特点?)
      • [1.2 Redis为什么这么快?](#1.2 Redis为什么这么快?)
      • [1.3 Redis单线程为什么还能高并发?](#1.3 Redis单线程为什么还能高并发?)
      • [1.4 Redis和Memcached的区别?](#1.4 Redis和Memcached的区别?)
    • 二、数据结构面试题
      • [2.1 Redis有哪些数据类型?各有什么应用场景?](#2.1 Redis有哪些数据类型?各有什么应用场景?)
      • [2.2 Redis String的内部编码有哪些?](#2.2 Redis String的内部编码有哪些?)
      • [2.3 Redis Hash的底层实现?](#2.3 Redis Hash的底层实现?)
      • [2.4 Redis ZSet为什么使用跳表而不是红黑树?](#2.4 Redis ZSet为什么使用跳表而不是红黑树?)
      • [2.5 Redis List的底层实现?](#2.5 Redis List的底层实现?)
    • 三、持久化面试题
      • [3.1 Redis持久化机制有哪些?](#3.1 Redis持久化机制有哪些?)
      • [3.2 RDB和AOF如何选择?](#3.2 RDB和AOF如何选择?)
      • [3.3 AOF重写是什么?](#3.3 AOF重写是什么?)
      • [3.4 Redis重启时如何选择恢复方式?](#3.4 Redis重启时如何选择恢复方式?)
    • 四、高可用面试题
      • [4.1 Redis主从复制的原理?](#4.1 Redis主从复制的原理?)
      • [4.2 哨兵模式的原理?](#4.2 哨兵模式的原理?)
      • [4.3 Redis Cluster的原理?](#4.3 Redis Cluster的原理?)
      • [4.4 Cluster和哨兵的区别?](#4.4 Cluster和哨兵的区别?)
    • 五、缓存应用面试题
      • [5.1 什么是缓存穿透、击穿、雪崩?](#5.1 什么是缓存穿透、击穿、雪崩?)
      • [5.2 如何保证缓存和数据库一致性?](#5.2 如何保证缓存和数据库一致性?)
      • [5.3 为什么是删除缓存而不是更新缓存?](#5.3 为什么是删除缓存而不是更新缓存?)
    • 六、分布式锁面试题
      • [6.1 Redis分布式锁如何实现?](#6.1 Redis分布式锁如何实现?)
      • [6.2 Redis分布式锁的可靠性如何保证?](#6.2 Redis分布式锁的可靠性如何保证?)
      • [6.3 Redis分布式锁和Zookeeper分布式锁的区别?](#6.3 Redis分布式锁和Zookeeper分布式锁的区别?)
    • 七、性能优化面试题
      • [7.1 如何排查Redis性能问题?](#7.1 如何排查Redis性能问题?)
      • [7.2 如何优化Redis内存使用?](#7.2 如何优化Redis内存使用?)
      • [7.3 为什么KEYS命令在生产环境禁用?](#7.3 为什么KEYS命令在生产环境禁用?)
    • 八、其他高频面试题
      • [8.1 Redis如何实现消息队列?](#8.1 Redis如何实现消息队列?)
      • [8.2 Redis如何实现延迟队列?](#8.2 Redis如何实现延迟队列?)
      • [8.3 Redis如何实现限流?](#8.3 Redis如何实现限流?)
      • [8.4 Redis如何实现分布式Session?](#8.4 Redis如何实现分布式Session?)
      • [8.5 Redis内存满了怎么办?](#8.5 Redis内存满了怎么办?)
    • 九、学习路线总结
      • [9.1 Redis学习路线图](#9.1 Redis学习路线图)
      • [9.2 面试重点总结](#9.2 面试重点总结)
    • 十、参考资料
    • 十一、互动话题

一、Redis基础面试题

1.1 Redis是什么?有什么特点?

答案

Redis(Remote Dictionary Server)是一个开源的、基于内存的高性能键值对数据库。

主要特点

特点 说明
高性能 基于内存,读写速度极快(10万+QPS)
丰富数据类型 String、Hash、List、Set、ZSet、Bitmap、HyperLogLog、Geo、Stream
持久化 RDB和AOF两种持久化方式
高可用 主从复制、哨兵模式、Cluster集群
单线程 核心处理流程采用单线程模型
支持事务 提供事务支持,保证原子性

1.2 Redis为什么这么快?

答案

原因 说明
基于内存 数据存储在内存中,读写速度极快
单线程模型 避免多线程上下文切换开销
IO多路复用 使用epoll实现高并发连接处理
高效数据结构 使用跳表、压缩列表等高效数据结构
协议简单 RESP协议简单高效

详细解释

  1. 单线程模型:Redis核心处理流程采用单线程,避免了多线程的锁竞争和上下文切换开销。

  2. IO多路复用:Redis使用epoll(Linux)实现IO多路复用,单线程可以处理大量并发连接。

  3. 高效数据结构

    • 字符串使用SDS(Simple Dynamic String)
    • 列表使用quicklist
    • 有序集合使用跳表
    • 小数据量使用压缩列表

1.3 Redis单线程为什么还能高并发?

答案

  1. 纯内存操作:内存访问速度极快,纳秒级

  2. 非阻塞IO:使用epoll实现IO多路复用,单线程处理多个连接

  3. 避免锁竞争:单线程不需要加锁,避免了锁开销

  4. CPU亲和性:单线程可以充分利用CPU缓存

注意:Redis 6.0引入了多线程,用于网络IO处理,核心命令执行仍然是单线程。

1.4 Redis和Memcached的区别?

答案

对比项 Redis Memcached
数据类型 丰富(5种基础+扩展) 仅支持String
持久化 支持RDB/AOF 不支持
集群 原生支持Cluster 需要客户端分片
事务 支持 不支持
内存管理 更灵活 更简单
性能 高(略快于Redis)
适用场景 缓存+数据存储 纯缓存

二、数据结构面试题

2.1 Redis有哪些数据类型?各有什么应用场景?

答案

数据类型 底层实现 应用场景
String SDS 缓存、计数器、分布式锁
Hash ziplist/hashtable 对象存储、购物车
List quicklist 消息队列、文章列表
Set intset/hashtable 标签、共同关注
ZSet skiplist+dict 排行榜、延时队列
Bitmap String 签到、布隆过滤器
HyperLogLog String 基数统计
Geo ZSet 地理位置
Stream listpack 消息队列

2.2 Redis String的内部编码有哪些?

答案

编码 条件 特点
int 整数值且范围在long内 内存占用最小
embstr 字符串长度≤44字节 一次分配,紧凑存储
raw 字符串长度>44字节 SDS实现,可修改

查看编码

redis 复制代码
OBJECT ENCODING mykey

2.3 Redis Hash的底层实现?

答案

Redis Hash底层使用两种编码:

  1. ziplist(压缩列表)

    • 条件:元素数≤512,所有值长度≤64字节
    • 特点:内存紧凑,适合小数据量
    • 时间复杂度:O(N)
  2. hashtable(哈希表)

    • 条件:不满足ziplist条件
    • 特点:O(1)时间复杂度
    • 扩容:负载因子>1时扩容

2.4 Redis ZSet为什么使用跳表而不是红黑树?

答案

对比项 跳表 红黑树
实现复杂度 简单 复杂
范围查询 高效 需要中序遍历
内存占用 略高 较低
并发友好 更好 一般
插入删除 简单 需要旋转调整

Redis选择跳表的原因

  1. 实现简单:跳表比红黑树更容易实现和维护

  2. 范围查询高效:跳表在找到起点后,可以顺序遍历,效率更高

  3. 内存效率:虽然跳表内存略高,但Redis主要瓶颈不在内存

2.5 Redis List的底层实现?

答案

Redis 3.2之后,List使用quicklist(快速列表)实现:

  • quicklist是ziplist的双向链表
  • 结合了ziplist的内存紧凑和链表的快速插入删除
  • 可以配置每个ziplist的大小和压缩策略
conf 复制代码
# 配置参数
list-max-ziplist-size -2  # 每个ziplist大小
list-compress-depth 0     # 压缩深度

三、持久化面试题

3.1 Redis持久化机制有哪些?

答案

机制 RDB AOF
方式 快照 日志追加
文件大小
恢复速度
数据安全性 可能丢失 更安全
系统资源 CPU消耗大 IO消耗大
适用场景 备份、主从复制 数据安全要求高

3.2 RDB和AOF如何选择?

答案

推荐方案:同时开启RDB和AOF

场景 推荐方案
数据安全要求高 开启AOF
允许少量数据丢失 只开启RDB
生产环境 同时开启RDB+AOF
纯缓存场景 可不持久化

配置建议

conf 复制代码
# RDB配置
save 900 1
save 300 10
save 60 10000

# AOF配置
appendonly yes
appendfsync everysec

3.3 AOF重写是什么?

答案

AOF重写原理

  • 随着写操作增加,AOF文件越来越大
  • 重写会创建一个新的AOF文件,只保留最终数据的写入命令
  • 重写过程中不影响正常服务

重写触发条件

conf 复制代码
# AOF文件大小超过上次重写后大小的100%
auto-aof-rewrite-percentage 100
# AOF文件最小64MB才触发重写
auto-aof-rewrite-min-size 64mb

重写流程

  1. Redis创建子进程进行重写
  2. 子进程根据内存数据生成新的AOF文件
  3. 父进程继续处理命令,写入AOF重写缓冲区
  4. 子进程完成后,父进程将重写缓冲区追加到新文件
  5. 用新文件替换旧AOF文件

3.4 Redis重启时如何选择恢复方式?

答案

Redis启动时恢复数据的优先级:

  1. 如果开启AOF,优先使用AOF恢复
  2. 如果只开启RDB,使用RDB恢复
  3. 如果AOF文件损坏,可以使用redis-check-aof修复
shell 复制代码
# 修复AOF文件
redis-check-aof --fix appendonly.aof

# 检查RDB文件
redis-check-rdb dump.rdb

四、高可用面试题

4.1 Redis主从复制的原理?

答案

主从复制流程

复制代码
从节点连接主节点
    ↓
发送SYNC命令
    ↓
主节点执行BGSAVE生成RDB
    ↓
主节点发送RDB给从节点
    ↓
从节点加载RDB
    ↓
主节点发送缓冲区写命令
    ↓
进入增量复制阶段

复制方式

方式 说明
全量复制 第一次同步或断开时间较长
增量复制 断开后重连,只同步差异部分
异步复制 主节点写完立即返回,异步同步

4.2 哨兵模式的原理?

答案

哨兵功能

  1. 监控:持续检查主从节点是否正常
  2. 通知:节点故障时通知管理员或其他应用
  3. 自动故障转移:主节点故障时自动选举新主节点

故障转移流程

复制代码
哨兵检测主节点下线(主观下线)
    ↓
多个哨兵确认(客观下线)
    ↓
哨兵选举领导者
    ↓
领导者选举新主节点
    ↓
更新其他从节点的复制目标
    ↓
通知客户端新主节点地址

配置示例

conf 复制代码
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000

4.3 Redis Cluster的原理?

答案

核心概念

  1. 哈希槽:将数据划分为16384个槽,分配给不同节点

  2. 数据分片:每个节点负责一部分槽

  3. Gossip协议:节点间通信,交换状态信息

槽位计算

复制代码
slot = CRC16(key) % 16384

MOVED重定向

当客户端访问的key不在当前节点时,返回MOVED错误,告知正确的节点。

4.4 Cluster和哨兵的区别?

答案

对比项 Cluster 哨兵
数据分片 支持 不支持
高可用 支持 支持
最小节点数 6个 3个
扩展性 支持在线扩容 不支持
客户端 需要集群客户端 普通客户端
复杂度 较高 较低
适用场景 大数据量 小数据量

五、缓存应用面试题

5.1 什么是缓存穿透、击穿、雪崩?

答案

问题 原因 解决方案
缓存穿透 查询不存在的数据 布隆过滤器、空值缓存
缓存击穿 热点key过期 互斥锁、热点预热
缓存雪崩 大量key同时过期 随机过期时间、多级缓存

详细解答

缓存穿透

  • 现象:查询不存在的key,请求穿透到数据库
  • 解决:布隆过滤器过滤不存在的key,或缓存空值

缓存击穿

  • 现象:热点key过期瞬间,大量请求打到数据库
  • 解决:加互斥锁,只允许一个线程查询数据库

缓存雪崩

  • 现象:大量key同时过期,或Redis宕机
  • 解决:随机过期时间、多级缓存、熔断降级

5.2 如何保证缓存和数据库一致性?

答案

常用方案:Cache Aside模式

java 复制代码
// 更新数据
public void update(String key, Object value) {
    // 1. 先更新数据库
    db.update(key, value);
    // 2. 再删除缓存
    cache.delete(key);
}

// 读取数据
public Object get(String key) {
    // 1. 先查缓存
    Object value = cache.get(key);
    if (value != null) {
        return value;
    }
    // 2. 查数据库
    value = db.query(key);
    // 3. 写入缓存
    if (value != null) {
        cache.set(key, value, expire);
    }
    return value;
}

延迟双删

java 复制代码
public void update(String key, Object value) {
    // 1. 删除缓存
    cache.delete(key);
    // 2. 更新数据库
    db.update(key, value);
    // 3. 延迟后再次删除缓存
    Thread.sleep(500);
    cache.delete(key);
}

5.3 为什么是删除缓存而不是更新缓存?

答案

对比项 删除缓存 更新缓存
复杂度
性能 高(懒加载) 低(每次写都更新)
一致性 较好 可能不一致
并发问题 较少 较多

原因分析

  1. 并发安全:删除是幂等操作,更新可能被覆盖

  2. 性能考虑:很多场景缓存可能不会被读取

  3. 数据新鲜:删除后下次读取时加载最新数据


六、分布式锁面试题

6.1 Redis分布式锁如何实现?

答案

基本实现

redis 复制代码
# 加锁
SET lock:key value NX PX 30000

# 解锁(Lua脚本保证原子性)
if redis.call('get', KEYS[1]) == ARGV[1] then
    return redis.call('del', KEYS[1])
else
    return 0
end

Java实现

java 复制代码
public boolean lock(String key, String value, long expireTime) {
    return redisTemplate.opsForValue()
        .setIfAbsent(key, value, expireTime, TimeUnit.MILLISECONDS);
}

public boolean unlock(String key, String value) {
    String script = 
        "if redis.call('get', KEYS[1]) == ARGV[1] then " +
        "    return redis.call('del', KEYS[1]) " +
        "else " +
        "    return 0 " +
        "end";
    Long result = redisTemplate.execute(
        RedisScript.of(script, Long.class),
        Collections.singletonList(key), value);
    return result != null && result == 1L;
}

6.2 Redis分布式锁的可靠性如何保证?

答案

问题 解决方案
死锁 设置过期时间
误删锁 使用唯一标识校验
锁超时 看门狗自动续期
单点故障 Redlock算法
主从切换丢锁 多节点部署

Redisson实现

java 复制代码
RLock lock = redisson.getLock("myLock");
try {
    lock.lock();  // 自动续期
    // 执行业务
} finally {
    lock.unlock();
}

6.3 Redis分布式锁和Zookeeper分布式锁的区别?

答案

对比项 Redis Zookeeper
实现方式 SET NX + 过期时间 临时顺序节点
一致性 最终一致 强一致
性能
锁释放 主动删除或过期 Session断开自动释放
可重入 需要自己实现 天然支持
适用场景 高并发 高可靠

七、性能优化面试题

7.1 如何排查Redis性能问题?

答案

排查步骤

  1. 查看慢查询日志
redis 复制代码
SLOWLOG GET 10
  1. 检查内存使用
redis 复制代码
INFO memory
  1. 检查大key
shell 复制代码
redis-cli --bigkeys
  1. 检查客户端连接
redis 复制代码
CLIENT LIST
  1. 实时监控
redis 复制代码
MONITOR

7.2 如何优化Redis内存使用?

答案

优化方法 说明
选择合适的数据结构 使用编码效率高的类型
控制key长度 使用简短的key名
使用压缩编码 ziplist、intset
设置过期时间 及时清理无用数据
开启内存碎片整理 activedefrag
避免大key 拆分大key

7.3 为什么KEYS命令在生产环境禁用?

答案

  1. 时间复杂度O(N):需要遍历所有key

  2. 阻塞主线程:Redis单线程,KEYS执行期间无法处理其他请求

  3. 影响可用性:大量key时可能导致服务不可用

替代方案:使用SCAN命令

redis 复制代码
SCAN 0 MATCH user:* COUNT 100

八、其他高频面试题

8.1 Redis如何实现消息队列?

答案

方案 实现 特点
List LPUSH + BRPOP 简单,不支持消费组
Pub/Sub PUBLISH + SUBSCRIBE 实时,不持久化
Stream XADD + XREAD 支持消费组,可持久化

Stream实现

redis 复制代码
# 生产消息
XADD mystream * field1 value1

# 消费消息
XREAD GROUP mygroup consumer1 COUNT 1 STREAMS mystream >

8.2 Redis如何实现延迟队列?

答案

使用ZSet实现延迟队列:

java 复制代码
// 添加延迟任务
public void addDelayTask(String taskId, long delayTime) {
    long executeTime = System.currentTimeMillis() + delayTime;
    redisTemplate.opsForZSet().add("delay:queue", taskId, executeTime);
}

// 消费延迟任务
public void consumeDelayTask() {
    while (true) {
        long now = System.currentTimeMillis();
        Set<String> tasks = redisTemplate.opsForZSet()
            .rangeByScore("delay:queue", 0, now, 0, 10);
        
        for (String taskId : tasks) {
            // 尝试获取任务
            Long removed = redisTemplate.opsForZSet()
                .remove("delay:queue", taskId);
            if (removed > 0) {
                // 执行任务
                executeTask(taskId);
            }
        }
        Thread.sleep(100);
    }
}

8.3 Redis如何实现限流?

答案

方案1:计数器限流

java 复制代码
public boolean allowRequest(String key, int limit, long period) {
    long count = redisTemplate.opsForValue().increment(key);
    if (count == 1) {
        redisTemplate.expire(key, period, TimeUnit.SECONDS);
    }
    return count <= limit;
}

方案2:滑动窗口限流

java 复制代码
public boolean allowRequest(String key, int limit, long period) {
    long now = System.currentTimeMillis();
    long start = now - period * 1000;
    
    // 移除过期请求
    redisTemplate.opsForZSet().removeRangeByScore(key, 0, start);
    
    // 统计当前窗口请求数
    long count = redisTemplate.opsForZSet().count(key, start, now);
    
    if (count < limit) {
        redisTemplate.opsForZSet().add(key, UUID.randomUUID().toString(), now);
        return true;
    }
    return false;
}

方案3:令牌桶限流

lua 复制代码
-- Lua脚本实现令牌桶
local tokens = redis.call('get', KEYS[1])
if tokens == false then
    tokens = ARGV[1]
end
if tonumber(tokens) > 0 then
    redis.call('decr', KEYS[1])
    return 1
else
    return 0
end

8.4 Redis如何实现分布式Session?

答案

java 复制代码
// 存储Session
public void setSession(String sessionId, Object data) {
    String key = "session:" + sessionId;
    redisTemplate.opsForValue().set(key, data, 30, TimeUnit.MINUTES);
}

// 获取Session
public Object getSession(String sessionId) {
    String key = "session:" + sessionId;
    return redisTemplate.opsForValue().get(key);
}

// 删除Session
public void deleteSession(String sessionId) {
    String key = "session:" + sessionId;
    redisTemplate.delete(key);
}

8.5 Redis内存满了怎么办?

答案

内存淘汰策略

策略 说明
noeviction 不淘汰,写入报错
allkeys-lru 所有key使用LRU淘汰
volatile-lru 设置过期时间的key使用LRU淘汰
allkeys-lfu 所有key使用LFU淘汰
volatile-lfu 设置过期时间的key使用LFU淘汰
allkeys-random 所有key随机淘汰
volatile-random 设置过期时间的key随机淘汰
volatile-ttl 淘汰即将过期的key

配置

conf 复制代码
maxmemory 4gb
maxmemory-policy allkeys-lru

九、学习路线总结

9.1 Redis学习路线图

复制代码
基础阶段
├── Redis简介与安装
├── 数据类型与命令
├── 持久化(RDB/AOF)
└── 主从复制

进阶阶段
├── 哨兵模式
├── Cluster集群
├── 缓存应用(穿透/击穿/雪崩)
└── 分布式锁

高级阶段
├── 性能优化
├── 内存管理
├── 监控运维
└── 源码分析

9.2 面试重点总结

知识点 重要程度 考察频率
数据类型与应用场景 ★★★★★ 必考
持久化机制 ★★★★★ 必考
主从复制原理 ★★★★☆ 高频
哨兵模式 ★★★★☆ 高频
Cluster集群 ★★★★☆ 高频
缓存三兄弟 ★★★★★ 必考
分布式锁 ★★★★★ 必考
性能优化 ★★★★☆ 高频

十、参考资料

Redis官方文档


十一、互动话题

恭喜你完成了Redis系列的学习!🎉

  1. 这个系列对你有帮助吗?欢迎反馈学习心得!
  2. 面试中遇到过哪些Redis问题?欢迎分享!
  3. 还想学习哪些技术?欢迎留言建议!

Redis系列文章完结撒花!感谢大家的陪伴!


相关推荐
姚愚谦2 小时前
Redis源码阅读1-SDS
redis
IT策士2 小时前
Docker 常见面试问题
docker·容器·面试
小森林之主2 小时前
凌晨3点的闹钟:分布式定时任务设计实战
java·redis·任务调度·cron·分布式定时任务
Amnesia0_02 小时前
MYSQL中表的基本查询
数据库·mysql
Database_Cool_2 小时前
Doris vs 阿里云 AnalyticDB MySQL vs ClickHouse:3 大 OLAP 产品 2026 深度对比
数据库·mysql·阿里云
金融支付架构实战指南2 小时前
秒杀&支付订单异步落地|Redis Stream 可靠队列实战
数据库·redis·缓存·stream·秒杀
小二·3 小时前
AI Agent 数据库运维实战
运维·数据库·人工智能
曹牧3 小时前
Oracle:子查询返回多行
数据库·oracle
SiYuanFeng3 小时前
大模型 / RAG / Agent 面试高频题
人工智能·面试·transformer·agent·rag