当前位置: 首页 > news >正文

Redisson 异步释放锁

在分布式系统中使用Redisson实现锁的问题。作者在尝试创建一个基础设施,让不同机器通过Redisson获取共享锁来执行异步任务。在任务完成后,由于线程上下文的丢失,出现了尝试解锁失败的IllegalMonitorStateException。为了解决这个问题,作者在获取锁时记录了线程ID,并在解锁时使用记录的线程ID来异步释放锁。此外,还展示了获取和释放锁的代码实现。

我正在尝试创建一个基础设施,不同的机器通过 Redisson 获取共享锁。一旦获得锁,一些异步任务就完成了,最后,当我完成工作时,我通过当前正在运行的线程释放 Redisson 锁 - 但我收到以下错误

java.lang.IllegalMonitorStateException: attempt to unlock lock, not locked by current thread by node id: xxxxx thread-id: 57

所以,我明白那个意思,但是因为我要执行异步工作,所以我不能使用获取线程来执行释放。
我不应该使用 Redisson 锁吗?像这样的异步工作的最佳匹配是什么?

解决方案
由于需要异步解锁,所以上锁时,将线程Id也记录下来

@Override
public ResultIf<String> match(Long orderId) {log.info("ResourceServiceImpl.match input:{}", orderId);String requestId = "";RLock lock = null;try {// 获取登录用户信息ActiveUser activeUser = userSysDao.getCurrentUser();Assert.notNull(activeUser, "activeUser is null");Assert.isTrue(activeUser.getUid() != 0, "userId is null");// 尝试获取锁lock = RedisLock.tryFairlock(buildKey(MATCH_LOCK, orderId + "", activeUser.getUid() + ""));if (ObjectUtils.isEmpty(lock)) {return ResultIf.FAIL("请重试!");}boolean locked = lock.isLocked();if (locked) {return ResultIf.SUCCESS("正在匹配,请稍后重试");}requestId = IdUtil.randomId();Assert.isTrue(StringUtils.isNotEmpty(requestId), "requestId is null");boolean flag =  lock.tryLock(60 * 4, TimeUnit.SECONDS);if (flag) {// 向redis中存入当前requestIdStringBuilder redisValue = new StringBuilder();redisValue.append(requestId);redisValue.append(":");redisValue.append(Thread.currentThread().getId());redisTemplateUtils.set(buildKey(MATCH_CURRENT_REQUEST, orderId + "", activeUser.getUid() + ""), redisValue.toString());// todo 业务代码return ResultIf.SUCCESS(requestId, "查询成功");}return ResultIf.SUCCESS("正在匹配,请稍后重试");} catch (Exception ex) {log.error("ResourceServiceImpl.match error", ex);return ResultIf.EXCEPTION(ex.getMessage());}
}

解锁

private void releaseLock(String orderId, String userId) {RLock lock = null;long threadId = 0l;try {/*** 2、释放分布式锁*/lock = RedisLock.tryFairlock(buildKey(MATCH_LOCK, orderId, userId));if (!ObjectUtils.isEmpty(lock)) {/*** 3、删除redis中当前requestId数据*/Object requestObj = redisTemplateUtils.get(buildKey(MATCH_CURRENT_REQUEST, orderId, userId));if (!ObjectUtils.isEmpty(requestObj)) {String redisValue = String.valueOf(requestObj);String[] split = redisValue.split(":");if (split.length == 2) {threadId = Long.valueOf(split[1]);}}// 是否还是锁定状态if (lock.isLocked()) {log.info("matchOperateLog unlock begin!");if (threadId != 0l) {lock.unlockAsync(threadId);boolean del = redisTemplateUtils.deleteKey(buildKey(MATCH_CURRENT_REQUEST, orderId, userId));log.info("matchOperateLog deleteKey remove res {}", del);} else {lock.unlockAsync();}log.info("matchOperateLog unlock end!");}}} catch (Exception e) {log.error("release operation failed", e);} finally {if (!ObjectUtils.isEmpty(lock) && lock.isLocked() && threadId != 0l) {lock.unlock();log.info("matchOperateLog finally unlock !");}}
}

http://www.mrgr.cn/news/26556.html

相关文章:

  • Leetcode 旋转图像
  • 如何建设数据中台(五)——数据汇集—打破企业数据孤岛
  • SpringBoot 整合酷狗获取下载音乐(需要自己账户)
  • Python画笔案例-048 绘制嵌套正方形
  • STM32 移植FATFS时遇到ff_oem2uni函数未定义问题
  • 雷达液位计助力造纸行业精准测量
  • 路由交换基础知识(bing1)
  • C语言——二分法搜索数组中特定元素并返回下标
  • 听劝!40天涨粉10W+,这个AI赛道太好赚了!
  • ADS1248 测电阻 0~10欧姆
  • 个体诊所社区门诊医务室电子处方生成开单软件 佳易王诊所处方管理系统操作教程
  • [XILINX] 正点原子ZYNQ7015开发板!ZYNQ 7000系列、双核ARM、PCIe2.0、SFPX2,性能强悍,资料丰富!
  • iso speed
  • 癌症细胞状态的十年探索:单细胞RNA测序的启示
  • 使用 Elastic 和 LM Studio 的 Herding Llama 3.1
  • Python OpenCV精讲系列 - 高级图像处理技术(六)
  • PHP一键寄送尽在掌中快递寄件小程序
  • Prompt最佳实践|善用分隔符,让你的Prompt更清晰
  • 深兰科技董事长陈海波应出席“香港大学国际科创大赛”
  • 使用开源框架HandyControl