1
0
mirror of synced 2025-12-17 13:08:02 +08:00

🐛 #3631 修复tryLockunlock中针对Key的序列化方式不一致导致无法unlock的问题

This commit is contained in:
imyzt
2025-09-23 00:24:02 +08:00
committed by GitHub
parent c8d84da2ab
commit 213cf6fd67
2 changed files with 32 additions and 3 deletions

View File

@@ -7,10 +7,12 @@ import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript; import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript; import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.data.redis.core.types.Expiration; import org.springframework.data.redis.core.types.Expiration;
import org.springframework.data.redis.serializer.RedisSerializer;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Condition;
@@ -70,8 +72,10 @@ public class RedisTemplateSimpleDistributedLock implements Lock {
value = UUID.randomUUID().toString(); value = UUID.randomUUID().toString();
valueThreadLocal.set(value); valueThreadLocal.set(value);
} }
final byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8); RedisSerializer<String> keySerializer = (RedisSerializer<String>) redisTemplate.getKeySerializer();
final byte[] valueBytes = value.getBytes(StandardCharsets.UTF_8); RedisSerializer<String> valueSerializer = (RedisSerializer<String>) redisTemplate.getValueSerializer();
final byte[] keyBytes = Objects.requireNonNull(keySerializer.serialize(key));
final byte[] valueBytes = Objects.requireNonNull(valueSerializer.serialize(value));
List<Object> redisResults = redisTemplate.executePipelined((RedisCallback<String>) connection -> { List<Object> redisResults = redisTemplate.executePipelined((RedisCallback<String>) connection -> {
connection.set(keyBytes, valueBytes, Expiration.milliseconds(leaseMilliseconds), RedisStringCommands.SetOption.SET_IF_ABSENT); connection.set(keyBytes, valueBytes, Expiration.milliseconds(leaseMilliseconds), RedisStringCommands.SetOption.SET_IF_ABSENT);
connection.get(keyBytes); connection.get(keyBytes);

View File

@@ -1,8 +1,10 @@
package me.chanjar.weixin.common.util.locks; package me.chanjar.weixin.common.util.locks;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.testng.annotations.BeforeTest; import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@@ -13,9 +15,10 @@ import java.util.concurrent.atomic.AtomicInteger;
import static org.testng.Assert.*; import static org.testng.Assert.*;
@Slf4j @Slf4j
@Test(enabled = false) @Test(enabled = true)
public class RedisTemplateSimpleDistributedLockTest { public class RedisTemplateSimpleDistributedLockTest {
private static final String KEY_PREFIX = "System:";
RedisTemplateSimpleDistributedLock redisLock; RedisTemplateSimpleDistributedLock redisLock;
StringRedisTemplate redisTemplate; StringRedisTemplate redisTemplate;
@@ -29,6 +32,28 @@ public class RedisTemplateSimpleDistributedLockTest {
connectionFactory.setPort(6379); connectionFactory.setPort(6379);
connectionFactory.afterPropertiesSet(); connectionFactory.afterPropertiesSet();
StringRedisTemplate redisTemplate = new StringRedisTemplate(connectionFactory); StringRedisTemplate redisTemplate = new StringRedisTemplate(connectionFactory);
// 自定义序列化器,为 key 自动加前缀
redisTemplate.setKeySerializer(new StringRedisSerializer() {
@NotNull
@Override
public byte[] serialize(String string) {
if (string == null) {
return super.serialize(null);
}
// 添加前缀
return super.serialize(KEY_PREFIX + string);
}
@NotNull
@Override
public String deserialize(byte[] bytes) {
String key = super.deserialize(bytes);
if (key.startsWith(KEY_PREFIX)) {
return key.substring(KEY_PREFIX.length());
}
return key;
}
});
this.redisTemplate = redisTemplate; this.redisTemplate = redisTemplate;
this.redisLock = new RedisTemplateSimpleDistributedLock(redisTemplate, 60000); this.redisLock = new RedisTemplateSimpleDistributedLock(redisTemplate, 60000);
this.lockCurrentExecuteCounter = new AtomicInteger(0); this.lockCurrentExecuteCounter = new AtomicInteger(0);