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

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中存入当前requestId
            StringBuilder 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.kler.cn/a/305325.html

相关文章:

  • 【Python TensorFlow】进阶指南(续篇一)
  • 【RabbitMQ】08-延迟消息
  • 游戏引擎学习第五天
  • uniapp分享功能
  • UI资源分包 -- 基于Xasset框架代码实例
  • 物流企业新闻稿怎么写?货运行业品牌宣传背书的报纸期刊杂志媒体有哪些
  • 什么是485无线通信
  • 磁盘写操作压力测试工具的设计与实现
  • ChatGLM3模型搭建教程
  • OpenCV结构分析与形状描述符(20)计算一个包围给定点集的最小外接圆函数minEnclosingCircle()的使用
  • 研1日记12
  • C++系列-函数对象/仿函数
  • [网络]TCP/IP协议 之 网络层IP协议(3)
  • 艾丽卡的区块链英语小课堂
  • 基于ssm+vue+uniapp的新生报到系统小程序
  • 第4步CentOS配置SSH服务用SSH终端XShell等连接方便文件上传或其它操作
  • 实战外网配置——光猫桥接+路由器PPPoE拨号+防火墙外网链路健康检查+外网流量负载均衡
  • kafka mirror maker之实现两个kafka集群之间的数据同步
  • HTML + CSS - 网页布局之一般布局浮动布局
  • JVM 体系与结构
  • Node.js 中间件与洋葱模型
  • SonicWall SSL VPN曝出高危漏洞,可能导致防火墙崩溃
  • java --- 性能优化01
  • Git使用—把当前仓库的一个分支push到另一个仓库的指定分支、基于当前仓库创建另一个仓库的分支并推送到对应仓库(mit6828)
  • 使用 easyX 库实现顺序表插入操作的可视化
  • 并发锁机制之深入理解synchronized