Skip to content

RedisTemplateSimpleDistributedLock 在trylock和unlock 中针对Key的序列化方式不一致导致无法unlock的问题。 #3631

Open
@dylan-hh

Description

@dylan-hh

简要描述

RedisTemplateSimpleDistributedLock 在trylock和unlock 中针对Key的序列化方式不一致导致无法正确释放锁的问题。

模块版本情况

  • WxJava 模块名: weixin-java-cp
  • WxJava 版本号: 4.7.6.B

详细描述

在使用Redis的分布式锁的场景下,WxCpRedisTemplateConfigImpl类需要注入StringRedisTemplate类,当我的StringRedisTemplate添加了自定义的Key序列化处理的时候, 比如统一对Key加上前缀 System: ,会导致分布式锁无法正常释放。
RedisTemplateSimpleDistributedLock类中的trylock方法如下

  @Override
  public boolean tryLock() {
    String value = valueThreadLocal.get();
    if (value == null || value.isEmpty()) {
      value = UUID.randomUUID().toString();
      valueThreadLocal.set(value);
    }
    final byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
    final byte[] valueBytes = value.getBytes(StandardCharsets.UTF_8);
    List<Object> redisResults = redisTemplate.executePipelined((RedisCallback<String>) connection -> {
      connection.set(keyBytes, valueBytes, Expiration.milliseconds(leaseMilliseconds), RedisStringCommands.SetOption.SET_IF_ABSENT);
      connection.get(keyBytes);
      return null;
    });
    Object currentLockSecret = redisResults.size() > 1 ? redisResults.get(1) : redisResults.get(0);
    return currentLockSecret != null && currentLockSecret.toString().equals(value);
  }

如上设置key使用的是Redis的底层 RedisConnection类直接处理的,会导致StringRedisTemplate类的Key的前缀无法加上

比如Key为 wechat_cp_lock:ww948:1000010:accessToken 无法加上System: 为 System:wechatt_cp_lock:ww948****:1000010:accessToken

但是在unlock的代码中:

@Override
public void unlock() {
  if (valueThreadLocal.get() != null) {
    // 提示: 必须指定returnType, 类型: 此处必须为Long, 不能是Integer
    RedisScript<Long> script = new DefaultRedisScript<>("if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end", Long.class);
    redisTemplate.execute(script, Collections.singletonList(key), valueThreadLocal.get());
    valueThreadLocal.remove();
  }
}

如上使用的却是redisTemplate 设置处理redis的Key的导致。

从而导致的问题就是 trylock实际设置的Key是 wechatt_cp_lock:ww948:1000010:accessToken

但是释放的时候 所使用的Key是System:wechatt_cp_lock:ww948:1000010:accessToken

导致无法释放的问题。

日志

如果日志不多,直接使用md代码引用格式贴在此处,否则如果太长,请将日志放在 [pastebin](https://paste.ubuntu.com/) 或者其他地方,然后将其url地址贴在这里

日志请写于此处

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions