Redisson 异步释放锁

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

好久不见,各位友友们

我正在尝试创建一个基础设施,不同的机器通过 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 !");
        }
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哩哩啦啦’

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值