
8月准备Java面试Redis这一块是绕不开的高频考点。无论是校招还是社招Redis 都是面试官最喜欢深挖的方向它不像 MySQL 那样以背 SQL 为主而是可以通过数据结构、缓存设计、分布式锁、集群方案层层递进地考察候选人的实战能力。网上关于 Redis 面试题的资料很零散不少文章只给结论不给原理看完记住结论面试官多问一句“为什么”就容易露馅。这篇文章会把 Redis 面试中最核心的知识点整理成一套完整的复习体系按照“概念-数据结构-持久化-缓存问题-分布式锁-集群-排错-复习路线”的顺序展开。每部分都会给出面试中高频的问题、标准的回答思路、容易踩的坑以及配套的命令和代码示例。不管你是刚开始准备面试还是已经进入冲刺阶段都可以直接对照这篇文章查漏补缺。先把这份内容存下面试前翻一遍确实能少走很多弯路。1. 先搞清楚 Redis 在面试中到底考什么1.1 Redis 是什么为什么面试必考RedisRemote Dictionary Server是一个基于内存的键值型 NoSQL 数据库。它的核心特点是所有数据都存储在内存中所以读写速度非常快官方给出的基准测试中单实例 QPS 可以达到 10 万级别。同时它支持持久化、过期策略、发布订阅、事务、Lua 脚本、分布式锁、集群扩展等丰富的功能所以在互联网项目中Redis 主要用于缓存、会话共享、排行榜、分布式锁、消息队列等场景。面试中考察 Redis本质上是从三个维度进行面试者是否掌握 Redis 的数据模型和常用命令。面试者是否理解 Redis 的底层机制比如持久化、淘汰策略、线程模型。面试者是否具备在真实项目中解决缓存问题、设计分布式方案的能力。这三个维度由浅入深正好对应面试官追问的节奏。如果只是背题不深入很容易在追问环节被识别出来。1.2 Redis 和 MySQL 有什么区别这是面试开场高频题。标准的回答思路是MySQL 是关系型数据库数据存储在磁盘上支持复杂的 SQL 查询、事务 ACID、表关联。Redis 是基于内存的键值存储读写速度快但一般不作为唯一数据源而是作为缓存层加速访问。Redis 支持的数据类型更丰富如 String、Hash、List、Set、ZSet每种类型都有自己的适用场景。MySQL 的数据一致性由事务保证Redis 在持久化上存在丢数据的可能取决于持久化策略所以两者一般是配合使用。回答时要强调“Redis 不是用来替代 MySQL 的而是为了提升系统的读取性能”。如果面试官问“为什么不直接用 Redis 存所有数据”可以从成本、内存容量、事务能力、持久化能力等方面回答。1.3 Redis 为什么快这个问题基本必问回答要点可以归纳为四点纯内存操作。数据放在内存中读写不涉及磁盘 IO。单线程模型。Redis 网络请求处理使用单线程避免了多线程上下文切换和锁竞争的开销。注意Redis 6.0 之后引入了多线程 IO但核心命令执行仍然是单线程的。IO 多路复用。Redis 基于 epoll 实现 IO 多路复用可以在一个线程里处理多个连接的读写事件。高效的数据结构。Redis 底层使用 SDS、跳表、压缩列表、哈希表等高效结构在不同数据量和场景下自动选择最优编码。面试官可能会追问“单线程为什么还这么快”核心原因就是 CPU 不是瓶颈内存和网络的 IO 才是瓶颈而单线程避免了锁和上下文切换。2. Redis 核心数据结构与常见面试问题2.1 String 字符串String 是 Redis 最基础的数据类型value 最大能存储 512MB。底层实现是 SDSSimple Dynamic String相比 C 字符串SDS 可以 O(1) 获取长度、避免缓冲区溢出、减少内存重分配次数。常用命令SET key value GET key INCR key DECR key EXPIRE key seconds SETEX key seconds valueString 的典型应用场景缓存用户信息、配置数据。计数器如点赞数、访问量。分布式 ID 生成利用 INCR 命令生成递增序列。分布式锁的SET key value NX EX也是基于 String 实现的。面试题举例“String 的底层实现是什么和传统 C 字符串有什么不同”回答时把 SDS 的动态扩容、二进制安全、获取长度 O(1) 这三个特点说出来即可。2.2 Hash 哈希Hash 类型是一个 string 类型的 field 和 value 的映射表适合存储对象数据。比如一个用户对象包含 id、name、age如果用 String 存储需要序列化整个对象更新某个字段要重新写入整个对象用 Hash 则可以直接更新某个字段。常用命令HSET user:1001 name zhangsan HGET user:1001 name HGETALL user:1001 HDEL user:1001 name HINCRBY user:1001 age 1Hash 底层在数据量小的时候使用压缩列表ziplist数据量大时转为哈希表hashtable。因为 Redis 3.2 之后引入了 listpack不同版本的编码细节略有差异但面试中掌握“小数据量压缩存储、大数据量哈希表”这个思路就够了。面试题举例“Hash 和 String 都存对象怎么选”一般推荐对象字段频繁修改、只需要部分字段时用 Hash对象整体读取、转发给前端时用 String JSON 更省内存且直观。2.3 List 列表List 是简单的字符串列表按照插入顺序排序可以从头部或尾部添加元素。底层在元素少时使用压缩列表元素多时转为双向链表quicklist 是 Redis 3.2 之后引入的混合结构。常用命令LPUSH key value [value ...] RPUSH key value [value ...] LPOP key RPOP key LRANGE key start stop LLEN key典型应用场景消息队列LPUSH BRPOP 实现简单的生产消费模型。最新动态列表用 LPUSH 把新数据放到头部用 LRANGE 分页查询。时间线列表关注的人发布动态后推送到自己的 List 中。面试题举例“List 和 Stream 做消息队列有什么区别”List 结构简单但无法支持消费组、消息确认等特性Redis Stream5.0 引入支持消费者组、消息持久化、ACK 确认更适合可靠性要求更高的场景。2.4 Set 集合Set 是无序、不可重复的字符串集合。集合操作支持交集、并集、差集这是它在业务中最大的价值。常用命令SADD key member [member ...] SMEMBERS key SREM key member SISMEMBER key member SINTER key1 key2 # 交集 SUNION key1 key2 # 并集 SDIFF key1 key2 # 差集典型应用场景抽奖去重用户参与抽奖SADD 时自动去重。共同关注用 SINTER 获取两个用户的共同关注列表。标签系统给文章打标签用 SMEMBERS 查询标签用 SINTER 查同时包含多个标签的文章。2.5 ZSet 有序集合ZSet 在 Set 的基础上给每个成员增加了一个 score分值Redis 根据 score 自动排序。底层实现是跳表skiplist加哈希表。常用命令ZADD key score member ZRANGE key start stop ZREVRANGE key start stop ZSCORE key member ZINCRBY key increment member ZRANK key member典型应用场景排行榜。比如游戏积分排行榜、商品销量榜用 ZINCRBY 增加分数用 ZREVRANGE 获取 Top N。延迟队列。把任务执行时间作为 score用一个线程轮询 ZRANGEBYSCORE 获取到期的任务。滑动窗口限流。用 score 存时间戳通过 ZRANGEBYSCORE 统计时间窗口内的请求数。面试中经常追问“ZSet 的底层结构为什么用跳表而不是红黑树”回答要点跳表实现简单、支持范围查询、在有序集合的场景下性能足够O(log N)而且跳表更适合做范围查找ZSet 的核心操作就是按分数范围取数据。2.6 其他高级数据类型面试加分项Bitmap位图用位操作存储布尔型数据典型场景是用户签到、在线状态。HyperLogLog去重计数内存极小适合统计 UV。GEO地理位置存储适合“附近的人”功能。Stream可靠消息队列支持消费者组。这部分可以展示知识广度面试官如果追问能说出“GEO 底层基于 ZSet 实现每个位置的经纬度会被编码为 score”这种程度就够用了。3. Redis 持久化机制RDB 和 AOF3.1 为什么需要持久化Redis 是内存型数据库如果进程异常退出或服务器宕机内存中的数据会全部丢失。持久化的目的就是把内存中的数据保存到磁盘上使 Redis 重启时能够恢复数据。面试中问到持久化通常围绕两个问题RDB 和 AOF 分别是什么如何选择3.2 RDB 快照持久化RDBRedis DataBase是在指定时间间隔内将内存中的数据集快照写入磁盘生成一个二进制的 dump.rdb 文件。触发方式# 手动触发 SAVE BGSAVE # 自动触发在 redis.conf 中配置 save 900 1 save 300 10 save 60 10000SAVE 会阻塞 Redis 主进程BGSAVE 会 fork 子进程来生成 RDB主进程继续处理命令。面试中需要说清楚RDB 的优点是文件紧凑、恢复速度快、适合做备份和灾难恢复缺点是可能丢失最后一次快照之后的数据同时 fork 子进程在大数据量下会有短暂的阻塞。3.3 AOF 追加持久化AOFAppend Of File会把每次写命令追加到 aof 文件末尾。Redis 重启时通过重新执行 AOF 文件中的命令来恢复数据。AOF 默认是关闭的开启配置appendonly yes appendfilename appendonly.aof appendfsync always appendfsync everysec appendfsync no配置项说明always每次写入都同步到磁盘数据最安全性能最差。everysec每秒同步一次最多丢失 1 秒数据是推荐配置。no由操作系统决定什么时候同步性能好但安全性不可控。为了避免 AOF 文件过大Redis 提供了 AOF 重写机制通过BGREWRITEAOF命令或自动触发用尽可能少的命令来记录当前数据集。3.4 RDB 和 AOF 怎么选对比项RDBAOF文件大小二进制压缩文件小记录写命令文件较大恢复速度快较慢数据安全性可能丢较多数据最多丢 1 秒everysec对性能影响fork 子进程可能瞬间阻塞写频率高时影响较大生产环境常用的方案是同时开启 RDB 和 AOF。Redis 优先使用 AOF 恢复数据因为 AOF 数据更完整同时利用 RDB 做定期备份。如果对数据丢失容忍度很低必须开启 AOF 并设置 appendfsync everysec。4. 缓存设计穿透、击穿、雪崩与解决方案4.1 缓存穿透缓存穿透是指查询一个不存在的数据缓存中没有数据库中也没有导致每次请求都直接打到数据库。如果有恶意攻击者持续构造不存在的 key数据库压力骤增。解决方案缓存空值查询结果为空也缓存设置较短的过期时间。布隆过滤器把所有可能存在的数据哈希到一个 bitmap 中请求先经过布隆过滤器过滤掉大部分不存在的 key。参数校验在接口层拦截明显不合法的请求。示例代码缓存空值使用 Spring Data Redispublic Object getData(String key) { Object value redisTemplate.opsForValue().get(key); if (value ! null) { return value; } // 模拟从数据库查询 Object dbValue queryFromDB(key); if (dbValue null) { // 缓存空值防止穿透过期时间设置短一些 redisTemplate.opsForValue().set(key, , 60, TimeUnit.SECONDS); } else { redisTemplate.opsForValue().set(key, dbValue, 30, TimeUnit.MINUTES); } return dbValue; }4.2 缓存击穿缓存击穿是指某个热点 key 刚好在过期时间失效此时大量并发请求同时查询这个 key缓存未命中请求全部打到数据库。解决方案互斥锁只允许一个线程查数据库并重建缓存其他线程等待。逻辑过期缓存中不设置物理过期时间而是存储一个逻辑过期时间字段查询时判断是否过期如果过期则异步重建缓存。热点数据永不过期在 value 中保存过期时间业务层判断后异步更新。这里给出基于互斥锁的简化示例public String getHotData(String key) { String value redisTemplate.opsForValue().get(key); if (value ! null) { return value; } String lockKey lock: key; boolean locked redisTemplate.opsForValue().setIfAbsent(lockKey, 1, 3, TimeUnit.SECONDS); if (locked) { try { value queryFromDB(key); redisTemplate.opsForValue().set(key, value, 30, TimeUnit.MINUTES); return value; } finally { redisTemplate.delete(lockKey); } } else { // 等待其他线程写入缓存 try { Thread.sleep(100); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } return getHotData(key); } }互斥锁方案简单有效代价是缓存重建期间有少量线程等待。实际项目中要重点关注锁的释放避免因异常导致锁无法释放。4.3 缓存雪崩缓存雪崩是指大量 key 在同一时间失效或者 Redis 服务宕机导致所有请求直接打到数据库。解决方案过期时间随机化在设置过期时间时加上一个随机值避免同一时间大面积失效。Redis 集群高可用使用主从复制、哨兵或 Cluster 模式避免单点故障。多级缓存本地缓存如 Caffeine Redis 缓存即使 Redis 不可用本地缓存也能扛一部分流量。服务降级在数据库层增加限流和降级策略保护数据库不被压垮。面试中更好的回答是“缓存雪崩的重点不是如何保证 Redis 不宕机而是要在 Redis 不可用或缓存大规模失效时系统依然能通过降级、限流、多级缓存等手段保持可用。”4.4 缓存一致性问题只要用 Redis 做缓存就绕不开“缓存和数据库数据不一致”的问题。常见的方案Cache Aside Pattern旁路缓存读的时候先读缓存缓存没有则读数据库并回填写的时候先更新数据库再删除缓存。延迟双删更新数据库后删除缓存等一段时间再次删除避免并发下读到旧数据。基于 Canal 监听 MySQL binlog异步更新缓存。面试中不要只说一个方案要能分析利弊。比较推荐的回答一般业务采用 Cache Aside 模式更新时“先更新数据库再删除缓存”如果要求更高的一致性可以引入分布式事务或 binlog 异步同步但这会增加系统复杂度需要根据业务权衡。5. Redis 分布式锁5.1 为什么要用分布式锁在分布式系统中多个服务实例同时操作共享资源时Java 的synchronized和ReentrantLock只能锁住当前 JVM 内的线程无法跨进程互斥。分布式锁就是让多个进程之间通过 Redis 实现互斥访问。5.2 基于 Redis 实现分布式锁的演进最早的方案是使用SETNX加锁然后EXPIRE设置过期时间但这两个命令不是原子的如果在 SETNX 之后、EXPIRE 之前进程崩溃锁就会永远不释放。后来 Redis 官方推荐使用SET key value NX EX seconds一条命令完成加锁和过期时间设置。加锁命令SET lock:order:1001 uuid_value NX EX 30释放锁时不能直接DEL因为如果锁已经过期另一个线程获取了同一把锁当前线程再执行 DEL 就会误删别人的锁。所以释放锁需要先比较 value 是否还是自己的再删除这个过程要用 Lua 脚本保证原子性-- 释放锁的 Lua 脚本 if redis.call(get, KEYS[1]) ARGV[1] then return redis.call(del, KEYS[1]) else return 0 endJava 中通过 Spring Data Redis 执行 Lua 脚本private static final String UNLOCK_SCRIPT if redis.call(get, KEYS[1]) ARGV[1] then return redis.call(del, KEYS[1]) else return 0 end; public void unlock(String lockKey, String requestId) { DefaultRedisScriptLong script new DefaultRedisScript(UNLOCK_SCRIPT, Long.class); redisTemplate.execute(script, Arrays.asList(lockKey), requestId); }5.3 Redisson 与看门狗机制手写分布式锁需要处理各种边界条件生产环境推荐使用 Redisson。Redisson 提供了RLock内部通过 Lua 脚本实现加锁、解锁、重入还提供了看门狗机制如果锁的持有者没有显式释放锁看门狗会每隔一段时间自动续期防止业务没执行完锁就过期了。RLock lock redissonClient.getLock(lock:order:1001); try { // 尝试加锁最多等待 5 秒锁有效期默认 30 秒看门狗会自动续期 if (lock.tryLock(5, TimeUnit.SECONDS)) { // 业务逻辑 } } finally { if (lock.isHeldByCurrentThread()) { lock.unlock(); } }5.4 RedLock 有必要用吗RedLock 是 Redis 官方提出的多节点分布式锁算法要求向多个独立的 Redis 主节点加锁超过半数成功才算加锁成功。面试中经常被问到但实际项目中较少使用因为 RedLock 依赖时钟同步、网络延迟实现复杂且在多主切换下仍存在一致性问题。推荐回答思路“单节点 Redis 锁 Redisson 的看门狗在绝大多数业务中已经够用如果要更强的安全性优先考虑 ZooKeeper 或 etcd 的分布式锁而不是 RedLock。”6. Redis 集群与可用性6.1 主从复制Redis 主从复制是指一台主节点Master将数据同步到多台从节点Slave实现读写分离和容灾。主节点负责写操作从节点负责读操作数据由主节点单向同步到从节点。顺序上主从复制分为两个阶段全量复制从节点首次同步时主节点生成 RDB 快照并发送给从节点。增量复制后续主节点把写命令发送给从节点。从节点断开重连后主节点通过复制积压缓冲区同步断连期间的数据。配置方式# 从节点配置 replicaof 127.0.0.1 63796.2 哨兵模式主从复制解决了数据备份和读写分离但主节点宕机后需要人工把某个从节点提升为主节点。哨兵Sentinel可以自动监控主节点和从节点的健康状态在主节点故障时自动完成故障转移从剩余从节点中选举新的主节点。哨兵的关键作用监控检查主从节点的运行状态。通知节点故障时通知其他实例。自动故障转移主节点不可用时自动选举新的主节点。配置中心客户端通过哨兵获取当前主节点地址。6.3 Cluster 集群模式Redis Cluster 是 Redis 3.0 引入的分布式解决方案能够将数据自动分片到多个节点上每个节点保存一部分数据。Redis Cluster 采用无中心化架构节点之间通过 Gossip 协议通信。分片原理整个数据空间被划分为 16384 个哈希槽slot。每个节点负责一部分 slot例如三主节点分别负责 0~5460、5461~10922、10923~16383。计算 key 的 CRC16 值然后对 16384 取模得到该 key 应该存储到哪个 slot。Cluster 模式的优势是支持水平扩展性能随节点增加而提升。需要注意的坑是 Cluster 模式下不支持多 key 操作除非这些 key 在同一个 slot因此需要使用 Hash Tag 技术让相关 key 落到同一个槽位。面试常见问题“为什么 Redis Cluster 是 16384 个槽”常见的解释是16384 个槽在保证数据分布均匀的同时可以使节点间心跳消息中的位图更小减少带宽消耗且对于常用规模的集群已经足够。6.4 一致性哈希和哈希槽可能被追问“Redis 为什么不用一致性哈希”。一致性哈希是分布式缓存中常用的分片算法如 Memcached但 Redis Cluster 选择哈希槽的原因主要有哈希槽将数据分成固定数量的槽位节点增减时只需要迁移部分槽位数据迁移范围可控。槽位和节点的映射关系明确客户端可以精确计算 key 所在节点。数据迁移时是以槽为单位进行操作粒度更清晰。7. Redis 内存淘汰与常见问题排查7.1 过期删除策略Redis 的过期删除策略是“惰性删除 定期删除”的结合惰性删除访问 key 时检查是否过期过期则删除。优点是不占用额外 CPU缺点是过期 key 可能长期占用内存。定期删除Redis 每隔一段时间随机抽取一部分设置了过期时间的 key删除其中已过期的 key。7.2 内存淘汰策略当 Redis 内存达到maxmemory限制后会根据配置的maxmemory-policy进行淘汰。常见配置项策略含义noeviction不淘汰写入时报错allkeys-lru从所有 key 中按 LRU 淘汰volatile-lru从设置了过期时间的 key 中按 LRU 淘汰allkeys-lfu从所有 key 中按 LFU 淘汰volatile-lfu从设置了过期时间的 key 中按 LFU 淘汰allkeys-random从所有 key 中随机淘汰volatile-ttl从设置了过期时间且剩余时间最短的 key 中淘汰面试中回答“生产环境推荐哪种策略”时不要直接说“用 allkeys-lru”。正确的思路是优先给每个 key 设置合理的过期时间根据业务是否允许缓存丢失决定使用 volatile-lru 还是 allkeys-lru如果业务数据要求严格不淘汰则使用 noeviction 并做好告警。7.3 内存不足报错 OutOfMemoryErrorJVM 项目和 Redis 都会出现内存不足的报错。热词中出现的java: outofmemoryerror: insufficient memory属于 JVM 启动时内存不足常见原因是启动 JVM 时指定的 -Xmx 大于物理内存。服务器内存被其他进程占用剩余可用内存不足。系统没有足够交换空间。排查方法# 查看系统内存 free -h # 查看 Java 进程内存占用 ps aux | grep java jmap -heap pid如果 Redis 本身内存不足可以检查maxmemory配置、大 key、连接数、内存碎片率必要时扩容或清理大 key。7.4 连接失败和超时Redis 连接失败通常表现为ERR max number of clients reached或RedisConnectionFailureException。排查思路检查 Redis 服务是否启动redis-cli ping。检查端口连通性telnet 127.0.0.1 6379。检查客户端最大连接数配置CONFIG GET maxclients。检查防火墙和远程访问配置bind、protected-mode。检查业务代码是否存在连接池泄漏用完连接没有释放。Spring Boot 中可以通过配置连接池参数优化spring.redis.hostlocalhost spring.redis.port6379 spring.redis.lettuce.pool.max-active50 spring.redis.lettuce.pool.max-idle20 spring.redis.lettuce.pool.min-idle5 spring.redis.lettuce.pool.max-wait3000ms7.5 热词背后的 Redis 高频面试题库根据搜索热词高频被搜的还有redis 下载、windows 安装 redis、docker 安装 redis 主从、redis desktop manager 可视化客户端、redis 缓存治理。这些属于环境搭建和运维工具建议在复习基础知识的同时把本机环境搭好用 Redis Desktop Manager 或 Another Redis Desktop Manager 连一次能加深对 Redis 数据结构的印象。8. 三天冲刺计划与复习建议8.1 第 1 天数据结构与基础命令把 String、Hash、List、Set、ZSet 的常用命令全部敲一遍。理解每个类型的底层编码和适用场景。用 Spring Data Redis 写一个增删改查的小 Demo。当天结束前完成自测能默写每种数据类型至少两个应用场景。8.2 第 2 天持久化、缓存问题与分布式锁配置 RDB 和 AOF观察 dump.rdb 和 appendonly.aof 文件的生成。手写缓存穿透、击穿、雪崩的解决方案示例。手写 SET NX EX 分布式锁和 Lua 解锁脚本。看完 Redisson 官方文档了解 RLock 基本用法。8.3 第 3 天集群、运维与面试模拟用 Docker 搭建一主两从、哨兵或 Cluster 环境。检查 Redis 日志分析主从复制和故障转移的过程。把高频面试题制作成卡片按“先结论后原理再举例”的方式模拟作答。# Docker 搭建 Redis 主从示例 docker run -d --name redis-master -p 6379:6379 redis:latest docker run -d --name redis-slave1 -p 6380:6379 --link redis-master \ redis:latest redis-server --replicaof redis-master 6379 docker run -d --name redis-slave2 -p 6381:6379 --link redis-master \ redis:latest redis-server --replicaof redis-master 63798.4 面试答题的通用模板面试中回答 Redis 相关问题时推荐采用“结论先行展开原理结合实际场景”的结构先给结论用一两句话说清楚是什么比如“缓存雪崩是指大量 key 同时过期导致请求打到数据库”。展开原因和原理说明为什么会出现。给出解决方案结合自己的项目经验描述实际是怎么处理的。如果被追问说明方案的优缺点和备选方案。8.5 面试中避免踩的坑只背结论不解释原理。面试官只要追问“为什么”就会暴露。忽略版本差异。Redis 6.0 引入了多线程 IO5.0 引入了 Stream不同版本支持的配置和行为有差异回答时注明“以 Redis 6.x/7.x 为例”。不区分单机和生产环境。面试官问分布式锁就不要只说SETNX一条命令完事要聊到锁释放的原子性、看门狗、集群下的问题。空谈高并发。说“我们项目用了 Redis”时至少能说出具体存了什么、为什么用 Hash 而不是 String、过期时间怎么设置的。9. Redis 面试中容易被忽略的细节9.1 Redis 是单线程的为什么还要用连接池虽然是单线程处理命令但每个客户端连接都需要占用一个文件描述符建立和断开连接也有开销。连接池的作用是复用已经建立的连接减少 TCP 握手和 Redis 处理连接事件的消耗让业务代码在高并发下不至于频繁创建连接。9.2 大 key 和热 key 问题大 key 是指 value 非常大例如一个 List 有几百万个元素或包含大量元素的 key。大 key 会造成阻塞、内存不均、网络拥塞。热 key 是指被高频访问的 key可能单点压力过大。解决方案大 key 拆分将大对象的字段拆分到多个 Hash key 中。对大 key 使用 SCAN 命令扫描避免使用 KEYS。热 key 加本地缓存或副本分散读压力。使用redis-cli --bigkeys扫描大 key。9.3 为什么生产环境禁止使用 KEYS 命令KEYS 命令会遍历所有 key在数据量大的情况下阻塞 Redis 主线程导致整个实例不可服务。推荐使用 SCAN 命令分批迭代不会阻塞。SCAN 0 MATCH user:* COUNT 1009.4 Redis 事务和 Lua 脚本Redis 事务通过 MULTI、EXEC、DISCARD 实现和 MySQL 事务不同Redis 事务不支持回滚只是把命令按顺序打包执行。如果在事务中发现命令语法错误事务会中断如果运行时错误如对字符串执行 INCR其他命令仍会执行。Lua 脚本则可以通过EVAL和EVALSHA将一段逻辑在服务端原子执行在分布式锁、限流等场景中非常常用。10. 实战踩坑记录10.1 缓存和数据库一致性出问题业务中曾经出现过修改用户信息后缓存里还是旧数据的情况。原因是代码里先删缓存再更新数据库并发情况下另一个线程先查数据库还没写完然后更新线程把旧数据又写回缓存。后来统一改成“先更新数据库再删除缓存”并加上延迟双删兜底才基本解决了问题。10.2 分布式锁导致的死锁手写分布式锁时使用 SETNX 加锁后忘记设置过期时间在业务出现异常时锁没有被释放其他线程一直拿不到锁。排查发现锁的 value 没有区分线程释放锁时直接 DEL导致误删了其他线程的锁。后来统一改为随机 UUID 作为 value并用 Lua 脚本校验后删除。10.3 Redis 连接数被打满上线后发现大量报错ERR max number of clients reached原因是项目使用redisTemplate时没有配置连接池的最大值默认连接数不够同时部分请求执行很慢连接被长期占用。解决方式是调大连接池最大连接数并优化慢查询排查业务代码中是否有大量不必要的 Redis 操作。11. 常见问题速查表下面这张表汇总了 Redis 面试中最高频的 12 个问题可以作为考前最后一天的速查清单问题核心回答要点Redis 为什么快内存存储、单线程、IO 多路复用、高效数据结构Redis 有哪些数据类型String、Hash、List、Set、ZSet、Bitmap、HyperLogLog、GEO、StreamString 底层是什么SDSO(1) 获取长度、避免缓冲区溢出、动态扩容ZSet 底层为什么要用跳表实现简单、支持范围查询、O(log N) 性能RDB 和 AOF 怎么选同时开启AOF 恢复为主RDB 做备份什么是缓存穿透查询不存在的数据布隆过滤器或缓存空值什么是缓存击穿热点 key 失效互斥锁或逻辑过期什么是缓存雪崩大量 key 同时失效或 Redis 宕机过期时间随机化、集群高可用分布式锁怎么实现SET NX EX Lua 解锁生产用 RedissonRedis 集群有几种主从、哨兵、Cluster演进关系Cluster 数据分片怎么分CRC16(key) % 16384 定位哈希槽Redis 内存满了怎么办maxmemory-policy 配置淘汰策略推荐 volatile-lru 或 allkeys-lru这份速查表里的每个问题都应该能展开讲 3 到 5 分钟。Redis 面试题表面上看是背考点实际上考的是对缓存设计和分布式场景的理解。把数据结构、持久化、缓存问题、分布式锁、集群模式这几条主线串起来配合手写命令和代码3 天时间足够把 Redis 这一块准备得比较扎实。面试时如果能随口说出 LInux 下的 redis-cli 命令以及 Spring Boot 中如何配置连接池会明显比只会背概念的候选人更有竞争力。这份清单可以先存下来每天过一遍8 月面试时不慌。