spring redis运行脚本:如何传递到期时间值

时间:2016-11-10 11:55:50

标签: spring-boot lua redis spring-data spring-data-redis

我使用lua脚本:

local lock = redis.call('get', KEYS[1])
if not lock then    
    return redis.call('SETEX', KEYS[1], ARGV[1] ,ARGV[2] );
end
return false

从spring boot应用程序我用脚本

来调用redis
DefaultRedisScript<Boolean> redisScript = new
DefaultRedisScript<Boolean>();
redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("checkandset2.lua")));
redisScript.setResultType(Boolean.class);
System.out.println(redisTemplate.execute(redisScript , Collections.singletonList("value123"),"10" ,"key123"));

我总是得到例外:

java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.String
at org.springframework.data.redis.serializer.StringRedisSerializer.serialize(StringRedisSerializer.java:32)
at org.springframework.data.redis.core.script.DefaultScriptExecutor.keysAndArgs(DefaultScriptExecutor.java:116)
at org.springframework.data.redis.core.script.DefaultScriptExecutor$1.doInRedis(DefaultScriptExecutor.java:63)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:202)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:164)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:152)
at org.springframework.data.redis.core.script.DefaultScriptExecutor.execute(DefaultScriptExecutor.java:60)
at org.springframework.data.redis.core.script.DefaultScriptExecutor.execute(DefaultScriptExecutor.java:54)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:298)
at com.masary.ledger.ResisScriptTestClass.msisdnJustRechargedException(ResisScriptTestClass.java:34)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

当我使用

  

System.out.println(redisTemplate.execute(redisScript,   Collections.singletonList(“value123”),new Long(10),“key123”));

我得到例外

     org.springframework.data.redis.RedisSystemException: Unknown redis exception; nested exception is java.lang.ClassCastException: [B cannot be cast to java.lang.Long
        at org.springframework.data.redis.FallbackExceptionTranslationStrategy.getFallback(FallbackExceptionTranslationStrategy.java:48)
        at org.springframework.data.redis.FallbackExceptionTranslationStrategy.translate(FallbackExceptionTranslationStrategy.java:38)
        at org.springframework.data.redis.connection.jedis.JedisConnection.convertJedisAccessException(JedisConnection.java:212)
        at org.springframework.data.redis.connection.jedis.JedisConnection.evalSha(JedisConnection.java:3173)
        at org.springframework.data.redis.connection.jedis.JedisConnection.evalSha(JedisConnection.java:3158)
        at org.springframework.data.redis.connection.DefaultStringRedisConnection.evalSha(DefaultStringRedisConnection.java:1374)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at org.springframework.data.redis.core.CloseSuppressingInvocationHandler.invoke(CloseSuppressingInvocationHandler.java:57)
        at com.sun.proxy.$Proxy182.evalSha(Unknown Source)
        at org.springframework.data.redis.core.script.DefaultScriptExecutor.eval(DefaultScriptExecutor.java:81)
        at org.springframework.data.redis.core.script.DefaultScriptExecutor$1.doInRedis(DefaultScriptExecutor.java:71)
        at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:202)
        at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:164)
        at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:152)
        at org.springframework.data.redis.core.script.DefaultScriptExecutor.execute(DefaultScriptExecutor.java:60)
        at org.springframework.data.redis.core.script.DefaultScriptExecutor.execute(DefaultScriptExecutor.java:54)
        at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:298)
        at com.masary.ledger.ResisScriptTestClass.msisdnJustRechargedException(ResisScriptTestClass.java:34)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
.
.
    Caused by: java.lang.ClassCastException: [B cannot be cast to java.lang.Long
        at org.springframework.data.redis.connection.jedis.JedisScriptReturnConverter.convert(JedisScriptReturnConverter.java:53)
        at org.springframework.data.redis.connection.jedis.JedisConnection.evalSha(JedisConnection.java:3171)
        ... 46 more

任何建议我如何将到期时间值传递给lua脚本?

2 个答案:

答案 0 :(得分:0)

我自己是一个新手,并且遇到了类似的问题。尝试发送字符串"10",而不是Long。为我工作。

答案 1 :(得分:0)

该线程可能很旧,但可能对那些偶然发现该线程的人有所帮助。

对我来说,原因是使用JdkSerializationRedisSerializer作为值序列化程序,例如:redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer()),这也是默认设置。

要解决此问题,请参阅下面的修复程序:

private static void redisEvalForExpire(String scriptText, List<String> keys, Object[] argv) {
  // since spring boot serializes data to - "\xac\xed\x00\x05t\x00\x0" it was not being recognized by redis as integer
  redisTemplate.execute(new DefaultRedisScript<>(scriptText), new StringRedisSerializer(), new StringRedisSerializer(), keys, argv);
}

这表示对任何值都使用StringRedisSerializer,所以当我们做-set a 2时,使用JdkSerializationRedisSerializer,将2序列化为类似的内容:

"\xac\xed\x00\x05sr\x00\x11java.lang.Integer\x12\xe2\xa0\xa4\xf7\x81\x878\x02\x00\x01I\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x00\x02"

但是当我们说使用StringRedisSerializer时,将2发送为"2",Redis可以轻松识别。

Official Documentation