Redisson 提供的分布式原子操作类(如 RAtomicLong、RAtomicDouble、RAtomicBoolean)基于 Redis 实现了与 Java 标准库中原子类类似的功能,确保跨节点操作的原子性。以下从原理、用法到应用场景详细说明:
一、核心原子类及原理
1. 主要原子类
- RAtomicLong:分布式原子长整型,支持加减、比较交换等操作。
- RAtomicDouble:分布式原子双精度浮点型。
- RAtomicBoolean:分布式原子布尔型。
- RAtomicReference:分布式原子引用,支持对象的原子操作。
这些类通过 Redis 的单线程特性和 Lua 脚本保证操作的原子性,避免多节点并发时的数据不一致问题。
2. 实现原理
以 RAtomicLong 为例:
- 数据存储:使用 Redis 的
String类型存储数值,键名为原子变量名。 - 原子操作:通过 Lua 脚本实现复合操作的原子性,如自增操作对应 Redis 命令
INCRBY key delta。 - 乐观锁机制:
compareAndSet()方法通过WATCH和事务实现 CAS(Compare-And-Swap)操作。
二、基本用法
1. RAtomicLong 示例
// 获取分布式原子长整型
RAtomicLong counter = redisson.getAtomicLong("global:counter");
// 初始化值(若不存在)
counter.compareAndSet(0, 100); // 若当前值为0,则设置为100
// 原子性自增
long newValue = counter.incrementAndGet(); // 先增后获取
long oldValue = counter.getAndIncrement(); // 先获取后增
// 原子性加减
counter.addAndGet(5); // 加5后返回新值
counter.getAndAdd(-3); // 返回原值后减3
// 原子性比较并设置
boolean success = counter.compareAndSet(105, 200); // 若当前值为105,则设置为200
2. RAtomicBoolean 示例
// 获取分布式原子布尔型
RAtomicBoolean initialized = redisson.getAtomicBoolean("system:initialized");
// 初始化(若不存在)
initialized.compareAndSet(false, true); // 若为false,则设置为true
// 原子性获取和设置
boolean current = initialized.get();
initialized.set(true);
// 原子性比较并设置
boolean updated = initialized.compareAndSet(true, false);
3. RAtomicReference 示例
// 获取分布式原子引用
RAtomicReference<User> userRef = redisson.getAtomicReference("user:123");
// 设置值
userRef.set(new User("Alice", 25));
// 原子性比较并设置
User oldUser = new User("Alice", 25);
User newUser = new User("Alice", 26);
boolean success = userRef.compareAndSet(oldUser, newUser);
// 原子性更新(使用函数式接口)
userRef.updateAndGet(user -> {
user.setAge(user.getAge() + 1);
return user;
});
三、高级特性
1. 批量操作
通过 Redis 的 Lua 脚本支持多个原子操作的批量执行,减少网络开销:
// 批量执行多个原子操作(伪代码,实际需通过 Redisson 的 RScript 实现)
RScript script = redisson.getScript();
script.eval(RScript.Mode.READ_WRITE,
"local counter = redis.call('INCR', 'counter') " +
"local flag = redis.call('GET', 'flag') " +
"return {counter, flag}",
RScript.ReturnType.MULTI,
Collections.singletonList("counter"));
2. 异步操作
所有原子操作都支持异步模式,提升高并发场景下的性能:
// 异步操作示例
RFuture<Long> future = counter.incrementAndGetAsync();
future.thenAccept(value -> {
System.out.println("异步自增后的值: " + value);
});
3. 分布式 CAS 操作
compareAndSet() 方法是实现分布式锁和乐观锁的基础:
// 分布式乐观锁示例
RAtomicLong version = redisson.getAtomicLong("data:version");
// 读取数据和版本
long currentVersion = version.get();
Data data = loadData();
// 修改数据后尝试提交
if (version.compareAndSet(currentVersion, currentVersion + 1)) {
// 提交成功
saveData(data);
} else {
// 版本冲突,重试或回滚
}
四、应用场景
1. 全局唯一ID生成器
// 基于RAtomicLong实现分布式ID生成器
RAtomicLong idGenerator = redisson.getAtomicLong("global:id");
// 获取下一个唯一ID
long nextId = idGenerator.incrementAndGet();
2. 分布式计数器
// 统计网站访问量
RAtomicLong visitCounter = redisson.getAtomicLong("website:visits");
// 每次访问时增加计数
visitCounter.incrementAndGet();
// 获取总访问量
long totalVisits = visitCounter.get();
3. 分布式限流
结合原子操作和时间窗口实现简单限流:
// 每秒限流100次请求
RAtomicLong requestCounter = redisson.getAtomicLong("request:counter:" + System.currentTimeMillis() / 1000);
// 请求处理前检查
if (requestCounter.incrementAndGet() <= 100) {
// 处理请求
} else {
// 拒绝请求(限流)
}
4. 状态标志管理
// 控制分布式任务的启动/停止状态
RAtomicBoolean taskRunning = redisson.getAtomicBoolean("task:running");
// 启动任务前检查
if (taskRunning.compareAndSet(false, true)) {
// 成功获取锁,启动任务
startTask();
} else {
// 任务已在运行
}
五、注意事项
1. 性能考虑
- 原子操作涉及 Redis 网络通信,性能低于本地原子类(如
java.util.concurrent.atomic.AtomicLong)。 - 高并发场景下,建议使用
updateAndGet()等批量操作减少网络调用。
2. 异常处理
- 网络异常可能导致操作失败,需捕获异常并重试:
try { counter.incrementAndGet(); } catch (RedisException e) { // 重试逻辑或降级处理 }
3. 数据类型限制
RAtomicDouble存储的是字符串形式的浮点数,可能存在精度损失,大额计算建议使用RBigDecimal。
4. Redis 集群兼容性
- 在 Redis 集群模式下,需确保原子操作的键分布在同一节点(通过哈希标签),否则可能导致跨节点操作失败。
六、总结
Redisson 的分布式原子操作类提供了跨节点的原子性保证,适用于全局唯一 ID 生成、分布式计数、状态标志管理等场景。使用时需注意网络性能和异常处理,在高并发场景下可结合异步操作提升吞吐量。