这是以下问题的后续问题:https://github.com/spring-projects/spring-integration/issues/8687
正如上面链接中所讨论的,Spring Integration Distributed Lock 的 TTL 概念仅适用于跨进程,不适用于同一进程中的线程。
后来尝试了redisson,它的RLock中有一个租约时间的概念:
/**
* Tries to acquire the lock with defined <code>leaseTime</code>.
* Waits up to defined <code>waitTime</code> if necessary until the lock became available.
*
* Lock will be released automatically after defined <code>leaseTime</code> interval.
*
* @param waitTime the maximum time to acquire the lock
* @param leaseTime lease time
* @param unit time unit
* @return <code>true</code> if lock is successfully acquired,
* otherwise <code>false</code> if lock is already set.
* @throws InterruptedException - if the thread is interrupted
*/
boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException;
我认为TTL和租约时间这两个概念很相似(如果我错了请纠正我)。
但是,redisson 的租用时间对于跨进程和同一进程中的线程都以一致的方式工作,而 spring 集成的TTL却不是。
docker run -p 6379:6379 -d redis:7.0.12 --requirepass "mypass"
docker run -e POSTGRES_USER=localtest -e POSTGRES_PASSWORD=localtest -e POSTGRES_DB=orders -p 5432:5432 -d postgres:15.3
# start this docker container before running the above junit test
lock.registry.name=redisson
# change this line to redis / jdbc / redisson then run test
在spring集成的redis/jdbc模式下运行测试时,线程2经过ttl后也拿不到锁。
在redisson模式下运行测试时,线程2可以在租约时间过去后获得锁,我认为这在概念上更有意义。
并不是想说哪个更好,只是出于好奇,与Redisson的租约时间相比,Spring Integration的ttl工作原理是否有特殊原因?
那个
RLock.tryLock()
的 Javadoc 是错误的,它使用 leaseTime
来解释 waitTime
。我相信可能还有其他不同的方法来实现分布式锁。
如果你查看 Spring Integration 的
RedisLockRegistry
,你会发现它与 JdbcLockRegistry
类似,并且有一个带有 ReentrantLock
的本地守卫。因此,同一进程内的所有交互都遵循标准 Java Lock
算法。正如我在该问题中向您解释的那样:TTL
实际上是为了在分布式环境中解除死锁。另一方面,您无法预测进程将持有锁多长时间,因此由于某些原因而过早释放锁可能会导致系统中您期望受到锁保护的不一致。不确定您进行此锁定练习的目标是什么,但我认为您的问题属于 leaseTime
类别,必须从 SO 中删除。