Skip to content
Redis 基础模型与高频场景 · 第 1 篇 / 共 4 篇
领域数据与中间件
专题Redis 专题
当前序列Redis 基础模型与高频场景
阅读位置第 1 篇 / 共 4 篇当前专题第 1 个序列 / 共 7 个序列

Redis 在后端项目里的高频场景:缓存、分布式锁、防重与会话共享

很多项目把 Redis 用上了,但真正出问题时,往往不是“不会连”,而是:

  • 不知道什么数据适不适合放 Redis
  • 不清楚缓存一致性边界
  • 低估了分布式锁的实现细节

Redis 很强,但它不是数据库替代品,也不是所有一致性问题的万能解法。

先说结论

在后端项目里,Redis 最常见的价值主要有四类:

  • 做缓存
  • 做分布式锁
  • 做防重和令牌校验
  • 做会话或短期状态共享

真正把 Redis 用稳,关键不是记更多命令,而是把一致性边界和失效策略想清楚。

一、先分清本地缓存和分布式缓存

这一点看起来基础,但非常重要。

1. 本地缓存

缓存只存在当前服务实例内,例如:

  • Caffeine
  • Guava Cache

优点:

  • 访问极快
  • 没有网络开销

缺点:

  • 多实例之间不共享
  • 数据一致性更难控制

2. 分布式缓存

缓存放在 Redis 这类独立中间件里,多个服务实例共享同一份数据。

优点:

  • 多实例可共享
  • 更适合分布式部署

缺点:

  • 有网络开销
  • 需要额外考虑热点、过期、淘汰和故障恢复

二、场景一:缓存

这是 Redis 最常见的用法。

适合放到 Redis 的数据通常具备这些特点:

  • 读多写少
  • 查询代价相对高
  • 可以接受短暂不一致

例如:

  • 商品详情
  • 配置项
  • 热门列表
  • 统计结果

缓存三类高频问题

1. 缓存穿透

查一个本来就不存在的数据,大量请求都打到数据库。

常见思路:

  • 缓存空值并设置较短过期时间
  • 布隆过滤器
  • 接口层防刷

2. 缓存击穿

某个热点 Key 失效瞬间,大量请求同时回源数据库。

常见思路:

  • 热点数据不过期
  • 加互斥锁
  • 预热缓存

3. 缓存雪崩

一批 Key 在同一时间大面积失效。

常见思路:

  • 过期时间加随机值
  • 热点数据错峰失效
  • 服务限流与降级
  • 做好缓存预热和主从高可用

三、缓存一致性怎么想更务实

很多人刚接触缓存时,容易把一致性要求想得过高。

但大部分缓存场景里,更现实的策略通常是:

  • 写数据库
  • 删除缓存
  • 下一次读请求再回源重建缓存

这是最常见、也最容易落地的思路。

为什么不推荐把缓存一致性设计得太复杂

因为很多业务数据本来就允许短暂不一致,例如:

  • 商品介绍
  • 菜单配置
  • 展示类列表

如果为了这类数据追求强一致,系统复杂度会很快上涨。

更实用的原则

  • 对一致性要求极高的数据,优先查数据库
  • 对允许短暂脏读的数据,缓存加过期时间通常已经够用
  • 对热点写场景,再考虑延迟双删、订阅 binlog 或加读写锁

也就是说,不是缓存做不到强一致,而是很多时候没必要为此付出过高复杂度。

四、场景二:分布式锁

当服务已经是多实例部署时,本地锁只能锁住单个进程。

这时才会考虑 Redis 分布式锁。

最经典的思路是:

text
SET key value NX EX seconds

重点不在“能不能加锁”,而在这些边界:

  • 进程挂了怎么办
  • 锁到期了但业务没执行完怎么办
  • 删除锁时怎么保证删的是自己的锁

更稳妥的几个原则

  • 锁一定要有过期时间
  • value 里要带唯一标识
  • 判断和删除要保证原子性
  • 业务执行时间可能很长时,要考虑续期机制

为什么删除锁要原子

如果你先判断 value,再单独执行删除,中间可能发生:

  • 锁过期
  • 别的线程拿到新锁

这时你删掉的就不是自己的锁了。

所以更稳妥的方式通常是:

  • 用 Lua 脚本把“判断 + 删除”放到一个原子操作里

Redisson 为什么常被推荐

因为它帮你把很多容易漏掉的细节封装掉了,例如:

  • 可重入锁
  • 看门狗续期
  • 更完整的锁模型

看门狗续期可以怎么理解

如果锁默认只给一个固定过期时间,业务执行过长时就会出现:

  • 锁提前过期
  • 别的线程拿到锁
  • 当前线程执行完又去删掉别人的锁

Redisson 的看门狗机制,本质上就是:

  • 在业务线程还活着时,周期性给锁续命

它解决的不是所有一致性问题,而是“锁持有时间不可预估”这个很常见的工程问题。

五、场景三:防重和令牌校验

这类场景也很常见,例如:

  • 表单重复提交
  • 订单防重
  • 短时间重复请求拦截

常见做法:

  • 为请求生成唯一 token
  • token 放入 Redis
  • 校验成功后立即删除

这里的关键点同样是:

  • 校验和删除尽量保证原子性

否则高并发下依然可能重复消费。

六、场景四:会话共享和短期状态

例如:

  • 登录态共享
  • 短信验证码
  • 临时业务上下文
  • 分布式限流计数

这类数据通常具备:

  • 生命周期短
  • 需要跨服务共享

Redis 非常适合承载这类状态。

七、Redis 很快,但不是强一致协调器

这点很重要。

Redis 更偏高性能、可接受一定最终一致性的场景。

如果你面对的是:

  • 强一致协调
  • 严格主从切换语义
  • 更重的分布式一致性约束

那就不能只看“Redis 很快”,还要考虑 ZooKeeper 这类更偏协调器定位的组件。

八、几个容易踩的坑

1. 把缓存一致性要求想得过高

很多缓存场景允许短暂脏数据,这是正常的工程取舍。

2. 直接自己手写一版分布式锁就上线

最简单的 setnx 只是起点,不是完整方案。

3. Redis 里无限堆数据

没有过期策略、没有容量预估、没有热点治理,最终都会演变成内存问题。

4. 用 Redis 承担它本来不擅长的职责

它适合做高性能共享状态,不适合替代数据库承载完整业务语义。

一句话总结

Redis 最适合做的是“高性能的临时共享状态和缓存层”,而不是替代数据库去承接所有业务语义。

真正把它用好,关键不是多记命令,而是搞清楚每种用法的一致性边界、锁语义和失效策略。

延伸阅读相关文章优先当前专题,再补跨专题关联。
同一序列 · 顺着当前主线继续读Redis 数据结构怎么选适合把数据结构、典型场景、布隆过滤器和集群分片放在一起先打底。Redis 专题 · Redis 基础模型与高频场景同一序列 · 顺着当前主线继续读Redis 布隆过滤器怎么用适合把数据结构、典型场景、布隆过滤器和集群分片放在一起先打底。Redis 专题 · Redis 基础模型与高频场景同专题其他序列 · Redis 高可用、过期与性能治理过期键删除策略为什么会影响 RT适合把复制、故障切换、槽迁移、内存碎片和冷启动预热放在一条 Redis 稳定性主线上看。Redis 专题 · Redis 高可用、过期与性能治理同专题其他序列 · Redis 可用性与热点治理细节缓存穿透治理怎么做更稳适合把 Sentinel、穿透防护、延迟队列和地理位置搜索放在一起看。Redis 专题 · Redis 可用性与热点治理细节跨专题关联 · 同场景:基础学习@Conditional 系列注解怎么配合使用适合把自动装配、条件装配、Profile 和循环依赖放回 Spring Boot 启动过程里理解。Spring 专题 · Spring Boot 启动、装配与配置跨专题关联 · 同场景:基础学习保留策略和日志压缩适合哪些场景适合把副本机制、acks、批量压缩和日志组织放在一条 Kafka 投递主线上理解。Kafka 专题 · Kafka 投递链路与日志存储机制
继续阅读Redis 基础模型与高频场景当前序列第 1 篇 / 共 4 篇当前专题第 1 个序列 / 共 7 个序列
往前看
上一序列MySQL 事务、锁与高可用从第 1 篇开始:MySQL 事务与锁
往后看
下一篇Redis 数据结构怎么选继续当前序列下一章下一序列Redis 缓存一致性与更新策略从第 1 篇开始:Redis 缓存更新策略

把零散经验整理成可查、可复用、可持续更新的企业级知识门户