公司动态

Redis面试高频考点与项目实践:从数据类型到分布式锁的3天复习清单

📅 2026/8/31 13:29:19
Redis面试高频考点与项目实践:从数据类型到分布式锁的3天复习清单
8月的 Java 面试窗口又到了Redis 作为服务端开发绕不开的基础组件几乎每一轮技术面都会出现。很多同学的问题不是“没看过 Redis”而是“看了很多面试时答不到点上”背过八股但一说项目里的实际场景就卡壳知道数据类型但不清楚每种类型的底层结构和适用边界会写简单的set/get但一聊分布式锁、缓存穿透、集群分片就开始含糊。这篇文章把 Redis 面试准备压缩成 3 天可执行的高频考点清单直接按面试官的提问顺序来梳理先过数据类型和底层结构再过持久化与过期策略然后集中攻缓存三大难题、分布式锁、集群架构和生产环境排查思路。每一块都给出“面试官到底在问什么”“标准答法怎么组织”“项目里怎么落地”三个层次适合 8 月正冲刺 Java 后端岗位的同学直接对照复习。1. 核心考点速览考点模块面试频次需要掌握的核心内容项目落地场景数据类型与底层结构极高String、Hash、List、Set、ZSet 的使用与编码转换缓存、计数器、排行榜、去重持久化机制高RDB、AOF 原理与混合持久化数据恢复、灾备过期删除与内存淘汰很高删除策略、内存淘汰策略与场景选择缓存淘汰、热点数据保护缓存三大问题很高穿透、击穿、雪崩的成因与解决方案缓存设计、接口优化缓存与数据库一致性很高Cache Aside Pattern、延迟双删订单、商品详情等同步场景分布式锁很高set nx ex、Redisson、RedLock 的取舍秒杀、防重、任务调度Redis 集群与高可用高主从复制、哨兵、Cluster 分片高并发读写、水平扩容Lua 脚本与原子性中高eval命令、限流、原子操作限流器、库存扣减2. Redis 本地环境准备2.1 Windows 下安装 RedisWindows 官方没有直接维护 Redis 的稳定安装包常见的做法是使用 tporadowski 维护的 Windows 移植版也可以直接使用 Docker 跑 Linux 容器。如果是本地快速验证核心命令推荐 Docker 方式环境更干净和线上 Linux 行为一致。docker run -d --name redis-local -p 6379:6379 redis:7.0如果要挂载数据目录可以加-vdocker run -d --name redis-local \ -p 6379:6379 \ -v /data/redis:/data \ redis:7.0 --appendonly yes启动后确认是否正常docker ps redis-cli -h 127.0.0.1 -p 6379 ping能看到PONG说明服务正常。2.2 Linux / Mac 下安装Linux 和 Mac 上建议直接用包管理器或编译安装最新稳定版本。# Ubuntu / Debian apt-get update apt-get install -y redis-server # CentOS yum install -y redis # Mac brew install redis编译安装指定版本的方式wget https://download.redis.io/releases/redis-7.0.14.tar.gz tar xzf redis-7.0.14.tar.gz cd redis-7.0.14 make make install redis-server --version编译之前需要确认系统有gcc和make缺少编译环境会出现cc: command not found之类的错误。2.3 可视化工具选择面试和日常开发不强制要求可视化工具但本地调试时能直观看到 key 的类型、过期时间和内存占用会更快。常用的有 Redis Desktop Manager、Another Redis Desktop Manager。这类工具连接方式基本都是地址127.0.0.1端口6379密码如果设置了requirepass才需要填生产环境不建议直接给工具开放公网端口把 Redis 绑定到127.0.0.1或者走内网访问是底线。3. 高频考点一Redis 数据类型与底层结构这块是 Redis 面试的“开场菜”面试官通常会直接问“Redis 有哪些数据类型分别用在什么场景”3.1 五种基本类型String最基础的类型底层是 SDS简单动态字符串支持set、get、incr、decr、setnx、setex、mset等命令。典型场景是缓存、计数器、分布式锁、共享 Session。set user:10001 {name:zhangsan,age:18} incr page:view setnx lock:order:10001 1 setex user:token:10001 7200 token-valueincr是原子的这也是用 Redis 做计数器的核心原因。Hash适合存对象属性底层是哈希表或压缩列表ziplist。修改某个字段不需要整个对象序列化重写。hset user:10001 name zhangsan age 18 hget user:10001 name hincrby user:10001 age 1电商购物车、用户信息管理这种“对象内局部更新”的场景Hash 比 String 更合适。List底层是双向链表或压缩列表支持头尾插入、范围查询。可以用作消息队列的临时存储、时间线列表、简单历史记录。lpush news:10001 article_1 rpop news:10001 lrange news:10001 0 9注意 List 做消息队列只是“可用”没有消费确认、重复消费、消息堆积的完整机制工程上更推荐 Redis Stream 或专门的 MQ。Set底层是哈希表或整数集合成员唯一且无序适合做去重、共同关注、抽奖。sadd user:lisi tag:java tag:redis sadd user:wangwu tag:java sinter user:lisi user:wangwu scard user:lisiZSet每个成员带 score按 score 排序底层是跳跃表 哈希表。排行榜、延迟队列、限流窗口都依赖它。zadd rank:202408 100 user_01 zadd rank:202408 88 user_02 zrevrange rank:202408 0 9 withscores zincrby rank:202408 10 user_013.2 底层编码与转换条件面试官如果继续深入会问“哈希在什么条件下从压缩列表变成哈希表”这属于底层编码的问题。Redis 在不同版本里的默认配置略有差异但核心逻辑是Hash元素少且值小时用 ziplist超过阈值后变成 hashtableZSet元素少时用 ziplist或 listpack超过阈值后变成 skiplistList元素少时用 quicklist 节点压缩大数据量时以 quicklist 为主这类问题不需要背出精确数字但要能讲清楚“压缩数据结构节省内存但读写复杂度与数据量相关所以小数据量用紧凑结构大数据量换成分散结构”的设计思路。3.3 Redis 6/7 新增结构较新的版本引入了 Stream消息队列、HyperLogLog基数统计、Bitmap位图、Geospatial地理位置。面试时能主动提到 Stream 和 HyperLogLog 是加分项特别是结合“UV 统计”“点击去重”“消息队列”这些实际场景。4. 高频考点二Redis 持久化机制面试官通常会问“Redis 是内存数据库数据会不会丢怎么保证重启后数据还在”4.1 RDB 快照RDB 会把某一时间点的全量数据写入磁盘默认生成dump.rdb。触发时机包括配置中save 900 1、save 300 10、save 60 10000手动执行save或bgsave关闭服务时默认触发优点文件紧凑恢复速度快适合做备份和冷数据迁移。缺点两次快照之间的数据可能丢失。4.2 AOF 日志AOF 记录每次写命令的追加日志重启时回放命令恢复数据。相关配置appendonly yes appendfilename appendonly.aof appendfsync everysec三种刷盘策略策略数据安全性性能影响always每条命令都刷盘最安全性能损耗最大everysec每秒刷盘一次最多丢 1 秒数据性能和安全的折中no交给操作系统决定性能最好可能丢更多数据工程上最常用的是everysec。4.3 RDB AOF 混合使用Redis 4.0 之后可以开启混合持久化用 RDB 作为全量基础再叠加 AOF 增量日志兼顾恢复速度和数据安全性。面试回答思路可以这样组织默认开启 RDB但如果追求更强的可靠性会开启 AOF。AOF 的appendfsync选everysec最多丢一秒数据。大版本恢复场景用混合持久化先加载 RDB 再回放增量 AOF比全量回放 AOF 快。5. 高频考点三过期删除与内存淘汰策略5.1 过期删除策略Redis 使用两种方式组合惰性删除key 被访问时才检查是否过期过期则删除。优点是不额外消耗 CPU缺点是过期 key 如果不访问会一直占内存。定期删除后台任务周期性抽取一部分 key 检查并删除过期 key兼顾 CPU 和内存。这是一个高频追问点Redis 为什么不像其他组件一样用定时扫描全量 key答案是为了避免 O(N) 扫描对主线程造成阻塞。5.2 内存淘汰策略当内存达到maxmemory限制时Redis 需要按策略淘汰部分 key。maxmemory 2gb maxmemory-policy allkeys-lru常见策略策略含义适用场景noeviction不淘汰直接报错不推荐生产使用allkeys-lru所有 key 中淘汰最近最少使用通用缓存volatile-lru仅淘汰设了过期时间的 key 中最近最少使用缓存与持久数据混合allkeys-lfu所有 key 中淘汰访问频率最低热点数据明显volatile-ttl淘汰剩余过期时间最早临时数据优先清理面试里常问“LRU 和 LFU 的区别”要答出LRU 看最后一次访问时间LFU 看访问频率。Redis 的近似 LRU 并不是严格遍历全局而是采样淘汰避免额外内存开销。6. 高频考点四缓存穿透、击穿、雪崩这是项目八股里含金量最高的一组问题需要背熟更需要能结合实际场景展开。6.1 缓存穿透查询一个数据库中也不存在的数据请求直接穿透 Redis 打到数据库。方案组合缓存空值即使数据库没有数据也在 Redis 写一个空值或占位符并设置短过期时间。布隆过滤器启动时把合法 key 集合构建成布隆过滤器查询前先判断 key 是否存在不存在直接返回。接口层参数校验非法参数直接拦截。6.2 缓存击穿某个热点 key 在缓存过期的瞬间大量并发请求同时打到数据库。方案组合热点 key 不设置过期时间由后台任务异步更新。互斥锁重建缓存时只允许一个线程去查询数据库其他线程等待。逻辑过期value 中保存逻辑过期时间读到时发现过期异步重建缓存先返回旧值。6.3 缓存雪崩大量 key 在同一时间过期或者 Redis 实例整体不可用导致请求全部打到数据库。方案组合key 过期时间加随机值避免同时失效。Redis 高可用部署避免单点故障。多级缓存本地缓存Caffeine Redis 组合。服务降级数据库压力大时直接返回兜底数据。这三个问题在面试中经常被要求“讲一个你在项目里实际遇到的案例”所以不只要背方案还要准备一个能讲清楚“为什么选这个方案、效果怎么样”的例子。7. 高频考点五缓存与数据库一致性7.1 Cache Aside Pattern最经典的模式是读先读缓存未命中则读数据库回填缓存。写先更新数据库再删除缓存。这里有一个高频追问“为什么先更新数据库再删缓存”原因是删除缓存是幂等操作即使删缓存失败下一次读也会因为缓存中没有数据而回源数据库数据不一致的时间窗口更小。7.2 延迟双删如果强一致要求更高可以用延迟双删先删缓存更新数据库隔一个短暂时间再次删除缓存。public void updateUser(User user) { String key user: user.getId(); redisTemplate.delete(key); userMapper.updateById(user); // 延迟 500ms 再删一次兜底并发读导致的脏缓存 executorService.schedule(() - redisTemplate.delete(key), 500, TimeUnit.MILLISECONDS); }需要明确告诉面试官延迟双删并不能做到绝对强一致只是把不一致窗口缩短如果业务对一致性要求极高可以考虑让读请求在写操作期间走数据库或引入 binlog 订阅异步淘汰缓存。7.3 监听 binlog 更新缓存更工程化的方案是使用 Canal 订阅 MySQL binlog当数据库数据变化时异步刷新 Redis 缓存。这样业务代码不需要在每次写操作后手动维护缓存逻辑缓存和数据库之间的同步交由增量日志驱动对业务的侵入性更小。面试中能提到这个方案说明你对一致性问题有系统性的思考。8. 高频考点六Redis 分布式锁分布式锁是 Java 面试里最容易被深挖的题目尤其是配合秒杀、任务调度场景。面试官可能会从“如何用 Redis 实现一个可用的分布式锁”一路追问到“这个锁有没有问题怎么改进”8.1 基础版set nx ex正确的加锁命令SET lock:order:10001 random_value NX PX 10000NXkey 不存在时才设置保证互斥PX设置过期时间避免死锁value 使用随机值释放锁时校验是“自己的锁”解锁不能用简单的del要配合 Lua 保证原子性if redis.call(get, KEYS[1]) ARGV[1] then return redis.call(del, KEYS[1]) else return 0 endJava 中通过DefaultRedisScriptLong执行这个 Lua。8.2 Redisson 方案生产上更推荐直接用 Redisson它封装了看门狗机制默认租约 30 秒业务没执行完会自动续期防止锁过期被其他线程获取。RLock lock redissonClient.getLock(lock:order:10001); boolean locked false; try { locked lock.tryLock(3, TimeUnit.SECONDS); if (locked) { // 执行秒杀扣减逻辑 } } finally { if (locked) { lock.unlock(); } }面试时可以这样总结手写SET NX EX Lua 是理解分布式锁原理的基础Redisson 解决了锁续期和自动释放的问题RedLock 在多节点场景下能降低主节点宕机造成的锁失效风险但也存在争议项目里一般不轻易使用。8.3 锁的粒度与性能锁的粒度比锁的实现方法更容易被忽略。如果所有订单都使用同一个锁 key并发能力会被严重削弱。正确做法是按业务维度拆分锁粒度例如lock:order:{orderId}、lock:user:{userId}把并发压力分散到不同的 key 上。9. 高频考点七Redis 集群与高可用9.1 主从复制主从复制解决的是“数据冗余”和“读写分离”问题主节点负责写从节点负责读全量同步使用 RDB增量同步使用积压缓冲区从节点同步时replicaof配置replicaof 192.168.1.100 6379主从延迟问题是面试高频点默认网络下复制延迟通常在毫秒级但网络异常时可能读到旧数据。如果业务不能接受读写延迟读操作也要走主节点或者使用强一致组件。9.2 哨兵模式哨兵解决的是“主节点挂了怎么办”的问题监控、自动故障转移、通知客户端新的主节点地址。部署上至少需要三个哨兵实例避免哨兵自身单点。客户端通过哨兵发现主从节点地址主节点故障时自动切换。9.3 Cluster 集群模式Redis Cluster 使用 16384 个哈希槽通过CRC16(key) % 16384决定 key 落在哪个槽。三主三从是常见部署方式。redis-cli --cluster create 192.168.1.1:6379 192.168.1.2:6379 192.168.1.3:6379 \ 192.168.1.4:6379 192.168.1.5:6379 192.168.1.6:6379 \ --cluster-replicas 1Cluster 里的重点问题客户端需要处理MOVED重定向或使用集群版客户端自动路由不支持跨 slot 的多 key 操作批量操作mset如果 key 不在同一个 slot 会报错需要用 hash tag 解决分片和主从切换是 Cluster 的两个核心能力9.4 脑裂问题主节点网络异常后哨兵选出新主节点旧主节点恢复了但旧主节点上可能还有客户端继续写入造成数据丢失。常见解决方式设置min-replicas-to-write和min-replicas-max-lag限制主节点在从节点数量不足时停止写入。配合 AOFeverysec把丢失窗口降到最低。10. 高频考点八性能相关命令与排查面试环节如果前面答得顺利面试官往往会追加一个生产问题“线上 Redis 突然变慢了你怎么排查”思考路径可以参考下面的顺序redis-cli --latency -h 127.0.0.1 -p 6379确认延迟曲线。SLOWLOG GET 20查看慢查询记录。INFO COMMANDSTATS查看哪些命令耗时高。检查是否出现 big keyredis-cli --bigkeys扫描大 key。INFO MEMORY查看内存使用率确认是否触发淘汰。MONITOR观察瞬时命令线上慎用会放大性能损耗。常见风险点使用KEYS *全量扫描阻塞主线程单个 key 存储的 value 过大读写和网络传输都会拖慢热点 key 集中在同一个实例导致负载不均频繁EXPIRE同样时间戳的 key 造成雪崩回答这类问题时重点是展示“先定位再优化最后验证”的工程思路而不是只背结论。11. 三道典型面试连环问11.1 第一套String 类型排查面试官你们项目里怎么用 Redis 存用户信息候选人用户基本信息用 String 存 JSON登录状态用 String 存 token 并设置过期时间。追问用户信息字段经常改动这时候 String 有什么缺点候选人每次变更都需要重新序列化整个对象字段多时浪费流量和内存。更合理的是用 Hash 存储字段hset单独更新某个字段。追问如果用户信息很热你怎么保证缓存不穿候选人热点 key 不设置过期由后台任务定时刷新再加本地缓存兜底。11.2 第二套分布式锁实战面试官说一下你对 Redis 分布式锁的理解。候选人先用SET NX EX保证互斥和过期value 用随机值释放时通过 Lua 比较再删。追问如果锁过期了业务还没执行完怎么办候选人用 Redisson 的看门狗自动续期。追问加了锁就一定安全吗候选人锁只能解决互斥不能解决幂等。极端情况下锁过期或主节点切换仍然可能并发执行所以核心扣减操作还要配合数据库唯一约束或乐观锁兜底。11.3 第三套缓存一致性面试官你们的商品详情是怎么保证缓存和数据库一致的候选人Cache Aside Pattern先更新数据库再删缓存读时未命中回源数据库。追问删缓存失败怎么办候选人设置短过期时间兜底同时引入延迟双删或者通过 binlog 订阅异步删除。追问如果商品价格变更用户读到旧价格怎么办候选人价格这类强一致数据可以不做缓存直接查库缓存只放不敏感信息比如商品标题和描述。12. 3 天复习路线安排Day 1基础与同步上午数据类型及底层结构、过期删除策略、内存淘汰策略下午RDB、AOF、混合持久化晚上本地起一个 Redis把set、hash、zset、slowlog、info命令全部敲一遍Day 2缓存设计上午穿透、击穿、雪崩的成因与方案下午缓存一致性、延迟双删、binlog 订阅晚上画一张缓存架构图把请求路径、回源路径、异步刷新路径标注清楚Day 3分布式与集群上午分布式锁手写版Redisson 使用下午主从、哨兵、Cluster 的原理与配置晚上模拟一张 Redis 故障场景表写出排查命令和每一步的解决动作这个安排的核心逻辑是第一天解决“Redis 本身是什么”第二天解决“Redis 在项目里怎么用”第三天解决“Redis 分布式下怎么保障”。面试时基本上就是围绕这三层提问。12.1 复习提纲速记五种数据类型的使用场景和底层结构RDB 和 AOF 的取舍惰性删除 定期删除组合allkeys-lru 与 volatile-lru 的区别缓存穿透、击穿、雪崩三套路Cache Aside 延迟双删 binlog 订阅SET NX EX Lua 解锁 Redisson 续期主从同步、哨兵故障转移、Cluster 槽位计算SLOWLOG GET、redis-cli --bigkeys等排查命令热点 key、big key、慢查询、连接数等生产隐患13. 常见问题与排查方法问题现象可能原因排查命令 / 步骤解决方案redis-cli ping卡住端口不通或服务未启动检查进程ps -ef grep redis启动 Redis 或检查防火墙启动报bind: Address already in use端口被占用lsof -i:6379更换端口或释放旧进程内存不足导致 OOMmaxmemory配置过高或物理内存不足INFO MEMORY查看 used_memory调低maxmemory检查大 key写入报OOM command not allowed when used memory达到内存上限且不允许淘汰查看maxmemory-policy改为allkeys-lru或扩容KEYS *执行后 Redis 阻塞全量扫描耗时过长使用SCAN代替分批遍历避免阻塞主线程从节点数据延迟较大网络延迟或同步压力大INFO REPLICATION查看 lag优化网络调整同步配置锁过期但业务未执行完默认过期时间设置过短检查锁续期机制使用 Redisson 看门狗手动续期缓存雪崩大量 key 同时过期检查过期时间分布过期时间加随机值API 调用超时连接池耗尽或 Redis 慢查询查看INFO CLIENTS、SLOWLOG调整连接池参数优化慢命令14. 最佳实践与复习建议不管面试时间多紧都要亲手敲一遍 Redis 命令。命令行敲过一遍和只看文章记忆深度完全不同。准备一个自己项目中的 Redis 使用案例不需要复杂关键是要能说清楚为什么要用 Redis、不用会怎样、出现问题时怎么排查。所有的“套路”都要准备一个反面案例。比如延迟双删如果第二次删除失败会带来什么后果。面对“你还有什么要问的”环节准备几个有质量的问题比如“你们项目 Redis 使用的是什么部署架构缓存和数据库一致性是怎么保障的”这类问题可以展示你的技术深度。面试题背熟只是基础关键是能把 Redis 放到实际的链路里讲清楚。时间有限时优先看这里数据类型、缓存穿透/击穿/雪崩、分布式锁、主从同步与 Cluster 分片、缓存一致性。其他内容可以放在这五块之后复习。Redis 并不难难的是把每个知识点串成一个完整的问题排查链路。3 天时间里每天按模块推进面试时遇到 Redis 相关的问题就不容易慌了。