Redis实战-Redisson-分布式锁 (2)

30:失效时间,防止死锁(如果加锁时不设置过期时间,当系统执行完加锁还未进行解锁时系统宕机,那其他节点也无法进行下单,因为锁一直在)。

解锁逻辑最好放在finally中进行,防止报错导致死锁。

// 锁标识 private static final String LOCK_KEY = "book_lock"; /** * 购买图书 */ @GetMapping("buy1") public String buy1() { String clientId = UUID.randomUUID().toString(); /* * 给redis设置一个key,并设置过期时间防止死锁 * setIfAbsent(setnx):当key不存在时才设置值 * flag=true:值设置成功(获取锁) flag=false:设置值失败(获取锁失败) */ Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(LOCK_KEY, clientId, 30, TimeUnit.SECONDS); try { if(Objects.nonNull(flag) && flag) { String buyBefore = stringRedisTemplate.opsForValue().get(KEY); if(Objects.isNull(buyBefore)) { log.error("未找到\"{}\"的库存信息~", KEY); return "暂未上架~"; } long buyBeforeL = Long.parseLong(buyBefore); if(buyBeforeL > 0) { Long buyAfter = stringRedisTemplate.opsForValue().decrement(KEY); log.info("剩余图书==={}", buyAfter); return "购买成功~"; } else { log.info("库存不足~"); return "库存不足~"; } } else { log.error("获取锁失败~"); } } catch(Exception e) { e.printStackTrace(); } finally { // 防止误删锁 if(clientId.equals(stringRedisTemplate.opsForValue().get(LOCK_KEY))) { stringRedisTemplate.delete(LOCK_KEY); } } return "系统错误~"; } 3.2 启动测试

​ 启动两个服务,并配置nginx负载均衡。

Redis实战-Redisson-分布式锁

​ nginx配置如下:

Redis实战-Redisson-分布式锁

​ jemter配置如下:

Redis实战-Redisson-分布式锁

Redis实战-Redisson-分布式锁

启动测试:

​ 部分日志如下:

Redis实战-Redisson-分布式锁

Redis实战-Redisson-分布式锁

redis中查看库存:

Redis实战-Redisson-分布式锁

打完收工~

3.3 小节

这里主要是用了setnx来实现分布式锁。虽然解决了超卖问题,但其中还是有很多缺陷。比如:

当请求获取锁失败时,能不能尝试重新获取锁或者阻塞等待获取锁,而不是直接返回系统繁忙之类的提示语。

如果持有锁的请求处理时间超过了设置的超时时间,也就是业务逻辑还没有处理完呢,但锁已经失效了,此时刚好又进来一个请求,又有并发问题了

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zysspy.html