跳到主要内容
约 5 分钟4 张卡

Redis

Redis 是以内存数据结构为核心的键值数据库。本文以 Redis 6、7 为基线,负责执行模型、事务和客户端调用。

1. 面试核心​

先记住这几条,再读正文
  • 低延迟机制。 Redis 通过内存访问、专用数据结构和事件循环降低命令延迟。卡 · 适用场景
  • 命令执行线程。 Redis 6、7 的主要命令路径串行执行,I/O 线程可分担网络工作。
  • 批处理与原子执行。 Pipeline 批量发送命令以减少往返,Lua 脚本在服务端原子执行。卡 · Pipeline 与 Lua
  • 事务错误。 EXEC 执行阶段的命令错误只影响该命令,其他命令继续执行。卡 · 原子命令与事务
  • 乐观并发控制。 WATCH 监视的键被修改时,EXEC 放弃执行整个事务队列。卡 · WATCH 与乐观并发控制

2. 适用场景​

Redis 提供直接操作数据结构的命令。递增、集合更新和队列操作可在服务端完成。

  • 缓存保存查询或计算结果,减少重复回源。
  • 计数与限流维护短期窗口状态。
  • 排行榜按分数保存成员顺序。
  • 会话与验证码保存有期限的状态。
  • Stream 保存带消费确认的消息记录。

复杂关联查询和外键约束更适合关系型数据库。选择存储还需比较数据规模、恢复目标和一致性要求。

3. 数据类型​

String、Hash、List、Set、ZSet 和 Stream 提供不同操作。选择规则与内部编码见 Redis 数据结构。

4. 低延迟的原因​

Redis 主要在内存中访问数据,省去常规查询的磁盘定位。专用数据结构缩短计数、成员查找和排名等操作路径。事件循环通过 I/O 多路复用处理许多连接。

Redis 6、7 的主要命令执行路径由主线程串行处理。多个命令无需同时争用同一数据结构的写锁。网络 I/O、异步释放和持久化还使用线程或子进程。

io-threads 可配置 I/O 线程数量。读取分担还由 io-threads-do-reads 控制。I/O 线程数增加后,主要命令仍串行执行。

KEYS 全量扫描、大集合操作和长脚本会拖慢其他请求。渐进遍历与对象大小控制见 SCAN 游标遍历。

5. 过期与淘汰​

TTL 控制键何时失效,具体规则见 Redis 过期。内存压力下的候选选择见 Redis 内存淘汰。

6. 原子命令与事务​

MULTI 将后续命令加入事务队列。EXEC 按序执行队列,执行期间其他客户端命令不会插入。DISCARD 放弃尚未执行的队列。

SET demo:number abc
MULTI
INCR demo:number
SET demo:flag done
EXEC
GET demo:flag

INCR 因内容无法转为整数而报错。SET 仍执行成功,最后 GET 返回 done。EXEC 返回数组,客户端应逐项检查结果。

入队阶段的错误有不同处理。例如参数数量错误会标记事务失败。Redis 6、7 的 EXEC 随后返回 EXECABORT,整队命令不执行。

Redis 事务与 Lua 都没有自动撤销已完成写入的机制。脚本应先校验输入,再执行写入,减少中途出错。

7. WATCH 与乐观并发控制​

WATCH 将键纳入乐观并发检查。应在读取前执行 WATCH,并在同一连接完成事务。

SET demo:balance 100
WATCH demo:balance
GET demo:balance
MULTI
SET demo:balance 90
EXEC

本例读取到 100,客户端计算扣减 10。期间键被其他客户端修改时,EXEC 返回空结果。事务队列整体放弃,客户端需重新读取并有限重试。

Redis 6.0.9 起,被监视键过期也会导致事务放弃。淘汰同样会触发冲突。EXEC、DISCARD 或 UNWATCH 会清除监视状态。连接复用时,应确保状态在归还前清理。

8. 客户端配置​

连接可由客户端复用,或通过连接池管理。应分别设置建连、命令与借用连接的超时。

Pipeline 一次发送多条命令,减少网络往返。批次过大时,待回复数据会占用更多服务端内存。客户端也需限制单批命令数和返回体积。

诊断延迟时,对照客户端耗时、SLOWLOG 与网络指标。SLOWLOG 记录命令执行时间,排除客户端通信等 I/O。慢日志很短时,网络和客户端排队仍能拉高总延迟。

9. 常见问题​

9.1 Redis 的存储边界​

存储选型还需判断查询能力、一致性和恢复目标。Redis 保存权威状态时,要配置持久化、复制与独立备份。可重建缓存与权威数据应分别规划恢复方式。

9.2 Pipeline 与 Lua​

10 · 面试题卡片​

本页题目与参考回答

10.1 Redis 为什么快,使用时有哪些边界​

考察重点

  • 内存访问、数据结构与命令执行模型。
  • 阻塞命令、大 key、网络和持久化成本。
  • 过期、淘汰、缓存一致性与数据边界。

相关内容:适用场景至客户端配置。

参考回答

Redis 主要通过内存访问、专用数据结构和事件循环降低延迟。

Redis 6、7 的主要命令路径串行执行,减少共享结构的锁竞争。I/O 线程与后台进程承担部分其他工作。

命令复杂度、对象大小、网络和持久化仍影响总延迟。长脚本和全量扫描会占用执行线程。诊断时对照客户端时间、SLOWLOG、内存和回源指标。

10.2 Redis 事务中一条命令报错,其他命令会执行或回滚吗?​

考察重点:入队错误、执行错误和结果数组。

相关内容:原子命令与事务。

参考回答

入队阶段错误会让 EXEC 放弃整个队列。

执行阶段某条命令报错时,其他命令继续执行。此前成功写入也保留结果。客户端应逐项检查 EXEC 返回数组,并设计业务恢复。

10.3 WATCH 怎样避免并发覆盖,键过期时会发生什么?​

考察重点:同连接监视、冲突放弃和版本边界。

相关内容:WATCH 与乐观并发控制。

参考回答

WATCH 在读取前监视键,EXEC 检查期间是否发生修改。

发生冲突时,整个队列放弃,客户端需重新读取。Redis 6.0.9 起,过期也会触发该检查失败。流程需在同一连接执行,并限制重试次数。

10.4 Pipeline、MULTI/EXEC 和 Lua 各提供什么保证?​

考察重点:网络批处理、顺序执行和服务端逻辑。

相关内容:Pipeline 与 Lua、原子命令与事务。

参考回答

Pipeline 减少往返,命令间允许其他请求插入。

MULTI/EXEC 将队列作为一段连续命令执行。Lua 还支持在服务端读取后进行条件判断。后两者均需处理运行错误,已完成写入不会自动撤销。

11. 参考资料​