相关框架:spring、spring-data-redis、lettuce
Step1、编写分布式锁工具,完成加锁与释放锁功能
/**
* 基于redis的分布式锁实现工具类
* 高并发访问同一资源时,使所有访问线程同步进行操作,使得该方法具有原子性
* 该资源可以存储在任何地方
* 例如:修改某库存数量,方法中先判断库存是否大于1,然后减去1
* 这两个操作中间可能延迟,让其他线程先把库存减成了0,最后库存变成了负数
* 所以需要引入分布式锁操作
*/
@Component
@Transactional
public class LockUtil {
@Autowired
@Qualifier("jsonSyncRedisTemplate")
//JSON序列化、同步
private RedisTemplate jsonSyncRedisTemplate;
//用于存储标识此线程的ID
private ThreadLocal<String> threadIdBox = new ThreadLocal<>();
/**
* 加锁
* @param serviceId KEY 用于标识高并发修改资源的业务
* @param timeout 超时时间
* @param timeUnit 超时单位
* @return 创建KEY成功返回true 创建KEY失败返回false
*/
public boolean lock(String serviceId, Long timeout, TimeUnit timeUnit) {
try {
threadIdBox.set(UUID.randomUUID().toString());
//如果KEY不存在,则创建KEY
//KEY不存在,返回true 存在返回false
return jsonSyncRedisTemplate.opsForValue().setIfAbsent(serviceId, threadIdBox.get(), timeout, timeUnit);
} catch (Exception e) {
//引发任何异常,spring将不会创建KEY,直接返回false
threadIdBox.remove();
return false;
}
}
/**
* 释放锁
* @param serviceId KEY 用于标识高并发修改资源的业务
* @return
*/
public boolean unlock(String serviceId) {
//当前线程没有生成线程标识,说明压根没有创