Redis 知识复盘 · 分布式锁与并发写至继续学习
先按业务选择数据结构,再理解内存、持久化与复制,最后处理事务、锁和缓存异常。每节集中回答一类问题,避免把同一概念拆成多组问答。
分布式锁与并发写
先判断是否真的需要跨请求锁:计数优先用 INCR 等原子命令,条件更新可用 WATCH 或脚本。需要锁时,获取与过期时间应在同一条 SET key token NX PX ... 中设置。
- token 应能标识本次持有者;释放时原子比较 token 再删除,不能直接
DEL其他持有者的锁。 - 业务可能执行超过租约;要考虑续租、暂停、超时与进程崩溃。锁过期不代表旧持有者已停止访问外部资源。
- 保护数据库或其他系统时,还要考虑 fencing token、幂等或版本校验等资源端保护。
- Redlock 有运行与时序假设,不能当作不加条件的“官方保证安全”。选型应以业务容错要求为依据。
具体读写流程与释放脚本见 缓存与锁实践。
缓存读写与异常处理
先定义数据一致性要求
常见旁路缓存流程是读缓存,未命中再读数据库并回填;写入时先更新数据库,再删除相关缓存。数据库成功、删缓存失败时需重试或补偿;并发回填也可能产生短暂旧值,TTL 只是限制旧值存活时间,不是严格一致性证明。
必须强一致的判断应回到权威数据源或采用适合该业务的协调方案,不能仅靠两个系统连续写入保证原子性。
穿透、击穿与雪崩不要混淆
| 问题 | 典型触发 | 应对 |
|---|---|---|
| 穿透 | 查询不存在的数据 | 输入校验、短期空值缓存、布隆过滤器 |
| 击穿 | 一个热点键失效,大量请求同时回源 | 同键请求合并、受控重建、允许时逻辑过期 |
| 雪崩 | 大片键同时失效或缓存整体故障 | TTL 分散、限流、预热、熔断与有边界的降级 |
布隆过滤器判断“不存在”可以排除数据;判断“可能存在”仍需继续查,不能反向理解。通常不直接支持删除,更新数据时也要维护过滤器。
预热只加载有预期访问的数据,逐批限制并发;热点重建失败要有超时和兜底,不能无限排队。缓存故障时也不能让所有请求无限回源;哪些场景允许旧值或默认值,应由业务定义,结算等关键行为不能用静默成功替代。
队列、客户端与复习检查
消息与延迟任务
- List 可配合阻塞弹出减少空轮询,但弹出后消费者崩溃时如何恢复需要单独设计。
- Pub/Sub 面向在线订阅者,不提供离线积压与消费确认。
- Sorted Set 可把到期时间作为 score;多个消费者竞争时,取出和移除需要原子性,并考虑执行失败重试与重复投递。
- 需要持久消息、消费组或重放时比较 Stream 与专用消息系统,不只比较命令是否能收发。
客户端选择与复习验收
Jedis、Lettuce、Redisson 的抽象层次与功能不同,按维护版本、连接模型、Cluster 支持及实际 API 选择,不沿用过时的“官方只推荐某一个”或“某客户端不支持字符串”等绝对结论。
用自己的场景回答以下问题,而不是背诵固定机器数或 QPS:
- 哪些键可以过期或淘汰?内存不足时写失败如何处理?
- 主库故障后允许丢多少更新?备份最近一次恢复是否成功?
- 一次事务内部分命令运行失败,会留下什么状态?
- 同一热点键失效时,最大有多少请求能回源?
- 分片后有关联的多键操作如何保持同槽或改造?
继续学习
继续阅读
- 数据与原子性
- 数据与原子性
- 完整实践