通过reids的自增来获取一个唯一的自增id是我们的一个需求场景,不过如果使用reids的多个命令需要处理事务,于是通过lua脚本获取自增id成为了我们的首选,不过在使用lua脚本过程中我们经常会遇到如下报错
org.springframework.data.redis.RedisSystemException: Redis exception; nested exception is io.lettuce.core.RedisException: java.lang.IllegalStateException
lua脚本如下
local key = KEYS[1]
local id = redis.call('get',key)
if(id == false)
then
redis.call('set',key,1)
return 1
else
redis.call('set',key,id+1)
return id + 1
end
java 调用方法如下
package com.bsx.test.lua;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Service;
/**
* @Description:
* @author: ztd
* @date 2019/7/11 下午4:13
*/
@Service
@Slf4j
public class RedisIDGenerator {
@Autowired
private RedisTemplate<String, Long> redisTemplate;
public Object nextIDLua(String key){
DefaultRedisScript redisScript =new DefaultRedisScript<>();
redisScript.setLocation(new ClassPathResource("lua/id.lua"));
// 这个值类型要跟lua返回值类型一致才行,否则就会报 java.lang.IllegalStateException
redisScript.setResultType(String.class);
log.info("sha1:{}", redisScript.getSha1());
return redisTemplate.execute(redisScript, Lists.newArrayList(key), Lists.newArrayList());
}
}
错误原因:结果类型不对应
也许你发现了,我们lua脚本返回的内容是数字类型,而我们使用的是String类型来接收的,那么spring在把内容进行转换的过程中就报错了,解决办法很简单就是把 :
redisScript.setResultType(String.class);
改成
redisScript.setResultType(Long.class);