Redis 执行 Lua 脚本抛出 StatusOutput does not support set(long) 异常

Redis Lua Spring Boot 大约 5287 字

异常信息

Caused by: org.springframework.data.redis.RedisSystemException: Unknown redis exception; nested exception is java.lang.IllegalStateException: io.lettuce.core.output.StatusOutput does not support set(long)
    at org.springframework.data.redis.FallbackExceptionTranslationStrategy.getFallback(FallbackExceptionTranslationStrategy.java:53) ~[spring-data-redis-2.4.5.jar:2.4.5]
    at org.springframework.data.redis.FallbackExceptionTranslationStrategy.translate(FallbackExceptionTranslationStrategy.java:43) ~[spring-data-redis-2.4.5.jar:2.4.5]
    at org.springframework.data.redis.connection.lettuce.LettuceConnection.convertLettuceAccessException(LettuceConnection.java:272) ~[spring-data-redis-2.4.5.jar:2.4.5]
    at org.springframework.data.redis.connection.lettuce.LettuceScriptingCommands.convertLettuceAccessException(LettuceScriptingCommands.java:236) ~[spring-data-redis-2.4.5.jar:2.4.5]
    at org.springframework.data.redis.connection.lettuce.LettuceScriptingCommands.evalSha(LettuceScriptingCommands.java:195) ~[spring-data-redis-2.4.5.jar:2.4.5]
    at org.springframework.data.redis.connection.DefaultedRedisConnection.evalSha(DefaultedRedisConnection.java:1530) ~[spring-data-redis-2.4.5.jar:2.4.5]
    at org.springframework.data.redis.connection.DefaultStringRedisConnection.evalSha(DefaultStringRedisConnection.java:1776) ~[spring-data-redis-2.4.5.jar:2.4.5]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_151]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_151]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_151]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_151]
    at org.springframework.data.redis.core.CloseSuppressingInvocationHandler.invoke(CloseSuppressingInvocationHandler.java:61) ~[spring-data-redis-2.4.5.jar:2.4.5]
    at com.sun.proxy.$Proxy67.evalSha(Unknown Source) ~[na:na]
    at org.springframework.data.redis.core.script.DefaultScriptExecutor.eval(DefaultScriptExecutor.java:77) ~[spring-data-redis-2.4.5.jar:2.4.5]
    at org.springframework.data.redis.core.script.DefaultScriptExecutor.lambda$execute$0(DefaultScriptExecutor.java:68) ~[spring-data-redis-2.4.5.jar:2.4.5]
    at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:222) ~[spring-data-redis-2.4.5.jar:2.4.5]
    at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:189) ~[spring-data-redis-2.4.5.jar:2.4.5]
    at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:176) ~[spring-data-redis-2.4.5.jar:2.4.5]
    at org.springframework.data.redis.core.script.DefaultScriptExecutor.execute(DefaultScriptExecutor.java:58) ~[spring-data-redis-2.4.5.jar:2.4.5]
    at org.springframework.data.redis.core.script.DefaultScriptExecutor.execute(DefaultScriptExecutor.java:52) ~[spring-data-redis-2.4.5.jar:2.4.5]
    at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:343) ~[spring-data-redis-2.4.5.jar:2.4.5]
    at com.example.cache.CacheApplication.run(CacheApplication.java:29) [classes/:na]
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:795) [spring-boot-2.4.3.jar:2.4.3]
    ... 5 common frames omitted

异常代码

private static final String UNLOCK_LUA_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
private static final Integer UNLOCK_SUCCESS_RESULT = 1;

public boolean unlock(String key, String value) {
    Integer result = stringRedisTemplate.execute(RedisScript.of(UNLOCK_LUA_SCRIPT, Integer.class), Collections.singletonList(key), value);
    return UNLOCK_SUCCESS_RESULT.equals(result);
}

原因

Redis中的integer对应Java中的Long

public enum ReturnType {

    /**
     * Returned as Boolean
     */
    BOOLEAN,

    /**
     * Returned as {@link Long}
     */
    INTEGER,

    /**
     * Returned as {@link List<Object>}
     */
    MULTI,

    /**
     * Returned as {@literal byte[]}
     */
    STATUS,

    /**
     * Returned as {@literal byte[]}
     */
    VALUE;

    /**
     * @param javaType can be {@literal null} which translates to {@link ReturnType#STATUS}.
     * @return never {@literal null}.
     */
    public static ReturnType fromJavaType(@Nullable Class<?> javaType) {

        if (javaType == null) {
            return ReturnType.STATUS;
        }

        if (ClassUtils.isAssignable(List.class, javaType)) {
            return ReturnType.MULTI;
        }

        if (ClassUtils.isAssignable(Boolean.class, javaType)) {
            return ReturnType.BOOLEAN;
        }

        if (ClassUtils.isAssignable(Long.class, javaType)) {
            return ReturnType.INTEGER;
        }

        return ReturnType.VALUE;
    }
}

修改代码

Integer改为Long

private static final String UNLOCK_LUA_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
private static final Long UNLOCK_SUCCESS_RESULT = 1L;

public boolean unlock(String key, String value) {
    Long result = stringRedisTemplate.execute(RedisScript.of(UNLOCK_LUA_SCRIPT, Long.class), Collections.singletonList(key), value);
    return UNLOCK_SUCCESS_RESULT.equals(result);
}
阅读 1320 · 发布于 2021-03-18

————        END        ————

扫描下方二维码关注公众号和小程序↓↓↓

扫描二维码关注我
昵称:
随便看看 换一批