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

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

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 。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/5606167.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-12-15
下一篇2022-12-15

发表评论

登录后才能评论

评论列表(0条)

    保存