Redis 常见面试题

返回 面试

Redis:内存 KV,单线程执行命令(6.0+ IO 多线程),常用于缓存、锁、限流、排行榜。详解 Redis


基础

说明
单线程命令无锁竞争,CPU 不是瓶颈;慢的是 IO/大 key
6.0+网络 IO 多线程,命令仍单线程
持久化RDB 快照 + AOF 日志;生产 混合 aof-use-rdb-preamble
过期惰性删除 + 定期抽样;maxmemory-policy 淘汰

五大数据结构(场景)

类型底层/int典型场景
StringSDS缓存、计数、SET NX
Hash压缩列表/哈希表对象字段、购物车
Listquicklist队列、时间线
Setintset/哈希表去重、共同好友
ZSetskiplist + 哈希排行榜、延迟队列

扩展:BitmapHyperLogLogGEOStream(消费组,轻量 MQ)。


持久化 RDB vs AOF

RDBAOF
方式子进程快照追加写命令
恢复慢(可重写 shrink)
丢数据两次快照间everysec 最多 1s
生产混合持久化推荐appendfsync everysec

高可用

单机 → 主从复制 → Sentinel 故障转移 → Cluster 分片(16384 slot)
形态适用
主从 + Sentinel中小规模、自动 failover
Cluster大数据量水平扩展

脑裂:旧主仍可写导致双主;min-replicas-to-write 等缓解。


缓存三大问题

问题现象方案
穿透查不存在 key,打穿 DB布隆过滤器、空值短 TTL
击穿热点 key 过期瞬间并发回源互斥锁、逻辑过期、热点不过期
雪崩大量 key 同时过期 / Redis 宕机TTL 随机、集群、降级、预热

Cache Aside(旁路缓存)

读:Redis → miss → DB → 写 Redis
写:更新 DB → **删除** Redis(非双写)
说明
DB 成功、删缓存失败Binlog/Canal → MQ 重试删除 + TTL 兜底
慢读回填旧值版本号、热点互斥重建、CDC 再删
MySQL/Redis 副本延迟写后读主或等待复制位点;普通读接受最终一致

多级:Caffeine(本地)→ Redis → DB,本地需失效广播。

详见 缓存与一致性


分布式锁

SET lock:order:1001 <uuid> NX EX 30

value 必须是本次请求唯一 token。释放须原子比较所有权:Redis 8.4+ 可用 DELEX ... IFEQ token,旧版本用 Lua 比对 value 再 DEL

问题方案
业务未完成锁过期Redisson 看门狗续期
可重入Redisson RLock
GC 暂停后陈旧写fencing token,资源端拒绝旧 token
主从切换丢锁副本确认降低风险;WAIT 仍非强一致;Redlock 有边界
锁与 DB先持锁,再开事务,事务提交后解锁;最终靠唯一约束/状态机
锁与幂等锁只限制同时进入,不能阻止稍后重试;仍需 requestId 去重

分布式锁分布式锁


Redis 单线程为什么快

  1. 内存操作
  2. IO 多路复用(epoll)
  3. 数据结构高效
  4. 避免线程切换与锁

“单线程”只指核心命令执行,不代表进程只有一个线程:

执行单元职责
主线程事件循环、串行执行命令、修改键空间
Redis 6.0+ I/O threads并行 socket 读写;不并行执行普通命令
BIO threadsAOF fsync、异步 close、lazy free
RDB/AOF child process快照与重写,属于子进程而非线程池

客户端也要区分:Lettuce native connection 线程安全,普通命令通常可共享;Jedis 单连接不可跨线程共享,常用 JedisPool;Redisson 的 Netty threads、回调 threads、命令连接池和订阅池不是同一个配置。阻塞命令、事务和 Pub/Sub 应使用专用连接。

详见 架构与线程模型线程池与客户端连接


Redis vs Memcached

RedisMemcached
类型多数据结构仅 String
持久化RDB/AOF
集群Cluster客户端分片
线程单线程命令多线程

Redis 事务

MULTI / EXEC不支持回滚;命令排队一次执行;非 ACID 隔离(无隔离级别)。

Cluster 下多 key 事务须 同一 hash slot{tag} 哈希标签)。


常见面试题

Q:Redis 和 MySQL 怎么保证一致?
A:Cache Aside + 删缓存;接受最终一致;强一致用 Canal/MQ 刷缓存或读主。

Q:SET NX 和 Redlock?
A:单实例 SET NX EX + Lua 够用多数场景;Redlock 多主过半,理论有争议。

Q:热 key 怎么办?
A:本地缓存、多副本(写随机 suffix 读聚合)、拆分、限流。

Q:BigKey 危害?
A:阻塞单线程、慢查询、迁移失败;拆分、压缩、异步删 UNLINK

Q:Stream 和 List 做队列?
A:Stream 支持消费组、ACK、Pending;List 简单但无原生消费组。


相关笔记