Lua脚本如下,key对应的值是个hash里面有type、userId、userName、ticket
,如果四个字段不存在或者四个字段完全相同,则表示加锁成功,否则视为加锁失败并且返回当前锁持有者的信息
--重要说明:
--参数type,userId,userName,ticket不能为空,需要在java代码中校验控制。
--返回结果res中code说明
--0、表示加锁失败。
--1、表示无人加锁并且参数ticket不为空,加锁成功,此举意味着如果key存在的话,后面从redis取到的值type、userId、ticket都不为空。
--2、表示同一type、同一用户、同一ticket,加锁成功,并且重新设置过期时间。
local hashTb=redis.call('hmget',KEYS[1],'type','userId','userName','ticket');
local exists=redis.call('exists',KEYS[1]);
local res={};
if exists==0
then redis.call('hmset',KEYS[1],'type',ARGV[1],'userId',ARGV[2],'userName',ARGV[3],'ticket',ARGV[4]);
redis.call('expire',KEYS[1],ARGV[5]);
local ttl=redis.call('ttl',KEYS[1]);
res={code='1',type=ARGV[1],userId=ARGV[2],userName=ARGV[3],ticket=ARGV[4],timeout=ttl};
elseif exists==1 and ARGV[1]==hashTb[1] and ARGV[2]==hashTb[2] and ARGV[4]==hashTb[4]
then redis.call('expire',KEYS[1],ARGV[5]);
local ttl=redis.call('ttl',KEYS[1]);
res={code='2',type=hashTb[1],userId=hashTb[2],userName=hashTb[3],ticket=hashTb[4],timeout=ttl};
else
local ttl=redis.call('ttl',KEYS[1]);
local tb1=hashTb[1]==false and '' or hashTb[1];
local tb2=hashTb[2]==false and '' or hashTb[2];
local tb3=hashTb[3]==false and '' or hashTb[3];
local tb4=hashTb[4]==false and '' or hashTb[4];
res={code='0',type=tb1,userId=tb2,userName=tb3,ticket=tb4,timout=ttl};
end
return cjson.encode(res);
控制台报错信息如下:
org.redisson.client.RedisException: ERR Error running script (call to f_711339d3f4791755f2d2302e82a31bc8976e0d17): @user_script:1: ERR value is not an integer or out of range . channel: [id: 0xbdf23c93, L:/10.4.36.15:1375 - R:test.bimdeco.com/139.196.144.93:31000] command: (EVALSHA), params: [711339d3f4791755f2d2302e82a31bc8976e0d17, 1, 01efc4f9-043c-4907-982a-1caf7c159df6, PooledUnsafeDirectByteBuf(ridx: 0, widx: 5, cap: 256), PooledUnsafeDirectByteBuf(ridx: 0, widx: 18, cap: 256), PooledUnsafeDirectByteBuf(ridx: 0, widx: 9, cap: 256), PooledUnsafeDirectByteBuf(ridx: 0, widx: 6, cap: 256), PooledUnsafeDirectByteBuf(ridx: 0, widx: 6, cap: 256)]
at org.redisson.client.handler.CommandDecoder.decode(CommandDecoder.java:343)
at org.redisson.client.handler.CommandDecoder.decodeCommand(CommandDecoder.java:178)
at org.redisson.client.handler.CommandDecoder.decode(CommandDecoder.java:117)
at org.redisson.client.handler.CommandDecoder.decode(CommandDecoder.java:102)
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:505)
at io.netty.handler.codec.ReplayingDecoder.callDecode(ReplayingDecoder.java:366)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:283)
首先登上redis服务器查看到在key不存在的情况下,调用以后key已经存在,并且能看到里面对应的值,可以确定lua脚本调用成功了
但value非常奇怪,理论上应该如下所示:
怀疑是redis中lua脚本返回的结果(lua中处理成了json字符串),并不是按照redisson指定的序列化方式来序列化的。
经调试发现:
org.redisson.config.Config中默认的是用的
MarshallingCodec来序列化的
public Config(Config oldConf) {
setNettyHook(oldConf.getNettyHook());
setExecutor(oldConf.getExecutor());
if (oldConf.getCodec() == null) {
// use it by default
oldConf.setCodec(new MarshallingCodec());
}
尝试改变redisson默认的序列化方式:
追踪了一下org.redisson.spring.starter.RedissonAutoConfiguration的源码发现
可以通过成员变量:private List redissonAutoConfigurationCustomizers来设置自己指定的序列化方式StringCodec
代码如下
@Bean
public List<RedissonAutoConfigurationCustomizer> redissonAutoConfigurationCustomizers() {
RedissonAutoConfigurationCustomizer customizer = configuration -> {
StringCodec codec = new StringCodec();
configuration.setCodec(codec);
};
List<RedissonAutoConfigurationCustomizer> list = new LinkedList<>();
list.add(customizer);
return list;
}
然后重启服务后再次调用该接口,发现响应正常
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)