Springboot框架下,Redisson简单使用
使用下方代码时,需要引入maven依赖,在代码的下方。废话不多说,上 代码片
.
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class YourService {
@Autowired
private RedissonClient redissonClient;
// 其他代码...
@Transactional(rollbackFor = Exception.class)
public long insertSyncData(SyncDataLog syncDataLog,
EcodePurchaseOrder purchaseOrder,
String csvFilePath) {
// 获取 Redis 锁
RLock lock = redissonClient.getLock("your-lock-name");
try {
// 尝试获取锁,最多等待 10 秒
if (lock.tryLock(10, TimeUnit.SECONDS)) {
// 读取csv文件
// ... 其他代码
return syncDataList.size();
} else {
throw new ServiceException("获取分布式锁失败");
}
} catch (Exception e) {
throw new ServiceException("处理过程中发生异常", e);
} finally {
// 释放锁
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
// 其他代码...
}
请注意,这只是一个简化的示例,实际上可能需要根据您的具体需求进行更复杂的处理。确保 Redisson 的配置正确,包括 Redis 的连接信息等。
下方是具体如何使用Redission
1、引入 Redisson 依赖
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.17.1</version>
</dependency>
2、配置 Redisson
@Configuration
public class RedissonConfig {
@Bean
public RedissonClient redissonClient() {
Config config = new Config();
// 配置 Redis 连接信息,例如 Redis 地址
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
return Redisson.create(config);
}
}
3、在需要控制并发的方法中使用分布式锁:
@Service
public class YourService {
@Autowired
private RedissonClient redissonClient;
public void yourConcurrentMethod() {
String lockName = "your-lock"; // 设置唯一的锁名
RLock lock = redissonClient.getLock(lockName);
try {
lock.lock(); // 尝试获取锁
// 在这里执行需要控制并发的代码
} finally {
lock.unlock(); // 释放锁
}
}
}
说明:
#:请注意,在使用分布式锁时,应该确保锁的加锁和解锁操作都能够正常执行,避免死锁等问题。同时,了解 Redisson 的其他特性,以便根据具体需求使用更多的分布式功能。
当然你也可以使用 StringRedisTemplate 实现了简单的分布式锁,通过调用 setIfAbsent 方法尝试获取锁。如果 setIfAbsent 返回 true,表示成功获取到锁,执行相应的业务逻辑,最后使用 delete 方法释放锁。当使用 StringRedisTemplate 实现分布式锁时,主要利用 Redis 的 SETNX(SET if Not eXists)命令实现原子性的加锁。当并发量较大时,可能会遇到一些问题:
1、抢锁失败的问题: 多个线程同时尝试加锁,只有一个线程能够成功,其余线程抢锁失败。这可能导致一些线程需要等待重新尝试获取锁。
2、死锁问题: 如果持有锁的线程执行时间过长或发生异常,可能导致其他线程一直无法获取锁,从而产生死锁。
3、非公平性: Redis 的 SETNX 操作是非公平的,没有按照加锁请求的顺序依次获得锁。这可能导致某些线程一直无法获取到锁。
4、无法自动释放锁: 与 Redisson 不同,StringRedisTemplate 无法提供自动释放锁的功能。需要手动调用 delete 方法释放锁,因此在使用过程中需要注意锁的释放。
5、性能问题: 使用 SETNX 实现锁可能不如 Redisson 的底层实现效率高,因为 SETNX 需要执行两个操作:检查 Key 是否存在和设置 Key 的值。
!!综上所述:如果你的项目主要是进行简单的缓存和基础的分布式锁操作,且对于依赖的引入和维护希望尽量简化,可以选择使用 StringRedisTemplate。如果项目中有较为复杂的分布式应用场景,或者对于分布式锁有更高级别的要求,可以考虑使用 Redisson。
补充一点:使用任何锁,都要意识到锁的超时过期时间,避免不必要的资源开销导致各种问题。以下以redisTemplate为例
当获取锁时放置:redisTemplate.opsForValue().set(lockName, “locked”, timeout, TimeUnit.SECONDS);
当取锁成功放置:redisTemplate.expire(lockName, timeout, TimeUnit.SECONDS); lockName为你的锁名,timeout超时时间。
以上这里以redisTemplate为例,需要显式设置,然而Redisson 默认会设置分布式锁的超时时间,超时时间由 LockWatchdogTimeout 参数控制,默认为 30 秒。
结论:在高并发场景中,建议考虑使用专门的分布式锁工具,如 Redisson 或 Curator 等,它们提供更多功能,包括锁的超时设置、异步执行、监听器等,能够更好地满足复杂的分布式应用场景。
欢迎评论指正,讨论发表观点,谢谢。