Skip to content

Commit 1e71d19

Browse files
authored
Drop switch from Redis unlink to delete
Redis 3, where no `UNLINK` yet, is not maintained since 2018 Fix `RedisLockRegistry` and `RedisMessageStore` to use only `UNLIK` for entries removal. The `DEL` fallback does not make sense with modern Redis versions. More over, such an algorithm was premature and felt back to `DEL` permanently for any errors. Signed-off-by: Michal Domagala <[email protected]>
1 parent 964dd9f commit 1e71d19

File tree

2 files changed

+11
-120
lines changed

2 files changed

+11
-120
lines changed

spring-integration-redis/src/main/java/org/springframework/integration/redis/store/RedisMessageStore.java

Lines changed: 3 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
* @author Oleg Zhurakousky
3838
* @author Gary Russell
3939
* @author Artem Bilan
40+
* @author Michal Domagala
4041
*
4142
* @since 2.1
4243
*/
@@ -48,8 +49,6 @@ public class RedisMessageStore extends AbstractKeyValueMessageStore implements B
4849

4950
private boolean valueSerializerSet;
5051

51-
private volatile boolean unlinkAvailable = true;
52-
5352
/**
5453
* Construct {@link RedisMessageStore} based on the provided
5554
* {@link RedisConnectionFactory} and default empty prefix.
@@ -133,48 +132,14 @@ protected Object doRemove(Object id) {
133132
Assert.notNull(id, ID_MUST_NOT_BE_NULL);
134133
Object removedObject = this.doRetrieve(id);
135134
if (removedObject != null) {
136-
if (this.unlinkAvailable) {
137-
try {
138-
this.redisTemplate.unlink(id);
139-
}
140-
catch (Exception ex) {
141-
unlinkUnavailable(ex);
142-
this.redisTemplate.delete(id);
143-
}
144-
}
145-
else {
146-
this.redisTemplate.delete(id);
147-
}
135+
this.redisTemplate.unlink(id);
148136
}
149137
return removedObject;
150138
}
151139

152-
private void unlinkUnavailable(Exception ex) {
153-
if (logger.isDebugEnabled()) {
154-
logger.debug("The UNLINK command has failed (not supported on the Redis server?); " +
155-
"falling back to the regular DELETE command", ex);
156-
}
157-
else {
158-
logger.warn("The UNLINK command has failed (not supported on the Redis server?); " +
159-
"falling back to the regular DELETE command: " + ex.getMessage());
160-
}
161-
this.unlinkAvailable = false;
162-
}
163-
164140
@Override
165141
protected void doRemoveAll(Collection<Object> ids) {
166-
if (this.unlinkAvailable) {
167-
try {
168-
this.redisTemplate.unlink(ids);
169-
}
170-
catch (Exception ex) {
171-
unlinkUnavailable(ex);
172-
this.redisTemplate.delete(ids);
173-
}
174-
}
175-
else {
176-
this.redisTemplate.delete(ids);
177-
}
142+
this.redisTemplate.unlink(ids);
178143
}
179144

180145
@Override

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

Lines changed: 8 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
* @author Roman Zabaluev
9797
* @author Alex Peelman
9898
* @author Youbin Wu
99+
* @author Michal Domagala
99100
*
100101
* @since 4.0
101102
*
@@ -158,8 +159,6 @@ protected boolean removeEldestEntry(Entry<String, RedisLock> eldest) {
158159
*/
159160
private boolean executorExplicitlySet;
160161

161-
private volatile boolean unlinkAvailable = true;
162-
163162
private volatile boolean isRunningRedisMessageListenerContainer = false;
164163

165164
/**
@@ -436,11 +435,6 @@ protected abstract boolean tryRedisLockInner(long time, long expireAfter)
436435
*/
437436
protected abstract boolean removeLockKeyInnerUnlink();
438437

439-
/**
440-
* Unlock the lock using the delete method in redis.
441-
*/
442-
protected abstract boolean removeLockKeyInnerDelete();
443-
444438
@Override
445439
public final void lock() {
446440
this.lock(RedisLockRegistry.this.expireAfter);
@@ -583,41 +577,15 @@ public final void unlock() {
583577
}
584578

585579
private void removeLockKey() {
586-
if (RedisLockRegistry.this.unlinkAvailable) {
587-
Boolean unlinkResult = null;
588-
try {
589-
// Attempt to UNLINK the lock key; an exception indicates lack of UNLINK support
590-
unlinkResult = removeLockKeyInnerUnlink();
591-
}
592-
catch (Exception ex) {
593-
RedisLockRegistry.this.unlinkAvailable = false;
594-
if (LOGGER.isDebugEnabled()) {
595-
LOGGER.debug("The UNLINK command has failed (not supported on the Redis server?); " +
596-
"falling back to the regular DELETE command", ex);
597-
}
598-
else {
599-
LOGGER.warn("The UNLINK command has failed (not supported on the Redis server?); " +
600-
"falling back to the regular DELETE command: " + ex.getMessage());
601-
}
602-
}
603-
604-
if (Boolean.TRUE.equals(unlinkResult)) {
605-
// Lock key successfully unlinked
606-
stopRenew();
607-
return;
608-
}
609-
else if (Boolean.FALSE.equals(unlinkResult)) {
610-
throw new ConcurrentModificationException("Lock was released in the store due to expiration. " +
611-
"The integrity of data protected by this lock may have been compromised.");
612-
}
580+
boolean unlinkResult = removeLockKeyInnerUnlink();
581+
if (unlinkResult) {
582+
// Lock key successfully removed
583+
stopRenew();
613584
}
614-
if (!removeLockKeyInnerDelete()) {
585+
else {
615586
throw new ConcurrentModificationException("Lock was released in the store due to expiration. " +
616587
"The integrity of data protected by this lock may have been compromised.");
617588
}
618-
else {
619-
stopRenew();
620-
}
621589
}
622590

623591
protected final boolean renew(long expireAfter) {
@@ -705,21 +673,9 @@ private final class RedisPubSubLock extends RedisLock {
705673
return false
706674
""";
707675

708-
private static final String DELETE_UNLOCK_SCRIPT = """
709-
local lockClientId = redis.call('GET', KEYS[1])
710-
if (lockClientId == ARGV[1] and redis.call('DEL', KEYS[1]) == 1) then
711-
redis.call('PUBLISH', ARGV[2], KEYS[1])
712-
return true
713-
end
714-
return false
715-
""";
716-
717676
private static final RedisScript<Boolean>
718677
UNLINK_UNLOCK_REDIS_SCRIPT = new DefaultRedisScript<>(UNLINK_UNLOCK_SCRIPT, Boolean.class);
719678

720-
private static final RedisScript<Boolean>
721-
DELETE_UNLOCK_REDIS_SCRIPT = new DefaultRedisScript<>(DELETE_UNLOCK_SCRIPT, Boolean.class);
722-
723679
private RedisPubSubLock(String path) {
724680
super(path);
725681
}
@@ -732,17 +688,8 @@ protected boolean tryRedisLockInner(long time, long expireAfter)
732688

733689
@Override
734690
protected boolean removeLockKeyInnerUnlink() {
735-
return removeLockKeyWithScript(UNLINK_UNLOCK_REDIS_SCRIPT);
736-
}
737-
738-
@Override
739-
protected boolean removeLockKeyInnerDelete() {
740-
return removeLockKeyWithScript(DELETE_UNLOCK_REDIS_SCRIPT);
741-
}
742-
743-
private boolean removeLockKeyWithScript(RedisScript<Boolean> redisScript) {
744691
return Boolean.TRUE.equals(RedisLockRegistry.this.redisTemplate.execute(
745-
redisScript, Collections.singletonList(this.lockKey),
692+
UNLINK_UNLOCK_REDIS_SCRIPT, Collections.singletonList(this.lockKey),
746693
RedisLockRegistry.this.clientId, RedisLockRegistry.this.unLockChannelKey));
747694
}
748695

@@ -854,21 +801,9 @@ private final class RedisSpinLock extends RedisLock {
854801
return false
855802
""";
856803

857-
private static final String DELETE_UNLOCK_SCRIPT = """
858-
local lockClientId = redis.call('GET', KEYS[1])
859-
if lockClientId == ARGV[1] then
860-
redis.call('DEL', KEYS[1])
861-
return true
862-
end
863-
return false
864-
""";
865-
866804
private static final RedisScript<Boolean>
867805
UNLINK_UNLOCK_REDIS_SCRIPT = new DefaultRedisScript<>(UNLINK_UNLOCK_SCRIPT, Boolean.class);
868806

869-
private static final RedisScript<Boolean>
870-
DELETE_UNLOCK_REDIS_SCRIPT = new DefaultRedisScript<>(DELETE_UNLOCK_SCRIPT, Boolean.class);
871-
872807
private RedisSpinLock(String path) {
873808
super(path);
874809
}
@@ -894,17 +829,8 @@ protected boolean tryRedisLockInner(long time, long expireAfter) throws Interrup
894829

895830
@Override
896831
protected boolean removeLockKeyInnerUnlink() {
897-
return removeLockKeyWithScript(UNLINK_UNLOCK_REDIS_SCRIPT);
898-
}
899-
900-
@Override
901-
protected boolean removeLockKeyInnerDelete() {
902-
return removeLockKeyWithScript(DELETE_UNLOCK_REDIS_SCRIPT);
903-
}
904-
905-
private boolean removeLockKeyWithScript(RedisScript<Boolean> redisScript) {
906832
return Boolean.TRUE.equals(RedisLockRegistry.this.redisTemplate.execute(
907-
redisScript, Collections.singletonList(this.lockKey),
833+
UNLINK_UNLOCK_REDIS_SCRIPT, Collections.singletonList(this.lockKey),
908834
RedisLockRegistry.this.clientId));
909835
}
910836

0 commit comments

Comments
 (0)