zoukankan      html  css  js  c++  java
  • springboot redis 用RedisTemplate执行lua脚本报错:@user_script:1: ERR value is not an integer or out of range

    代码如下:

    /**
    * 获取分布式锁
    *
    * @param lockKey 锁
    * @param requestId 请求标识
    * @param expireTime 单位秒|你认为此方法需要多少时间,设置一个最长时间,此时间必须大于需要调用锁的业务方法逻辑的最大时间,否则锁会冲突
    * @param waitTimeout 单位毫秒|如果拿不到锁,那么休眠,然后反反复复重试,直到拿到锁为止
    * demo redisService.getLock("lock", uuid, 10, 1500) 调用方法的业务逻辑最多需要1秒执行完成,1500毫秒一直等待(默认休眠500毫秒一次轮回)线程不执行,等到1500毫秒到了,才执行完整个方法
    * @return 是否获取成功
    */
    public boolean getLock(String lockKey, String requestId, long expireTime, long waitTimeout) {
    // 当前时间
    long nanoTime = System.nanoTime();
    try {
    String script = "if redis.call('setnx',KEYS[1],ARGV[1]) == 1 then return redis.call('expire',KEYS[1],ARGV[2]) else return 0 end";
    logger.debug("开始获取分布式锁-key[{}]", lockKey);
    int count = 0;
    List<String> lockKeyList = Collections.singletonList(lockKey);
    do {
    RedisScript<Long> redisScript = new DefaultRedisScript<>(script, Long.class);
    logger.debug("尝试获取分布式锁-key[{}]requestId[{}]count[{}]", lockKey, requestId, count);

    Object result = redisTemplate.execute(redisScript, lockKeyList, requestId, expireTime + "");
    Long SUCCESS = 1L;
    if (SUCCESS.equals(result)) {
    logger.debug("尝试获取分布式锁-key[{}]成功", lockKey);
    return true;
    }
    //休眠200毫秒
    Thread.sleep(200L);
    count++;
    } while ((System.nanoTime() - nanoTime) < TimeUnit.MILLISECONDS.toNanos(waitTimeout));
    } catch (Exception e) {
    e.printStackTrace();
    logger.error("尝试获取分布式锁-key[{}]异常", lockKey);
    logger.error(e.getMessage(), e);
    }
    return false;
    }

    /**
    * 释放锁
    *
    * @param lockKey 锁
    * @param value 请求标识
    * @return 是否释放成功
    */
    public boolean releaseLock(String lockKey, String value) {
    String script = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";
    DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>(script, Long.class);
    Object result = redisTemplate.execute(redisScript, Collections.singletonList(lockKey), value);
    Long SUCCESS = 1L;
    if (SUCCESS.equals(result)) {
    logger.debug("释放锁成功key[{}]value[{}]", lockKey, value);
    return true;
    }
    return false;
    }

    错误如下:

    org.springframework.data.redis.RedisSystemException: Error in execution; nested exception is io.lettuce.core.RedisCommandExecutionException: ERR Error running script (call to f_dce7e03aa7a8103dc00e40ebb8e287d7d499bd3a): @user_script:1: ERR value is not an integer or out of range
    at org.springframework.data.redis.connection.lettuce.LettuceExceptionConverter.convert(LettuceExceptionConverter.java:54)
    at org.springframework.data.redis.connection.lettuce.LettuceExceptionConverter.convert(LettuceExceptionConverter.java:52)
    at org.springframework.data.redis.connection.lettuce.LettuceExceptionConverter.convert(LettuceExceptionConverter.java:41)
    at org.springframework.data.redis.PassThroughExceptionTranslationStrategy.translate(PassThroughExceptionTranslationStrategy.java:44)
    at org.springframework.data.redis.FallbackExceptionTranslationStrategy.translate(FallbackExceptionTranslationStrategy.java:42)
    at org.springframework.data.redis.connection.lettuce.LettuceConnection.convertLettuceAccessException(LettuceConnection.java:268)
    at org.springframework.data.redis.connection.lettuce.LettuceScriptingCommands.convertLettuceAccessException(LettuceScriptingCommands.java:236)
    at org.springframework.data.redis.connection.lettuce.LettuceScriptingCommands.evalSha(LettuceScriptingCommands.java:195)
    at org.springframework.data.redis.connection.DefaultedRedisConnection.evalSha(DefaultedRedisConnection.java:1318)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.data.redis.core.CloseSuppressingInvocationHandler.invoke(CloseSuppressingInvocationHandler.java:61)
    at com.sun.proxy.$Proxy148.evalSha(Unknown Source)
    at org.springframework.data.redis.core.script.DefaultScriptExecutor.eval(DefaultScriptExecutor.java:77)
    at org.springframework.data.redis.core.script.DefaultScriptExecutor.lambda$execute$0(DefaultScriptExecutor.java:68)
    at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:224)
    at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:184)
    at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:171)
    at org.springframework.data.redis.core.script.DefaultScriptExecutor.execute(DefaultScriptExecutor.java:58)
    at org.springframework.data.redis.core.script.DefaultScriptExecutor.execute(DefaultScriptExecutor.java:52)
    at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:346)

    分析,可能是值的类型不对或长度太长了?

    1、修改value 的长度以后错误仍然存在。

    2、在分析是不是返回值的类型不对,改为Integer后,又抛出另一个错误

    org.springframework.data.redis.RedisSystemException: Redis exception; nested exception is io.lettuce.core.RedisException: java.lang.IllegalStateException
    at org.springframework.data.redis.connection.lettuce.LettuceExceptionConverter.convert(LettuceExceptionConverter.java:74)
    at org.springframework.data.redis.connection.lettuce.LettuceExceptionConverter.convert(LettuceExceptionConverter.java:41)
    at org.springframework.data.redis.PassThroughExceptionTranslationStrategy.translate(PassThroughExceptionTranslationStrategy.java:44)
    at org.springframework.data.redis.FallbackExceptionTranslationStrategy.translate(FallbackExceptionTranslationStrategy.java:42)
    at org.springframework.data.redis.connection.lettuce.LettuceConnection.convertLettuceAccessException(LettuceConnection.java:268)
    at org.springframework.data.redis.connection.lettuce.LettuceScriptingCommands.convertLettuceAccessException(LettuceScriptingCommands.java:236)
    at org.springframework.data.redis.connection.lettuce.LettuceScriptingCommands.evalSha(LettuceScriptingCommands.java:195)
    at org.springframework.data.redis.connection.DefaultedRedisConnection.evalSha(DefaultedRedisConnection.java:1318)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.data.redis.core.CloseSuppressingInvocationHandler.invoke(CloseSuppressingInvocationHandler.java:61)
    at com.sun.proxy.$Proxy148.evalSha(Unknown Source)
    at org.springframework.data.redis.core.script.DefaultScriptExecutor.eval(DefaultScriptExecutor.java:77)
    at org.springframework.data.redis.core.script.DefaultScriptExecutor.lambda$execute$0(DefaultScriptExecutor.java:68)
    at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:224)
    at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:184)
    at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:171)
    at org.springframework.data.redis.core.script.DefaultScriptExecutor.execute(DefaultScriptExecutor.java:58)
    at org.springframework.data.redis.core.script.DefaultScriptExecutor.execute(DefaultScriptExecutor.java:52)
    at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:346)

    3、改为String类型以后错误仍然存在。

    最后百度可能是值序列化的问题,

    4、修改RedisConfig

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
    RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
    redisTemplate.setConnectionFactory(factory);
    return redisTemplate;
    }
    改为:
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
    RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
    redisTemplate.setConnectionFactory(factory);
      RedisSerializer stringRedisSerializer = new StringRedisSerializer();
      redisTemplate.setKeySerializer(stringRedisSerializer);
    redisTemplate.setValueSerializer(stringRedisSerializer);
    redisTemplate.setHashKeySerializer(stringRedisSerializer);
    redisTemplate.setHashValueSerializer(stringRedisSerializer);

    return redisTemplate;
    }

      嘿嘿,果然可以了,就是redis 值序列化的问题, 默认的是JdkRedisSeerializer,改为StringRedisSerializer 就好了

  • 相关阅读:
    Sublime2 Text编辑器使用技巧
    PHP实现一个简单url路由功能
    jQuery extend函数详解
    Memcached常用命令及使用说明
    根据一张表去更新另一张表
    npm ERR! Error: socket hang up
    Oracle中group by 1,order by 1的理解
    Oracle中的next_day(date,char)函数的理解
    WebService入门
    OCupload、POI、PinYin4j的简单入门
  • 原文地址:https://www.cnblogs.com/fancy2041/p/13213358.html
Copyright © 2011-2022 走看看