分布式锁代码编写问题分析
先给大家一段代码示例:
@Autowired Redisson redisson; @GetMapping("/modifyInfo/{id}") public Result modifyInfo(@PathVariable String id) { String lockKey = RedisLockConstant.ERP_CLUE_LOCK + id; RLock rLock = redisson.getLock(lockKey); try { rLock.tryLock(15,10, TimeUnit.SECONDS); doSomething(id); } catch (InterruptedException e) { log.error("加锁失败",e); return Result.error("网络拥堵请稍后再试", null); } finally { rLock.unlock(); } return Result.success(); } private void doSomething(String id) { log.info("业务请求- start -- {},{}",id,Thread.currentThread().getName()); try { Thread.sleep(6000); } catch (InterruptedException e) { throw new RuntimeException(e); } log.info("业务请求-end - {},{}",id,Thread.currentThread().getName()); }
问题点分析:
rLock.tryLock(15,10, TimeUnit.SECONDS);
先说tryLock三个参数的含义:
接着分析:
rLock.tryLock(100,10, TimeUnit.SECONDS);
设置等待时间100S ,如果6个请求同时过来了,看起来没问题,日志显示排队执行的。
2024-12-16 17:34:28.868 INFO [TID: N/A] http-nio-9115-exec-2 com.alpha.erp.controller.accounts.SupplierAccountsController - 业务请求- start -- 11,http-nio-9115-exec-2
2024-12-16 17:34:34.868 INFO [TID: N/A] http-nio-9115-exec-2 com.alpha.erp.controller.accounts.SupplierAccountsController - 业务请求-end - 11,http-nio-9115-exec-2
2024-12-16 17:34:34.880 INFO [TID: N/A] http-nio-9115-exec-1 com.alpha.erp.controller.accounts.SupplierAccountsController - 业务请求- start -- 11,http-nio-9115-exec-1
2024-12-16 17:34:40.881 INFO [TID: N/A] http-nio-9115-exec-1 com.alpha.erp.controller.accounts.SupplierAccountsController - 业务请求-end - 11,http-nio-9115-exec-1
2024-12-16 17:34:40.890 INFO [TID: N/A] http-nio-9115-exec-9 com.alpha.erp.controller.accounts.SupplierAccountsController - 业务请求- start -- 11,http-nio-9115-exec-9
2024-12-16 17:34:46.891 INFO [TID: N/A] http-nio-9115-exec-9 com.alpha.erp.controller.accounts.SupplierAccountsController - 业务请求-end - 11,http-nio-9115-exec-9
2024-12-16 17:34:46.905 INFO [TID: N/A] http-nio-9115-exec-3 com.alpha.erp.controller.accounts.SupplierAccountsController - 业务请求- start -- 11,http-nio-9115-exec-3
2024-12-16 17:34:52.905 INFO [TID: N/A] http-nio-9115-exec-3 com.alpha.erp.controller.accounts.SupplierAccountsController - 业务请求-end - 11,http-nio-9115-exec-3
2024-12-16 17:34:52.910 INFO [TID: N/A] http-nio-9115-exec-6 com.alpha.erp.controller.accounts.SupplierAccountsController - 业务请求- start -- 11,http-nio-9115-exec-6
2024-12-16 17:34:58.910 INFO [TID: N/A] http-nio-9115-exec-6 com.alpha.erp.controller.accounts.SupplierAccountsController - 业务请求-end - 11,http-nio-9115-exec-6
2024-12-16 17:34:58.927 INFO [TID: N/A] http-nio-9115-exec-4 com.alpha.erp.controller.accounts.SupplierAccountsController - 业务请求- start -- 11,http-nio-9115-exec-4
2024-12-16 17:35:04.928 INFO [TID: N/A] http-nio-9115-exec-4 com.alpha.erp.controller.accounts.SupplierAccountsController - 业务请求-end - 11,http-nio-9115-exec-4
可以理解为,每个线程都是进来最大等待100S,执行过程中,每个线程都没超过最大时间,都很文明的在等待;
如果我们把最大等待时间调整后继续测试,还是6个请求:
rLock.tryLock(15,10, TimeUnit.SECONDS);
上面有三个请求已经超过最大等待时间了,3个请求排队了,另外3个最大时间已过,15S后,这3个一起不文明的进来了。同时还出现了锁的释放也乱了,出现了异常;
总结:可以理解为,最大等待时间就是并发的每个线程,最大的文明时间。如果阻塞的请求过多,排队执行的时间累加起来超过最大等待时间,那继续排队的那些线程就开始不文明了。同时涌入,也就是不可控了