Сценарий запуска Spring 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

Из весеннего загрузочного приложения я использую для вызова 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?


person Shady Ragab    schedule 10.11.2016    source источник


Ответы (2)


Я сам новичок, и у меня была похожая проблема. Попробуйте отправить строку "10" вместо Long. Работал на меня.

person ystark    schedule 07.02.2017

Тема может быть старой, но может быть полезной для других, которые могут наткнуться на это.

Для меня причиной было использование 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 может легко распознать.

Официальная документация

person Darvesh    schedule 05.08.2020