Skip to content

Commit 54f258a

Browse files
kistlersspring-builds
authored andcommitted
GH-10546: Fix RedisLockRegistry for cluster
Fixes: #10546 * pass `unLockChannelKey` as `ARGV[2]` instead of `KEYS[2]` to make this unlock script compatible with both Redis cluster and AWS Elastic valkey cluster * add documentation for AWS ElastiCache Valkey Support in `RedisLockRegistry` Signed-off-by: Severin Kistler <[email protected]> # Conflicts: # spring-integration-redis/src/main/java/org/springframework/integration/redis/util/RedisLockRegistry.java # src/reference/antora/modules/ROOT/pages/redis.adoc (cherry picked from commit c71d5b3)
1 parent 95a5114 commit 54f258a

File tree

2 files changed

+26
-3
lines changed

2 files changed

+26
-3
lines changed

spring-integration-redis/src/main/java/org/springframework/integration/redis/util/RedisLockRegistry.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,7 @@ private final class RedisPubSubLock extends RedisLock {
668668
private static final String UNLINK_UNLOCK_SCRIPT = """
669669
local lockClientId = redis.call('GET', KEYS[1])
670670
if (lockClientId == ARGV[1] and redis.call('UNLINK', KEYS[1]) == 1) then
671-
redis.call('PUBLISH', KEYS[2], KEYS[1])
671+
redis.call('PUBLISH', ARGV[2], KEYS[1])
672672
return true
673673
end
674674
return false
@@ -711,8 +711,8 @@ protected boolean removeLockKeyInnerDelete() {
711711
private boolean removeLockKeyWithScript(RedisScript<Boolean> redisScript) {
712712
String unLockChannelKeyToUse = RedisLockRegistry.this.unLockChannelKey + ":" + this.lockKey;
713713
return Boolean.TRUE.equals(RedisLockRegistry.this.redisTemplate.execute(
714-
redisScript, List.of(this.lockKey, unLockChannelKeyToUse),
715-
RedisLockRegistry.this.clientId));
714+
redisScript, List.of(this.lockKey),
715+
RedisLockRegistry.this.clientId, unLockChannelKey));
716716
}
717717

718718
private boolean subscribeLock(long time) throws ExecutionException, InterruptedException {

src/reference/antora/modules/ROOT/pages/redis.adoc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -860,3 +860,26 @@ Starting with version 6.4, instead of throwing `IllegalStateException`, the `Red
860860

861861
Starting with version 6.4, a `RedisLockRegistry.setRenewalTaskScheduler()` is added to configure the scheduler for periodic renewal of locks.
862862
When it is set, the lock will be automatically renewed every `1/3` of the expiration time after the lock is successfully acquired, until unlocked or the redis key is removed.
863+
864+
[[elasticache-valkey-cluster]]
865+
=== AWS ElastiCache for Valkey Support in cluster mode
866+
867+
Starting with version 6.4.9/6.5.4/7.0.0, `RedisLockRegistry` supports AWS Elasticache for Valkey in cluster mode.
868+
In this version of valkey (a redis drop-in replacement), all PubSub operations (`PUBLISH`, `SUBSCRIBE`, etc.) use their sharded variants (`SPUBLISH`, `SSUBSCRIBE`, etc.) internally.
869+
If you are observing errors in the form of:
870+
871+
[source]
872+
----
873+
Caused by: io.lettuce.core.RedisCommandExecutionException: ERR Script attempted to access keys that do not hash to the same slot script: b2dedc0ab01c17f9f20e3e6ddb62dcb6afbed0bd, on @user_script:3.
874+
----
875+
876+
in the `unlock` step of the `RedisLockRegistry`, you have to supply a lock key that includes a hash tag `{...}` to ensure all operations in the `unlock` script are hashed to the same cluster slot/shard, e.g.:
877+
878+
[source]
879+
----
880+
RedisLockRegistry lockRegistry = new RedisLockRegistry("my-lock-key{choose_your_tag}");
881+
882+
lockRegistry.lock();
883+
# critical section
884+
lockRegistry.unlock();
885+
----

0 commit comments

Comments
 (0)