RedisTemplate执行lua脚本在Redis集群模式下报错EvalSha is not supported in cluster environment

RedisTemplate执行lua脚本在Redis集群模式下报错EvalSha is not supported in cluster environment.

异常信息:

1
2
3
4
5
6
7
8
9
10
org.springframework.dao.InvalidDataAccessApiUsageException: EvalSha is not supported in cluster environment.
at org.springframework.data.redis.connection.jedis.JedisClusterScriptingCommands.evalSha(JedisClusterScriptingCommands.java:83) ~[spring-data-redis-2.1.8.RELEASE.jar:2.1.8.RELEASE]
at org.springframework.data.redis.connection.DefaultedRedisConnection.evalSha(DefaultedRedisConnection.java:1318) ~[spring-data-redis-2.1.8.RELEASE.jar:2.1.8.RELEASE]
at org.springframework.data.redis.connection.DefaultStringRedisConnection.evalSha(DefaultStringRedisConnection.java:1729) ~[spring-data-redis-2.1.8.RELEASE.jar:2.1.8.RELEASE]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_181]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_181]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_181]
at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_181]
at org.springframework.data.redis.core.CloseSuppressingInvocationHandler.invoke(CloseSuppressingInvocationHandler.java:61) ~[spring-data-redis-2.1.8.RELEASE.jar:2.1.8.RELEASE]
at com.sun.proxy.$Proxy196.evalSha(Unknown Source) ~[?:?]

执行方法,集群下报错:

1
2
3
4
public boolean unlock(String key, String value) {
Long result = template.execute(redisScript, Arrays.asList(key),Arrays.asList(value));
return RELEASE_SUCCESS.equals(result);
}

解决方案

原因:spring自带的执行脚本方法中,集群模式直接抛出不支持执行脚本的异常,所以只能拿到原redis的connection来执行脚本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public boolean unlock(String key, String value) {
//使用Lua脚本:先判断是否是自己设置的锁,再执行删除
// 使用lua脚本删除redis中匹配value的key,可以避免由于方法执行时间过长而redis锁自动过期失效的时候误删其他线程的锁
// spring自带的执行脚本方法中,集群模式直接抛出不支持执行脚本的异常,所以只能拿到原redis的connection来执行脚本

List<String> keys = new ArrayList<>();
keys.add(key);
List<String> args = new ArrayList<>();
args.add(value);

Long result = template.execute(new RedisCallback<Long>() {
@Override
public Long doInRedis(RedisConnection connection) throws DataAccessException {
Object nativeConnection = connection.getNativeConnection();
// 集群模式和单机模式虽然执行脚本的方法一样,但是没有共同的接口,所以只能分开执行
// 集群模式
if (nativeConnection instanceof JedisCluster) {
return (Long) ((JedisCluster) nativeConnection).eval(UNLOCK_LUA, keys, args);
}

// 单机模式
else if (nativeConnection instanceof Jedis) {
return (Long) ((Jedis) nativeConnection).eval(UNLOCK_LUA, keys, args);
}
return 0L;
}
});

//返回最终结果
return RELEASE_SUCCESS.equals(result);
}

参考文档:

https://my.oschina.net/dengfuwei/blog/1600681

-------------已经触及底线 感谢您的阅读-------------

本文标题:RedisTemplate执行lua脚本在Redis集群模式下报错EvalSha is not supported in cluster environment

文章作者:趙小傑~~

发布时间:2019年11月19日 - 17:04:26

最后更新:2019年11月28日 - 22:04:51

原始链接:https://cnsyear.com/posts/36ce5187.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

0%