Search code examples
javaspring-integrationredissondistributed-lockspring-integration-distributed-lock

Spring Integration Distributed Locks: conceptual consistency of TTL as compared to Redisson's lease time


This is a follow up question of: https://github.com/spring-projects/spring-integration/issues/8687

As discussed in the above link, Spring Integration Distributed Lock's concept of TTL is meant for cross-process only, not for threads in the same process.

Later I have tried Redisson, it has a concept of lease time in its 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;

https://github.com/redisson/redisson/blob/c2c00a07c279d55d627717fbb290426e19744a65/redisson/src/main/java/org/redisson/api/RLock.java#L55

I think these 2 concepts TTL and lease time are similar (correct me if I am wrong).

But lease time of Redisson works in a consistent way for both cross-process and threads in same process, while TTL of spring integration does not.

The following junit test can reproduce what I mean: https://github.com/cuipengfei/Spikes/blob/22a9896137dd62bda5f030f5a3d33c67fba67310/jpa/spring-jdbc-distributed-lock-issue/src/test/java/com/github/spring/example/LockTest.java#L38C9-L49

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

and change mode to compare: https://github.com/cuipengfei/Spikes/blob/master/jpa/spring-jdbc-distributed-lock-issue/src/test/resources/application.properties#L16-L17

lock.registry.name=redisson
# change this line to redis / jdbc / redisson then run test

When running the test in Redis/jdbc mode of spring integration, thread 2 can not get the lock even after TTL.

While running the test in Redisson mode, thread 2 can get the lock after lease time has past, which I think makes more sense conceptually.

What are the design considerations behind TTL/lease time that led to different choices?


Solution

  • enter image description here

    ↑ This is my interpretation.

    In the case of Spring Integration, Bob is denied the lock because it values the fact that Alice might still be using it more than the fact that more than 20 seconds have passed. This reduces the chance of interrupting Alice's work.

    In contrast, Redisson grants the lock to Bob, prioritizing the expiration of the lock duration over the possibility that Alice is still using it. This provides more consistent behavior for lease time.