如何解决Spring Boot中Redis并发下的缓存击穿问题_采用双重检查锁或Redisson分布式锁

星明酱_5630

星明酱_5630

2026-06-24

796人浏览

原创

缓存击穿需用分布式锁而非本地锁,因sync=true仅限单jvm;redisson双重检查方案最稳妥:锁内二次查缓存防穿透,锁key须与业务key分离且带标识,leasetime需大于查库+写缓存耗时并留余量。

如何解决spring boot中redis并发下的缓存击穿问题_采用双重检查锁或redisson分布式锁

缓存击穿在高并发场景下会直接压垮数据库,核心原因是热点 Key 过期瞬间多个请求同时穿透。用本地锁(synchronized)完全无效,必须用分布式锁;而「双重检查 + Redisson」是目前最稳妥、开箱即用的组合方案。

为什么 @Cacheable(sync = true) 不足以解决缓存击穿

Spring Cache 的 sync = true 确实会在缓存未命中时加本地锁,但它只在单 JVM 进程内生效。在多实例部署(如 Kubernetes 多 Pod、Tomcat 集群)下,每个节点都各自加自己的锁,根本无法互斥 —— 依然会有 N 个请求同时查库。

  • 它底层用的是 ConcurrentHashMap + ReentrantLock,不跨进程
  • 即使你配置了 RedisCacheManager,sync = true 也不走 Redis,更不涉及分布式协调
  • 如果你的应用是单体且确定永不水平扩展,它才勉强可用;否则就是假安全感

Redisson.getLock() 加锁时的三个关键参数怎么设

调用 lock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS) 时,这三个值不是随便填的,直接影响锁的可靠性与响应性:

Redis Skill - 高性能缓存管理
Redis Skill - 高性能缓存管理

Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。

下载
  • waitTime(等待获取锁的最大时间):建议 1–3 秒。太长会让请求堆积,太短容易频繁重试加重负载
  • leaseTime(锁自动释放时间):必须大于「查库 + 写缓存」的最长耗时。例如 DB 查询平均 200ms,序列化+写入最多 800ms,那就至少设为 2 秒;再加点余量,设为 3–5 秒更稳妥
  • 单位统一用 TimeUnit.SECONDS,避免传错单位导致锁秒级失效
  • 注意:leaseTime 不能设为 -1(永久),否则依赖手动 unlock,一旦异常未执行就会死锁;Redisson 的看门狗机制只对有限期锁生效

双重检查为什么必须写在 tryLock 成功后

这是防止「锁已释放但缓存还没写完」导致的重复加载。典型错误是把第二次查缓存放在 tryLock 外面,或只做一次检查。

// ❌ 错误:没进锁就查了一次,可能刚查完别人就写进去了,但你还去查库
Product product = (Product) redisTemplate.opsForValue().get(cacheKey);
if (product != null) return product;

RLock lock = redissonClient.getLock("lock:product:" + id);
if (lock.tryLock(2, 5, TimeUnit.SECONDS)) {
    // ✅ 正确:进锁后再查一次 —— 防止 A 刚释放锁、B 就拿到锁、C 还在等,此时缓存可能已被 A 写入
    product = (Product) redisTemplate.opsForValue().get(cacheKey);
    if (product != null) return product;

    product = productRepository.findById(id).orElse(null);
    if (product != null) {
        redisTemplate.opsForValue().set(cacheKey, product, 30, TimeUnit.MINUTES);
    }
    return product;
}
  • 第一次检查在锁外,是为了快速返回已有缓存,减少锁竞争
  • 第二次检查在锁内,是真正防击穿的防线:确保只有第一个抢到锁的线程查库,其余人在锁里查一次缓存就直接返回
  • 如果省略第二次检查,多个线程可能在「锁释放 → 缓存写入」这个极小时间窗口内先后获得锁,全部查库

锁 key 和业务 key 分离是硬性要求

锁的 key 必须和缓存 key 有明确区分,且带业务标识。常见错误是直接用 "product:"+id 当锁名 —— 这会导致不同业务互相干扰或锁粒度失控。

  • 推荐格式:"lock:product:"+id 或 "lock:cache:product:"+id
  • 绝对不要用固定锁名(如 "lock:product"),那会把整个商品模块串行化
  • 也不要拼接用户 ID、Session ID 等动态敏感信息进锁名,除非你明确需要按用户隔离,否则增加 key 数量和内存压力
  • Redisson 的锁 key 默认带前缀 redisson_lock:{xxx},你传进去的只是逻辑名,不用自己加前缀

真正容易被忽略的是锁 key 的生命周期管理:它不随业务逻辑结束而消失,只靠 leaseTime 自动清理。如果 leaseTime 设得太短,又没开启看门狗(比如用了低版本 Redisson 或禁用了),就可能在业务还没做完时锁就被释放,后续线程再次闯入 —— 这种竞态很难复现,但线上会偶发数据错乱或 DB 压力突增。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

redis spring boot

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
spring框架介绍
spring框架介绍

本专题整合了spring框架相关内容,想了解更多详细内容,请阅读专题下面的文章。

2025.08.06

2371

22

Java Spring Security 与认证授权
Java Spring Security 与认证授权

本专题系统讲解 Java Spring Security 框架在认证与授权中的应用,涵盖用户身份验证、权限控制、JWT与OAuth2实现、跨站请求伪造(CSRF)防护、会话管理与安全漏洞防范。通过实际项目案例,帮助学习者掌握如何 使用 Spring Security 实现高安全性认证与授权机制,提升 Web 应用的安全性与用户数据保护。

2026.01.26

437

25

什么是分布式
什么是分布式

分布式是一种计算和数据处理的方式,将计算任务或数据分散到多个计算机或节点中进行处理。本专题为大家提供分布式相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

1953

5

分布式和微服务的区别
分布式和微服务的区别

分布式和微服务的区别在定义和概念、设计思想、粒度和复杂性、服务边界和自治性、技术栈和部署方式等。本专题为大家提供分布式和微服务相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.07

2794

5

常用的数据库软件
常用的数据库软件

常用的数据库软件有MySQL、Oracle、SQL Server、PostgreSQL、MongoDB、Redis、Cassandra、Hadoop、Spark和Amazon DynamoDB。更多关于数据库软件的内容详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.02

4309

19

内存数据库有哪些
内存数据库有哪些

内存数据库有Redis、Memcached、Apache Ignite、VoltDB、TimesTen、H2 Database、Aerospike、Oracle TimesTen In-Memory Database、SAP HANA和ache Cassandra。更多关于内存数据库相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.14

3815

11

mongodb和redis哪个读取速度快
mongodb和redis哪个读取速度快

redis 的读取速度比 mongodb 更快。原因包括:1. redis 使用简单的键值存储,而 mongodb 存储 json 格式的数据,需要解析和反序列化。2. redis 使用哈希表快速查找数据,而 mongodb 使用 b-tree 索引。因此,redis 在需要高性能读取操作的应用程序中是一个更好的选择。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.02

6912

6

redis怎么做缓存服务器
redis怎么做缓存服务器

redis 作为缓存服务器的答案:redis 是一款开源、高性能、分布式的键值存储,可作为缓存服务器使用。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

623

6

redis怎么解决数据一致性
redis怎么解决数据一致性

redis 提供了两种一致性模型,以维护副本数据一致性:强一致性 (sync) 确保写操作仅在复制到所有从节点后才完成;最终一致性 (async) 则在主节点上写操作后认为已完成,牺牲一致性换取性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

736

6

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
phpEnv手册
phpEnv手册

共0课时 | 0人学习

进程与SOCKET
进程与SOCKET

共6课时 | 0.5万人学习