在Spring Boot中多线程操作同一个Redis键怎么避免并发冲突?

胖敏酱_1795

胖敏酱_1795

2026-11-14

217人浏览

原创

INCR/DECR等原子命令可替代“读-改-写”三步操作,避免并发下计数器更新丢失;其核心价值在于Redis单线程模型保障服务端一次完成整个操作,彻底消除竞态条件。

在spring boot中多线程操作同一个redis键怎么避免并发冲突?

用 INCR/DECR 等原子命令替代“读-改-写”三步操作

最常见也最容易踩坑的场景,就是多个线程同时执行 get → 计算 → set。比如计数器递增,两个线程都读到 100,各自加 1 后都写回 101,结果丢了一次更新。

Redis 本身是单线程的,但它的原子命令(如 INCR、DECR、INCRBY、SETNX)能在服务端一次完成整个操作,客户端无需参与中间状态。

  • redisTemplate.opsForValue().increment("counter", 1) 比先 get 再 set 安全得多,且性能更好
  • 对字符串做拼接?用 APPEND;想设值但只在 key 不存在时生效?用 setIfAbsent()(注意它不带过期时间)
  • 避免把业务逻辑挪到 Java 层做判断——只要能用原子命令表达的,就别拆成多条 Redis 命令

共享资源必须加锁时,别手写 SETNX + EXPIRE

如果操作不能靠原子命令覆盖(比如扣库存 + 写订单 + 发消息这一整套),就必须加分布式锁。但直接用 setIfAbsent("lock:order:123", "1") 然后调 expire() 是危险的:两步非原子,网络抖动或 Redis 响应慢会导致锁没过期时间,变成死锁。

真正安全的做法是使用原子命令 SET lock:key unique-value NX PX 30000 —— 这个“判断不存在 + 设值 + 设过期”必须一步到位。

  • Spring Boot 项目里,直接用 Redisson 的 RLock.lock(),它底层就是封装了这个原子命令
  • 自己手写 Lua 脚本解锁也行,但必须保证解锁时先校验 value 是否匹配,再 DEL,这两步也要原子执行
  • value 必须全局唯一(推荐用 UUID + 线程ID),否则可能误删别人持有的锁

连接池配置不当会放大并发问题

Redis 服务端没问题,不代表客户端稳。当大量线程争抢 Redis 连接时,如果连接池太小,会卡在获取连接阶段,表现为超时、拒绝连接、响应毛刺,甚至触发熔断。

Sentinal Redis
Sentinal Redis

监控Redis服务器健康状况、内存、性能及BullMQ队列。检查队列深度、失败任务,分析慢查询并诊断问题。

下载

默认的 Lettuce 或 Jedis 连接池参数往往不适合高并发场景,尤其在 Spring Boot 自动配置下容易被忽略。

  • Lettuce 推荐显式配置:spring.redis.lettuce.pool.max-active=32、max-wait=3000、min-idle=8
  • 连接数不是越多越好:过高会压垮 Redis,过低则排队严重;建议从 16–32 开始压测,观察 redis.clients.lettuce.core.RedisClient 的连接等待日志
  • 务必启用连接健康检测(test-on-borrow=true 或 Lettuce 的 validateConnection),避免拿到已断连的脏连接

集群模式下跨槽操作天然不支持原子性

如果你用的是 Redis 集群(不是单机或哨兵),那要特别小心:同一个业务逻辑涉及的多个 key,如果落在不同 slot,就无法用事务或 Lua 脚本保证原子性。

比如订单号 order:123 和对应库存 stock:123,默认哈希后很可能分到不同节点,WATCH 或 MULTI/EXEC 会直接报错 CROSSSLOT Keys in request don't hash to the same slot。

  • 强制共槽的最简单办法:用花括号包裹公共标识,例如 order:{123} 和 stock:{123},Lettuce 会只对花括号内内容哈希
  • 集群下不要依赖 keys *、scan 全局扫描,它们在各节点分别执行,结果不可靠
  • 分布式锁的 key 也得带哈希标签,否则 lock:order:{123} 才能确保锁和业务数据在同一个节点

真正难的不是写对一行 increment(),而是搞清哪部分该用原子命令、哪部分必须加锁、锁该加在哪一层(key 粒度?业务维度?)、以及集群拓扑如何影响你的键设计。这些决策一旦定错,压测时可能不暴露,上线后流量一上来就出数据错乱。

相关文章

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

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

下载

相关标签:

redis spring boot

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

相关专题

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

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

2025.08.06

2971

22

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

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

2026.01.26

517

25

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

2025.12.24

1369

20

java多线程相关教程合集
java多线程相关教程合集

本专题整合了java多线程相关教程,阅读专题下面的文章了解更多详细内容。

2026.01.21

463

30

C++多线程相关合集
C++多线程相关合集

本专题整合了C++多线程相关教程,阅读专题下面的的文章了解更多详细内容。

2026.01.21

599

24

C# 多线程与异步编程
C# 多线程与异步编程

本专题深入讲解 C# 中多线程与异步编程的核心概念与实战技巧,包括线程池管理、Task 类的使用、async/await 异步编程模式、并发控制与线程同步、死锁与竞态条件的解决方案。通过实际项目,帮助开发者掌握 如何在 C# 中构建高并发、低延迟的异步系统,提升应用性能和响应速度。

2026.02.06

449

20

C++多线程并发控制与线程安全设计实践
C++多线程并发控制与线程安全设计实践

本专题围绕 C++ 在高性能系统开发中的并发控制技术展开,系统讲解多线程编程模型与线程安全设计方法。内容包括互斥锁、读写锁、条件变量、原子操作以及线程池实现机制,同时结合实际案例分析并发竞争、死锁避免与性能优化策略。通过实践讲解,帮助开发者掌握构建稳定高效并发系统的关键技术。

2026.03.16

273

22

Java 多线程与并发编程实战
Java 多线程与并发编程实战

深入讲解 Java 并发编程体系,涵盖 Thread / Runnable / Callable 线程创建方式、线程生命周期与状态转换、synchronized 同步锁与 Lock/ReentrantLock 显式锁、volatile 可见性保证、ThreadPool 线程池配置与调优(核心参数/拒绝策略)、JUC 并发工具类(CountDownLatch/CyclicBarrier/Semaphore/ConcurrentHashMa

2026.04.17

409

31

C++ 多线程使用教程大全
C++ 多线程使用教程大全

系统讲解 C++11 及后续标准引入的多线程编程能力,涵盖 std::thread 线程创建与生命周期管理、std::mutex / shared_mutex 互斥锁与读写锁、std::condition_variable 条件变量同步、std::atomic 原子操作与内存序(memory_order)、std::future / promise / async 异步任务、线程池的设计与实现、死锁检测与避免策略,帮助开发者编写正确高效

2026.04.28

256

17

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go-Zero官方文档
Go-Zero官方文档

共0课时 | 0人学习