zoukankan      html  css  js  c++  java
  • RedisTemplate执行lua脚本在Redis集群模式下报错EvalSha is not supported in cluster environment.

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

    异常信息:

    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) ~[?:?]
    

    执行方法,集群下报错:

    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来执行脚本。

    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

  • 相关阅读:
    Sona && Little Elephant and Array && Little Elephant and Array && D-query && Powerful array && Fast Queries (莫队)
    P1494 [国家集训队]小Z的袜子(luogu)
    【题解】洛谷P1311 [NOIP2011TG] 选择客栈(递推)
    【题解】洛谷P2296 [NOIP2014TG] 寻找道路(SPFA+DFS)
    【题解】洛谷P2661 [NOIP2015TG] 信息传递
    【题解】洛谷P1065 [NOIP2006TG] 作业调度方案(模拟+阅读理解)
    【题解】洛谷P1032 [NOIP2002TG]字串变换(BFS+字符串)
    [BZOJ2127]happiness-[网络流-最小割]
    [BZOJ3218]a + b Problem-[主席树+网络流-最小割]
    BZOJ4049][CERC2014]Mountainous landscape-[线段树+凸包+二分]
  • 原文地址:https://www.cnblogs.com/cnsyear/p/12731979.html
Copyright © 2011-2022 走看看