
准备Redis缓存相关的面试最怕的不是题目多而是背了一堆答案结果被面试官一个问题问穿。这份Redis缓存面试题50道是我前后花了两周整理出来的从真实面试记录和社区高频题里筛掉了大量重复考法最终按底层逻辑归纳成六大板块穿透/击穿/雪崩、数据一致性、分布式锁、内存淘汰与持久化、集群高可用、回答框架。很多候选人能把缓存空值布隆过滤器延迟双删这些词挂在嘴边但被追问一句你这方案在极端场景下会怎样就卡壳了。这篇文章不打算把50道题一条条列出来堆答案而是带你把它当成一张知识地图来走每类题都梳理清楚面试官考察的本质、可复用的回答套路以及我在线上实战中踩过的那些坑。适合正在准备后端面试的开发者也适合刚接手缓存系统、想系统建立Redis全局认知的运维和架构同学。1. 缓存三兄弟的底层差异穿透、击穿、雪崩对应的第2、7、13、22、31、40题这道题组是Redis缓存面试的必考开场原题集合里至少有6道直接问三兄弟的区别和解决方案。我梳理过不少候选人发现大部分人能各自说出定义但把场景一换就分不清了。面试官要的不是三个名词而是你对缓存故障模型的理解。1.1 一个类比分清三兄弟我通常喜欢用实体店做类比。缓存穿透是有人反复去一家根本不存在的店每次都敲门询问你还得专门跑去仓库确认没货对应到系统里就是大量请求查询一个数据库里也没有的key缓存永远miss请求直接打到数据库。缓存击穿是某家网红店门口排了长队忽然招牌挂了热点key过期一瞬间所有人都涌去仓库问对应到系统里就是某个热点key在缓存失效的瞬间大量并发同时去查数据库。缓存雪崩是所有店家同时关门或者整个商场停电对应到系统里要么是大量key在同一时间过期要么是Redis直接宕机数据库瞬间被海量请求淹没。这三兄弟共同点都是缓存没能挡住请求但根因差异很大穿透是数据不存在击穿是单点热点失效雪崩是批量失效或全局故障。面试时如果你能把这个分层说清楚就已经超过一半的候选人了。1.2 穿透的最优解不是缓存空值缓存穿透最常见的解法有两个缓存空值和布隆过滤器。很多人开口就是设置短TTL空值这是可行的但要小心两个问题一是空值也会占用Redis内存如果攻击者伪造大量不存在的key空值会越积越多二是空值缓存期间真实数据如果被创建了业务上有可能会读到旧值形成短暂不一致。布隆过滤器的思路是把可能存在的key提前映射到一个大型位数组中查询key时用多个哈希函数判断是否在位。不存在的判断是绝对准确的但存在是有误判率的而且标准的布隆过滤器不支持删除元素。如果你在面试里能主动补一句如果要支持删除可以用Counting Bloom Filter或者退回到缓存空值短TTL的方案面试官一般会眼前一亮。那什么时候该用哪个我给自己定的经验法则是请求量不大业务上不存在数据也有限缓存空值就够数据量上百万且攻击风险高的场景上布隆过滤器。另外布隆过滤器本身也要考虑怎么维护你不可能每次新增一个key都全量重建所以常见做法是用Redis bitmap自己实现一个配合定期的重建任务。1.3 击穿与雪崩的应对差异互斥锁、逻辑过期、随机TTL击穿的核心问题是单点热点key失效后的并发重建。我遇到的最常见答法是用互斥锁但很少有人讲清楚加锁粒度。比如某个热点商品详情key过期了100个请求同时进入真正查数据库的应该只有1个其他99个要么阻塞等待要么快速失败返回旧缓存。很多候选人只说加锁但用什么锁、锁多久、等待超时怎么处理一概不知道。互斥锁方案虽然朴素但确实有效尤其适合重建代价高、允许少量请求等待的场景。另一个方案是逻辑过期把过期时间作为一个字段和真实数据一起放进value读的时候发现逻辑过期先返回旧数据同时起一个异步线程去刷新缓存。这个方案不会阻塞请求但短时间会让用户读到旧数据适合读多写少、一致性要求不太苛刻的详情页场景。雪崩的应对要区分两种情况。第一种是大量key同时过期解法很直接过期时间加随机值比如TTL在基础值上加上一个0到300秒的随机数让失效时间错开。第二种是Redis节点宕机这已经不是加随机TTL能解决的了需要多级缓存比如本地缓存挡一层、接口限流降级、DB连接池保护以及Redis的主从哨兵或集群高可用。面试中我经常追问如果Redis彻底挂了你的系统还能不能撑住能答出应用本地缓存降级到DB前先限流的人不多。1.4 面试追问布隆过滤器误删怎么办这块属于加分项但也很容易暴露深度。比如面试官追问布隆过滤器判断key存在又去DB查结果没有怎么办这不是布隆过滤器的问题是误判率的设计问题通常把误判率控制在1%左右就够了不会产生灾难性影响。如果你用了可删除的Counting Bloom Filter还要额外考虑计数器减到0时如果还有其他key共享bit位会导致误删。所以实践中我发现绝大多数业务场景不需要支持删除缓存空值方案配合短TTL反而更稳。另一个追问点是互斥锁方案会不会把请求堆死。如果锁等待时间设置过长1000个请求在锁上排队表现反而是接口RT飙升。我会在锁等待上设置一个合理的超时时间超时就返回缓存中的旧值或直接快速失败绝不能把线程池拖垮。能用一句我宁可让少量请求失败也不让整个服务雪崩来收尾这句很提分。2. 数据一致性题组为什么先删缓存再更新数据库总被面试官挑刺这一类题在原题集中大约对应第16到22题。很多候选人会背先删缓存再更新DB这个结论但说不清反例。面试官真正想听的是你能不能在分布式读写并发情景下分析缓存与数据库一致性的边界。2.1 典型读改写时序里藏着两个坑先看一个最常见的错误考法。线程A写数据先更新了数据库再删除缓存线程B读数据缓存miss后去数据库读到了旧值然后回填缓存。如果这两个操作发生交错就会出现数据库已经新了缓存里还是旧值的情况。所以经典Cache Aside模式里写操作是先删缓存再更新数据库这样读请求在缓存miss后去数据库读到的如果是旧值回填缓存后也不会破坏一致性吗不一定。反例是这样的线程A先删缓存线程B读miss去DB查到了旧值正准备回填缓存此时线程A更新DB成功。线程B回填了旧值。数据库和缓存又不一致了。这就是面试官爱说的删缓存和更新DB之间有一个时间窗口旧数据可能回填到缓存。所以有人提出延迟双删先删缓存、更新DB、隔几百毫秒再删一次缓存把窗口期间可能被回填的旧值清掉。2.2 延迟双删、binlog订阅、事务消息怎么选延迟双删最大的问题是延迟时间怎么定。如果主从复制延迟很大500毫秒不够就需要1秒甚至更长但如果碰到刚好长时间的主从延迟第二次删除还是会晚。这里我建议不要死守着sleep等待的方案更好的办法是把删缓存作为一个可靠事件异步执行。目前生产环境中比较成熟的组合是把更新DB和删缓存解耦。比如订阅MySQL的binlog利用Canal这类中间件把变更事件解析出来再异步删除对应的缓存。这样主业务只需要保证DB更新成功缓存任务由旁路补齐还能重试。另一条路是用事务消息让写请求先发一条待删除缓存的消息等DB提交成功后把消息转成可投递消费者收到后再删缓存。事务消息成本略高但能保证不丢事件。这些方案的本质都一样不去追求读和写在毫秒级强一致而是让缓存最终收敛到和DB一致。TTL是兜底中的兜底异步删除失败后最多等到key过期缓存也会自动重建。2.3 CAP框架下最终一致才是更务实的选项面试官喜欢问能不能做到缓存和数据库强一致。我的经验是如果强一致是刚需那就不该用缓存或者缓存只做local reference用。分布式环境下跨存储做强一致需要引入分布式事务或分布式锁复杂度成倍上升性能也会明显下降。绝大多数业务场景里缓存本来就是读多写少、可以忍受极短时间数据滞后的。回答这类题时我通常会先明确我的目标是最终一致并给出收敛时间预算。比如这个数据最多允许5秒的最终一致延迟我会用binlog异步删缓存TTL 60秒兜底。有数字、有方案比空谈CAP好得多。这里还可以再补一句缓存删除本身就是个幂等操作删了不存在的key也没关系所以异步删除方案天然可靠。3. 分布式锁题组setnx、过期时间、Lua脚本和Redlock的取舍分布式锁题目几乎每场面试都会出现原题第23到30题基本绕不开。它不是独立的考点而是和缓存击穿、超卖控制紧密相关。面试官想考察你对Redis命令原子性和异常场景的敏感度。3.1 加锁为什么要setnx加过期时间放在一条命令里最基础的版本是SET lock_key value NX EX 30一条命令完成。NX保证只有key不存在时才能设置成功EX设置了锁的自动过期时间。如果把加锁和设置过期时间拆成两条命令隐患在于第一条setnx成功进程突然崩溃还没有执行expire锁永远不会释放后面所有线程都进不来。这个场景我见过不止一次简单得让人措手不及。另外value是什么也很有讲究。我建议用业务请求的唯一标识比如UUID而不是固定字符串。这个value会在释放锁时用来确认锁是不是我的。不设唯一标识的锁就像钥匙上不写房间号谁拿都能开成一房多客。3.2 释放锁的Lua脚本误删别人锁的问题锁过期之后会怎么样A线程持有锁期间业务执行太久锁30秒自动到期此时B线程加锁成功。等A线程执行完如果直接执行DEL就会把B的锁删除导致B还在执行任务时锁已经不存在另一个线程C又能加锁进来。这就是经典误删。正确做法是先对比value再删除。但要注意get判断和del删除必须是一个原子操作所以得用Lua脚本if redis.call(get, KEYS[1]) ARGV[1] then return redis.call(del, KEYS[1]) else return 0 end我在面试中会特意追问候选人判断和删除分开写行不行如果他说行那说明对并发原子性还没形成肌肉记忆。这个Lua脚本虽然只有几行但它戳中Redis分布式锁核心判断程序的锁标识和释放锁必须原子否则又会回到误删别人的锁那一幕。3.3 面试官问Redlock时到底在问什么Redlock被问得也很多。它的思想是同时在多个Redis节点上申请锁大多数节点成功才算获锁。面试官问Redlock往往不是期待你去解决分布式系统的PHANTOM问题而是想看你是否理解单节点锁在故障切换时会失效吗主从切换时如果锁在旧主节点上还没同步到新主节点新主节点就可以被另一线程加锁导致两个线程同时持锁。注意这里我不建议无脑吹Redlock我认为大多数业务场景下单实例Redis配合合理的锁超时和业务幂等已经能满足需求。Redlock依赖多个独立Redis实例部署成本和运行复杂度都很高而且业界对它在时钟跳跃、网络分区、GC停顿下的安全性是有争议的。面试时你可以说我会先评估业务是否真的需要跨故障域的多节点锁单点加锁幂等保护通常更务实这比只背Redlock流程有力得多。4. 内存淘汰与持久化maxmemory、LRU近似与RDB/AOF的工程权衡这类题看着是配置参数其实考的是你对Redis作为缓存和作为存储的理解。原题第31到38题里我挑三个最容易踩坑的点。4.1 淘汰策略不是maxmemory-policy一念之间的事面试题里常问内存满了怎么办标准答案是Redis有8种淘汰策略。但很多人没有想过如果业务缓存key都没设置过期时间你配置volatile-lru是永远淘汰不了任何key的因为volatile开头的策略只淘汰带TTL的key。很多线上事故就是这么来的——想限制内存结果maxmemory到了以后所有写请求直接报错。我习惯的选型维度很简单如果Redis只做纯缓存会设置allkeys-lru或allkeys-lfu优先保留最近访问/高频访问的数据。如果Redis里还存了一些不能丢的业务数据那淘汰策略就要精细很多甚至建议给不同业务使用不同Redis实例。同时LFU并不一定永远优于LRU它的优势是能识别长期高频但最近偶发的热点适合电商大促这类有数据倾斜的场景。还有个容易被忽略的点maxmemory不是越大越好。本机内存要给操作系统留缓冲容器部署还要留意cgroup限制。如果你在Docker里把maxmemory设置得比cgroup限制还高当Redis内存增长被cgroup杀掉时日志都来不及看。4.2 RDB与AOF恢复速度、数据安全、性能三者怎么平衡RDB是二进制定时快照恢复快但如果宕机发生在两次快照之间这期间数据就全丢了。AOF是追加写命令数据丢失少但文件巨大、重放恢复慢。Redis 4.0之后的aof-use-rdb-preamble混合持久化方案则是AOF文件头部用RDB格式后段用增量命令兼顾恢复速度和数据安全。面试里一个高频追问是为什么AOF默认每秒刷盘而不是每条命令刷盘。如果每条写命令都fsync性能会掉得非常厉害每秒刷盘最多丢1秒数据对绝大多数业务是可接受的。我会补一句如果Redis只被当作缓存我反而会建议关掉持久化。因为缓存层的数据丢失可以由DB重建持久化带来的fork开销和磁盘IO反而影响性能。但如果Redis同时扛着分布式锁这类需要保证锁安全的数据就不能只图快关闭AOF。4.3 fork写时复制持久化期间的内存翻倍迷思很多人理解RDB持久化时会以为内存会翻倍其实没那么简单。RDB或AOF rewrite依赖fork创建一个子进程子进程开始时和父进程共享同一份内存页。只有当父进程收到写请求、修改了某个内存页时才会把该页复制一份这就是Copy-On-Write。所以写负载越低额外内存开销越小写负载很高时大量页面被复制内存确实可能飙升极端情况下接近翻倍。这个机制直接解释了为什么做持久化时高写入QPS下的Redis会偶发卡顿甚至被系统OOM Kill。我在压测里见过一次AOF rewrite期间实例内存从3G冲到近6G最后被内核杀掉。所以生产环境要提前评估如果写入量很大开启安全持久化时内存至少保留maxmemory一倍以上的余量或者在低峰期手动触发重写。5. 从单机缓存到集群缓存热点Key、分片slot与高可用集群题目不需要每个都背原理掌握热点发现、key设计、扩容动作这几个点面试已经能打出两板斧。原题第39到45题大多是现场设计题。5.1 热点Key与大Value50题里最容易实战翻车的两类我监考过不少系统最常见的翻车不是缓存穿透而是热点Key。某个key的访问量突然占到Redis整体流量的八成以上单实例的网卡先被打满紧接着Redis服务端CPU飙升。解决方案里本地缓存比如Caffeine是性价比最高的热点数据在应用内存里挡掉一大半请求另一个办法是把同一个key复制成多个key比如hot:1到hot:10读取时随机访问其中一个。不要只加一层Redis热点key这个问题Redis单节点本身就是瓶颈。面试里也经常问大Key。Redis中单个String超过512KB就算大value它会导致读取延迟高、删除阻塞主线程。曾经有人用DEL删除一个几十MB的keyRedis直接阻塞了几秒下游全超时。现在Redis 4.0有UNLINK命令可以异步删除。大Key更应该在源头解决拆成多个hash字段、用压缩算法压缩或者提前按业务id拆分。关于热点如何发现我补充一个技巧如果确认线上Redis是4.0以上版本并且开启了LFU淘汰策略可以用redis-cli --hotkeys扫描热点如果不想改配置就在客户端做请求统计按key维度聚合Redis命令调用次数。5.2 缓存key设计与过期策略的治理面试题问你平时是怎么设计缓存key的我建议不要只答加项目前缀而要给一套完整思路。key命名的第一原则是能快速定位业务归属和查询维度比如order:detail:userId:orderId。冒号隔开的格式在Redis里可读性好而且可以用scan按前缀批量处理。第二原则是控制key粒度同一份业务数据不要衍生出一堆key来否则做缓存更新时容易漏。TTL策略更要按业务语义设计。缓存访问越频繁、数据变化越慢TTL可以越长但如果你同时担心缓存穿透空值缓存建议也给一个短TTL比如30秒。批量key的TTL不要设成同一个值除非你希望它们同时过期然后一起打到DB。我在线上做过最蠢的事就是给所有首页推荐位key都设了10分钟过期结果整点一到首页接口集体降级。后来改成TTL加上随机抖动再也没有发生过批量过期。5.3 集群扩容时避免雪崩的常用姿势Redis Cluster的key路由依赖CRC16哈希到16384个slot。扩容时slot会在节点间迁移期间如果客户端没处理好可能遇到大量重定向错误。更危险的是迁移过程中某些slot短暂不可服务缓存命中率下降DB压力瞬间上去了。所以线上扩容必须在低峰期做并且要在迁移前预热目标节点上的key。除了Cluster还有一类用一致性哈希做分片的中间件比如Codis它减少迁移时需要移动的key范围破坏性更小。面试时我会讲清楚无论哪种分片扩容本质上都是腾挪数据都会造成一段窗口期的缓存命中率波动。处理好这个波动要靠客户端容错、本地缓存熔断和DB限流三重兜底而不是只指望Redis自己解决。主从高可用也是同一个逻辑主节点宕机后哨兵发起切换如果选出的从节点数据落后于旧主节点那么切换窗口期缓存可能是冷的业务缓存命中率会瞬间掉下来。所以从节点的数据同步状态监控比配置哨兵本身更重要。我一般会在从节点上开启min-replicas-to-write之类的保护防止主从断连期间主节点写入的数据在切换后全部丢失。6. 高效准备Redis缓存面试的答题框架和自测清单最后这部分相当于把50道题从知识点变成答题肌肉记忆。我发现很多候选人刷题刷得很散真正到面试时东一句西一句缺乏主线。如果你能把每类问题都挂到一个缓存请求生命周期上答题会顺很多。6.1 把知识点串成输入-存储-失效-兜底四条线我建议按一条读请求的路径来组织自己的话术请求进来先查缓存存储结构如果没命中就要查DB回填穿透风险如果命中的key是热点同时快要过期击穿风险如果一大批key同时过期或者Redis宕机雪崩风险。写入时改动数据库就需要处理缓存如何同步一致性。Redis自身还有容量限制所以要知道何时淘汰内存策略。为了保证数据不丢需要持久化方案RDB/AOF。为了防止多个业务并发操作同一个资源要用分布式锁。这样一套下来几乎能把50道题全部覆盖。给自测表格的时候我会在脑子里把题目按这个主线排队比如数据类型、序列化对应第1~6题穿透/击穿/雪崩对应第7~15题缓存一致性对应第16~22题分布式锁对应第23~30题内存淘汰与持久化对应第31~38题集群、热key、扩容高可用对应第39~45题混合场景设计题对应第46~50题。这样一来每个主题群背后都有一个核心问题而不是一个个孤立的知识点。6.2 一个合格回答的示范缓存击穿的全流程作答举个让我印象深刻的例子。有一次候选人被问缓存击穿如何解决他的回答是强制缓存永不过期或者加锁。我追问锁怎么加加完以后锁失效怎么办他就愣住了。而我认为一个好的答案应该像这样缓存击穿指热点key在过期瞬间大量请求同时穿透到DB。我会分两种场景处理如果系统能容忍少量请求等待就使用互斥锁用Redis的SET NX实现让第一个线程查DB并回填其他线程等待锁释放后重新读缓存如果系统不能容忍因为锁等待导致的RT抖动就使用逻辑过期方案缓存value里保存真实数据和过期时间读时发现过期先返回旧值同时丢一个异步任务去刷新缓存。两条方案各有代价互斥锁更实时但可能增加延迟逻辑过期性能更好但可能短暂读到旧值。我的最终选择要看业务对一致性和延迟的容忍度。这段话没有堆概念而是先定义问题再写两个方案然后主动给出选择依据。面试官接着问锁抢不到怎么办你就可以说设置合理的锁等待超时超时后返回旧值或走降级而不是无限阻塞。整个回答一环扣一环听下来就很有经验。6.3 50道题复习路径与自测表我平时复习Redis缓存面试题不会按题目顺序刷而是先按前面说的六个主题逐个攻破每个主题至少要能回答出三个为什么。比如背了布隆过滤器能防穿透就要能解释位数组、多个哈希函数、误判率的关系背了延迟双删就要能说清第二次删除要延迟多久、删多久合适背了多级缓存就得能说清本地缓存更新失败时如何兜底。给一个简单的自测清单你能不能在10分钟内不看资料把缓存穿透、击穿、雪崩完整地讲完吗能不能把分布式锁从加锁到释放的每一步异常场景都梳理一遍能不能画出RDB和AOF在故障恢复时的数据恢复流程如果都可以那你面对50道题的时候就不再是背题而是答题。我自己实际面试候选人的经验是能做到这个程度的人基本都能通过Redis缓存方向的考核剩下就是弹性、沟通能力和业务权衡能力了。