Redis实现分布式锁的简单例子
废话不多说,直接看代码。
public String lock(Goods goods, Long goodsCount) {
// 先去尝试给 redis 加锁
String id = String.valueOf(goods.getGoodsId());
ValueOperations<String, String> ops = redisTemplate.opsForValue();
String threadName = Thread.currentThread().getName();
long startTime = System.currentTimeMillis();
while (true) {
if (Boolean.FALSE.equals(ops.getOperations().hasKey(id))) {
ops.set(id, threadName, 10, TimeUnit.SECONDS);
if (threadName.equals(ops.get(id))) {
// 加锁成功了,退出
log.info(threadName + "加锁成功");
break;
}
}
if (System.currentTimeMillis() - startTime > 15 * 1000) {
return "购买超时,请稍后重试";
}
}
// 设置守护线程,防止还线程还没做完就key就过期了
Thread daemonThread = ThreadUtils.getDaemon(() -> {
while (true) {
try {
Thread.sleep(9000);
ops.set(id, threadName, 10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
break;
}
}
});
try {
// 说明没库存了
if (goodsCount < 0 && goodsCount + goods.getStockNum() < 0) {
return "库存不足!";
}
// 注意不能直接更新值
log.info(String.valueOf(goodsMapper.updateGoodsStockNum(
goods.getGoodsId(), goodsCount, LocalDateTime.now())));
} catch (Exception e) {
e.printStackTrace();
} finally {
daemonThread.interrupt();
if (Objects.equals(ops.get(id), threadName)) {
redisTemplate.delete(id);
log.info(threadName + "释放锁");
}
}
return ResultGenerator.ResultMsg.SUCCESS;
}