5.1 KiB
id, title, type, domain, stack, tags, level, related, week
| id | title | type | domain | stack | tags | level | related | week | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| backend.redis.interview | Redis 面试题 | interview | backend |
|
|
intermediate |
|
|
Redis 面试题
基础
【基础】Redis 为什么快?
参考答案:数据在内存里;核心命令执行是单线程的,没有锁竞争和线程切换;使用 IO 多路复用(epoll)同时处理大量连接;数据结构针对场景做了优化(如压缩列表、跳表)。Redis 6 起网络读写可以多线程,命令执行仍是单线程。
【基础】Redis 有哪些数据类型?各举一个使用场景。
参考答案:String(缓存、计数器、验证码)、Hash(对象、购物车)、List(最新消息列表)、Set(标签、去重、共同关注)、ZSet(排行榜、延迟队列)、Stream(轻量消息队列);另有 Bitmap(签到)、HyperLogLog(UV 统计)、Geo(附近的人)。
【基础】过期的 key 是怎么删除的?内存满了怎么办?
参考答案:惰性删除(访问时发现过期就删)+ 定期删除(周期性抽样检查过期 key)。内存达到 maxmemory 时按淘汰策略处理:noeviction(拒绝写入)、allkeys-lru、allkeys-lfu、volatile-lru(只淘汰设置了过期的 key)等,缓存场景常用 allkeys-lru / allkeys-lfu。
【基础】RDB 和 AOF 的区别?
参考答案:RDB 定时生成内存快照,文件小、恢复快,但可能丢失最后一次快照之后的数据;AOF 追加记录写命令,可配置每秒刷盘,丢数据更少,但文件更大,需要重写压缩。生产常两者都开,Redis 4 起支持混合持久化。
进阶
【进阶】缓存穿透、击穿、雪崩分别是什么?怎么解决?
参考答案:穿透是查询不存在的数据,每次都打到数据库——缓存空值、参数校验、布隆过滤器。击穿是热点 key 过期瞬间大量请求同时回源——互斥锁 / singleflight 只让一个请求回源,或逻辑过期后台刷新。雪崩是大量 key 同时过期或 Redis 不可用——过期时间加随机值、Redis 高可用、服务限流降级。
【进阶】怎么保证缓存和数据库的一致性?
参考答案:常用旁路缓存:先更新数据库,再删除缓存。删除而不是更新,是为了避免并发写导致缓存写入旧值。仍有极小概率不一致,可以用延迟双删、订阅 binlog 异步删除、短 TTL 兜底。缓存只能做到最终一致,要求强一致的数据(余额、库存最终值)以数据库为准。
追问:为什么不先删缓存再更新数据库?→ 删除后、更新前的读请求会把旧值写回缓存,不一致窗口更大。
【进阶】Redis 分布式锁怎么实现?有什么问题?
参考答案:SET key 随机令牌 NX PX 过期时间 加锁;用 Lua 脚本比较令牌后删除来解锁,防止误删别人的锁。问题:业务执行时间超过过期时间会导致两个持有者同时存在(续期 / 看门狗);主从异步复制,主节点宕机时锁可能丢失(Redlock 有争议);所以关键业务还要用数据库唯一约束、乐观锁等做最终保证。
【进阶】Redis 的主从、哨兵、集群分别解决什么问题?
参考答案:主从复制解决读扩展和数据冗余;哨兵(Sentinel)监控主节点,故障时自动选新主,解决高可用;Cluster 把数据按 16384 个槽分到多个主节点,解决容量和写扩展,每个主节点也可以有从节点。Cluster 下多 key 操作(包括 Lua)要求 key 在同一个槽,可以用哈希标签 {}。
场景题
【场景题】秒杀场景怎么防止超卖和重复购买?
参考答案:库存提前加载到 Redis;Lua 脚本原子完成“是否已购买 → 库存是否充足 → 扣减 → 记录用户”;成功后发 MQ 异步创建订单,数据库唯一约束兜底;失败或超时未支付回补库存;前端、网关层层限流。详见库存预扣场景。
【场景题】线上 Redis 突然变慢,怎么排查?
参考答案:SLOWLOG GET 看慢命令(KEYS *、大 key 的 HGETALL / DEL、复杂 Lua);INFO 看内存、连接数、命中率、是否在做 RDB / AOF 重写(fork 导致的卡顿);--bigkeys / MEMORY USAGE 找大 key;检查是否有热点 key 集中在一个节点。处理:改用 SCAN、UNLINK,拆分大 key,热点 key 加本地缓存。
【场景题】一个接口要按用户限流,每分钟最多 60 次,多实例部署,怎么做?
参考答案:用 Redis 共享计数。简单做法是固定窗口 INCR + 过期时间;要求精确时用 ZSET 滑动窗口(Lua 脚本里删除过期记录、计数、写入);允许突发用令牌桶。返回 429 并带上重试时间。要考虑 Redis 故障时的策略(放行还是拒绝)。详见分布式锁和限流。