RedisLockRegistry: Don't expire not acquired lock
Fix race condition, when methods `RedisLockRegistry#expireUnusedOlderThan` and `RedisLockRegistry#obtain` are executed successively. It's possible to delete the lock from `RedisLockRegistry#expireUnusedOlderThan` method, when lock is created but is not acquired (`RedisLock#getLockedAt = 0`) It can lead to the situation, when `RedisLockRegistry#obtain` returns multiple locks with the same redis-key, which shouldn't happen at all. * Skip locks from expiration when their `lockedAt == 0` - new, not acquired yet. **Cherry-pick to `6.0.x` & `5.5.x`**
This commit is contained in:
@@ -81,6 +81,7 @@ import org.springframework.util.ReflectionUtils;
|
||||
* @author Artem Bilan
|
||||
* @author Vedran Pavic
|
||||
* @author Unseok Kim
|
||||
* @author Anton Gabov
|
||||
*
|
||||
* @since 4.0
|
||||
*
|
||||
@@ -235,7 +236,11 @@ public final class RedisLockRegistry implements ExpirableLockRegistry, Disposabl
|
||||
this.locks.entrySet()
|
||||
.removeIf(entry -> {
|
||||
RedisLock lock = entry.getValue();
|
||||
return now - lock.getLockedAt() > age && !lock.isAcquiredInThisProcess();
|
||||
long lockedAt = lock.getLockedAt();
|
||||
return now - lockedAt > age
|
||||
// 'lockedAt = 0' means that the lock is still not acquired!
|
||||
&& lockedAt > 0
|
||||
&& !lock.isAcquiredInThisProcess();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user