栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Redis释放锁报错Lock was released in the store due to expiration. The integrity of data protected by this

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Redis释放锁报错Lock was released in the store due to expiration. The integrity of data protected by this

背景

今天在生产环境中碰到了这个问题,Lock was released in the store due to expiration. The integrity of data protected by this lock may have been compromised.

分析

查看报错来源,是来自于org.springframework.integration.redis.util.RedisLockRegistry的内部类 RedisLock的 unlock 方法。

@Override
public void unlock() {
    if (!this.localLock.isHeldByCurrentThread()) {
        throw new IllegalStateException("You do not own lock at " + this.lockKey);
    }
    if (this.localLock.getHoldCount() > 1) {
        this.localLock.unlock();
        return;
    }
    try {
        if (!isAcquiredInThisProcess()) {
            throw new IllegalStateException("Lock was released in the store due to expiration. " +
                                            "The integrity of data protected by this lock may have been compromised.");
        }

        if (Thread.currentThread().isInterrupted()) {
            RedisLockRegistry.this.executor.execute(this::removeLockKey);
        }
        else {
            removeLockKey();
        }

        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("Released lock; " + this);
        }
    }
    catch (Exception e) {
        ReflectionUtils.rethrowRuntimeException(e);
    }
    finally {
        this.localLock.unlock();
    }
}

可以看到,在释放锁时只要当前线程没有持有锁,就会报这个异常。

查看该类的注释,大致意思是 RedisLockRegistry 是 ExpirableLockRegistry 接口的实现类,其提供了 Redis 的分布式锁功能。该锁的过期时间默认是 60 s。当线程尝试解锁已过期的锁时将会抛出 IllegalStateException 异常。这种场景应该被视为一个致命的错误,因为此时受保护的资源可能已被第三方修改。
对于这一问题也有人在官方的 Github 上提了 issue ,其地址为 https://github.com/spring-projects/spring-integration/issues/2894 。

提问者的大致意思为,在锁过期时释放锁这一行为看起来不是个 bug ,在这时抛异常可能会误导开发者。所以,为什么不能忽略 Redis 锁已过期的场景,这样对开发者不是更友好嘛。至少这样就不需要在上面的 finally 语句块中再嵌入一个 try catch 语句块。

而官方回答的大致意思也和上述注释差不多,即当锁过期时,这往往意味着受保护的数据可能已被其他程序所修改。 IllegalStateException 这个异常是为了告诉应用锁过期这一场景已经发生了,因此应用可以采取一些措施来验证数据是否还是 ok 的。假如此时只是安静退出的话,应用将不会知道数据可能已被第三方修改。

解决方案

可以在 finally 语句块中再嵌入一个 try catch 语句块,并视情况选择是否采取一些措施来验证数据是否 ok 。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/601364.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号