秒杀系统不超卖:Redisson分布式计数器AtomicLong与AtomicDouble实战指南
【免费下载链接】redisson 项目地址: https://gitcode.com/gh_mirrors/red/redisson
你是否还在为分布式系统中的并发计数问题头疼?库存超卖、统计数据不一致、分布式ID生成错误——这些问题往往源于传统单机计数器无法跨节点同步状态。本文将通过Redisson的分布式原子类AtomicLong和AtomicDouble,带你一站式解决分布式环境下的计数难题,掌握高并发场景下的精准计数方案。
分布式计数的痛点与解决方案
在分布式系统中,多个服务实例同时操作同一个计数器时,传统的java.util.concurrent.atomic.AtomicLong由于仅作用于单个JVM进程,无法保证跨节点的数据一致性。以电商秒杀场景为例,当100个用户同时抢购最后10件商品时,若每个服务实例单独维护库存计数,会导致超卖问题。
Redisson提供的分布式原子类通过Redis的单线程特性和Lua脚本原子性操作,完美解决了这一问题。其核心实现位于:
- RedissonAtomicLong.java:分布式长整型计数器
- RedissonAtomicDouble.java:分布式双精度浮点型计数器
快速上手:Redisson环境搭建
Maven依赖配置
在项目的pom.xml中添加Redisson依赖:
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.30.0</version>
</dependency>
初始化Redisson客户端
通过简单配置即可创建Redisson客户端实例,支持单机、集群、哨兵等多种部署模式:
// [Redisson.java](https://link.gitcode.com/i/1b7cf85cb3557c8ae3ce2f7ec229e318)
Config config = new Config();
config.useSingleServer()
.setAddress("redis://127.0.0.1:6379");
RedissonClient redisson = Redisson.create(config);
RAtomicLong核心操作与实战场景
基础API全解析
RedissonAtomicLong实现了与JDK AtomicLong类似的API,同时提供异步操作能力:
| 方法 | 同步调用 | 异步调用 | 说明 |
|---|---|---|---|
| 递增并获取 | incrementAndGet() | incrementAndGetAsync() | 原子性+1并返回新值 |
| 递减并获取 | decrementAndGet() | decrementAndGetAsync() | 原子性-1并返回新值 |
| 累加并获取 | addAndGet(long delta) | addAndGetAsync(long delta) | 原子性增加delta并返回新值 |
| 比较并设置 | compareAndSet(long expect, long update) | compareAndSetAsync(...) | CAS操作,成功返回true |
秒杀系统库存控制案例
以下代码展示如何使用RAtomicLong实现秒杀场景的库存控制:
// 获取分布式原子计数器实例
RAtomicLong stockCounter = redisson.getAtomicLong("seckill:stock:1001");
// 初始化库存为100件
stockCounter.set(100);
// 用户抢购逻辑
public boolean purchase(String userId) {
// 原子性递减库存,返回新值
long remaining = stockCounter.decrementAndGet();
if (remaining < 0) {
// 库存不足,恢复计数
stockCounter.incrementAndGet();
return false;
}
// 生成订单逻辑...
return true;
}
分布式ID生成器实现
利用RAtomicLong的递增特性,可以轻松实现分布式环境下的唯一ID生成:
RAtomicLong idGenerator = redisson.getAtomicLong("order:id:generator");
// 初始值设为10000
idGenerator.set(10000);
// 生成唯一订单号
public long generateOrderId() {
return idGenerator.incrementAndGet();
}
RAtomicDouble与浮点型计数场景
对于需要小数精度的计数场景(如评分系统、统计平均值),RAtomicDouble提供了双精度浮点型支持。其核心实现通过Redis的字符串存储,使用Lua脚本保证操作原子性。
核心方法示例
// 获取分布式浮点计数器
RAtomicDouble scoreCounter = redisson.getAtomicDouble("product:score:1001");
// 设置初始评分
scoreCounter.set(4.5);
// 增加0.3分并获取新值
double newScore = scoreCounter.addAndGet(0.3);
// 输出: 4.8
System.out.println(newScore);
// 比较并设置新值
boolean success = scoreCounter.compareAndSet(4.8, 4.7);
商品评分统计案例
以下代码实现电商商品的平均分统计功能:
public class ProductScoreService {
private final RAtomicDouble avgScore;
private final RAtomicLong scoreCount;
public ProductScoreService(RedissonClient redisson, String productId) {
this.avgScore = redisson.getAtomicDouble("product:avgScore:" + productId);
this.scoreCount = redisson.getAtomicLong("product:scoreCount:" + productId);
}
public void addScore(double score) {
// 原子性更新总分和计数
double total = avgScore.get() * scoreCount.get();
avgScore.set((total + score) / scoreCount.incrementAndGet());
}
public double getAvgScore() {
return avgScore.get();
}
}
高级特性:监听器与原子操作扩展
计数器变更监听器
Redisson提供了事件监听机制,可以实时响应计数器变化:
RAtomicLong counter = redisson.getAtomicLong("user:login:counter");
// 添加递增监听器
counter.addListener((IncrByListener) (charSequence, long1) -> {
System.out.println("计数器递增: " + long1);
});
批量原子操作
通过Redisson的getAtomicLong和getAtomicDouble方法,可以轻松创建多个计数器实例,实现复杂业务场景的原子操作组合:
// [Redisson.java](https://link.gitcode.com/i/1b7cf85cb3557c8ae3ce2f7ec229e318)
RAtomicLong orderCounter = redisson.getAtomicLong("daily:order:count");
RAtomicDouble salesAmount = redisson.getAtomicDouble("daily:sales:amount");
// 订单创建时原子更新两个计数器
public void createOrder(double amount) {
orderCounter.incrementAndGet();
salesAmount.addAndGet(amount);
}
性能优化与最佳实践
合理选择数据类型
- 整数计数优先使用
RAtomicLong,存储和计算效率更高 - 小数计数(如评分、百分比)使用
RAtomicDouble,避免浮点运算误差
避免热点Key问题
对于高并发场景,可通过Redisson的分片机制分散热点:
// [RedissonLongAdder.java](https://link.gitcode.com/i/e27e41b4b4af9c8a96c5b3a3daf8bc12)
RLongAdder counter = redisson.getLongAdder("high:concurrency:counter");
counter.increment();
资源释放
使用完毕后,及时关闭Redisson客户端释放资源:
// [Redisson.java](https://link.gitcode.com/i/1b7cf85cb3557c8ae3ce2f7ec229e318)
redisson.shutdown();
总结与扩展阅读
通过Redisson的分布式原子类,我们可以在分布式环境中轻松实现线程安全的计数功能。无论是秒杀库存控制、分布式ID生成,还是实时统计分析,RAtomicLong和RAtomicDouble都能提供高效可靠的原子操作支持。
相关模块与文档
- 官方文档:README.md
- 配置指南:Redisson配置文档
- 完整API:Redisson JavaDoc
下期预告
下一篇我们将深入探讨Redisson的分布式集合框架,学习如何使用分布式Map、Set等数据结构解决更复杂的业务场景。记得点赞收藏本文,关注获取更多分布式系统实践指南!
【免费下载链接】redisson 项目地址: https://gitcode.com/gh_mirrors/red/redisson
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



