引入依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.68</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.14.0</version>
</dependency>
RedissonConfig
创建连接
@Configuration
public class RedissionConfig {
@Bean
public RedissonClient getRedisson() {
Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
return Redisson.create(config);
}
}
RedissonUtil
@Component
public class RedissonUtil {
@Autowired
private RedissonClient redissonClient;
private Logger logger = Logger.getLogger(RedissonUtil.class);
private final String LOCK_FLAG = "rlock_";
/**
* 根据name对进行上锁操作,redissonLock 阻塞事的,采用的机制发布/订阅
* @param lockName
*/
public void lock(String lockName, int timeOutMinute) {
String key = LOCK_FLAG + lockName;
RLock lock = redissonClient.getLock(key);
//lock提供带timeout参数,timeout结束强制解锁,防止死锁 :1分钟
lock.lock(timeOutMinute, TimeUnit.MINUTES);
}
/**
* 根据name对进行上锁操作,redissonLock 阻塞事的,采用的机制发布/订阅
* @param lockName
*/
public void lock(String lockName) {
String key = LOCK_FLAG + lockName;
RLock lock = redissonClient.getLock(key);
lock.lock();
}
/**
* 根据name进行上锁操作,redissonLock 非阻塞的
*
* @param lockName
* @param waitTime 毫秒,等待锁的时间,等待超时即放弃
* @return true锁成功,false锁失败
*/
public boolean trylock(String lockName, long waitTime) {
try {
String key = LOCK_FLAG + lockName;
RLock lock = redissonClient.getLock(key);
return lock.tryLock(waitTime, TimeUnit.MILLISECONDS);
} catch (Exception e) {
return false;
}
}
/**
* 多重锁<br>
* 根据name进行上锁操作,redissonLock 非阻塞的
*
* @param lockNamePre 锁前缀
* @param waitTime 毫秒,等待锁的时间,等待超时即放弃
* @param args 锁后缀列表
* @return true锁成功,false锁失败
*/
public boolean trylock(String lockNamePre, List<String> args, long waitTime) {
boolean flag;
RLock[] locks = new RLock[args.size()];
for (int i=0;i<args.size();i++) {
String key = LOCK_FLAG + lockNamePre + args.get(i);
RLock lock = redissonClient.getLock(key);
locks[i] = lock;
}
RLock multiLock = redissonClient.getMultiLock(locks);
try {
flag = multiLock.tryLock(waitTime, TimeUnit.MILLISECONDS);
} catch (Exception e) {
flag = false;
}
return flag;
}
/**
* 根据name进行解锁操作
*
* @param lockNamePre 锁前缀
* @param args 锁后缀列表
*/
public void unlock(String lockNamePre, List<String> args) {
RLock[] locks = new RLock[args.size()];
for (int i=0;i<args.size();i++) {
String key = LOCK_FLAG + lockNamePre + args.get(i);
RLock lock = redissonClient.getLock(key);
locks[i] = lock;
}
RLock multiLock = redissonClient.getMultiLock(locks);
multiLock.unlock();
}
/**
* 根据name对进行解锁操作
* @param lockName
*/
public void unlock(String lockName) {
String key = LOCK_FLAG + lockName;
RLock lock = redissonClient.getLock(key);
lock.unlock();
}
}
使用分布式锁
@Service
public class StockFlowServiceImpl extends ServiceImpl<StockFlowMapper, SkillStockFlow> implements StockFlowService {
@Autowired
private ActivityItemServiceImpl activityItemService;
@Autowired
private RedissonUtil redissonUtil;
@Override
public boolean skillItem(SkillDto skillDto) {
boolean trylock = false;
String orderId = UUID.randomUUID().toString().replace("-","");
//lockName不一样,持的锁就不一样
String lockName = skillDto.getItemId();
try {
trylock = redissonUtil.trylock(lockName,100);
if (!trylock){
return false;
}
boolean flag = activityItemService.reduceStock(skillDto.getItemId(), skillDto.getBuyNum());
if (flag){
SkillStockFlow skillStockFlow = new SkillStockFlow();
BeanUtils.copyProperties(skillDto,skillStockFlow);
skillStockFlow.setOrderId(orderId);
save(skillStockFlow);
}
return true;
} catch (BeansException e) {
e.printStackTrace();
return false;
} finally {
if (trylock){
redissonUtil.unlock(lockName);
}
}
}
}
参考博客:
Redisson重连后WatchDog失效问题解决http://events.jianshu.io/p/84522c2736a2
获取锁的原理参考博客:https://blog.csdn.net/qq_41489540/article/details/113772408