JedisMovedDataException(将 sadd 与管道一起使用时)

JedisMovedDataException (When using sadd with pipeline)

我有一个 3 节点 EC2 redis 集群设置,我正在尝试使用管道模式将记录添加到 redis(使用 sadd)。

在 3 个节点中添加大约 70/82 和 81 个键后出现以下错误:

    Exception in thread "main" redis.clients.jedis.exceptions.JedisMovedDataException: MOVED 1539 172.31.59.103:6379
at redis.clients.jedis.Protocol.processError(Protocol.java:93)
at redis.clients.jedis.Protocol.process(Protocol.java:122)
at redis.clients.jedis.Protocol.read(Protocol.java:191)
at redis.clients.jedis.Connection.getOne(Connection.java:258)
at redis.clients.jedis.ShardedJedisPipeline.sync(ShardedJedisPipeline.java:44)
at org.hu.e63.MovieLens21MPipeline.push(MovieLens21MPipeline.java:47)
at org.hu.e63.MovieLens21MPipeline.main(MovieLens21MPipeline.java:53

我查看了 this 线程,我的代码很像这样:

输入文件来自这里(ratings.csv): http://files.grouplens.org/datasets/movielens/ml-latest-small.zip

代码如下:

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPipeline;

public class MovieLens21MPipeline {
    ShardedJedis jedis;

    public MovieLens21MPipeline() {
        JedisShardInfo si = new JedisShardInfo("172.31.59.103", 6379, 5000);
        List<JedisShardInfo> list = new ArrayList<JedisShardInfo>();
        list.add(si);
        list.add(new JedisShardInfo("172.31.59.104", 6379, 5000));
        list.add(new JedisShardInfo("172.31.59.105", 6379, 5000));

        jedis = new ShardedJedis(list);
    }

    public void push() {
        ShardedJedisPipeline pipeline = jedis.pipelined();
        Scanner s;

        try {
            s = new Scanner(new File("input/ratings.csv"));

            StringBuilder key = new StringBuilder();
            String s1 = s.nextLine(); // Skip first line
            while (s.hasNextLine()) {
                s1 = s.nextLine();
                String[] spl = s1.split(",");
                // key="u:"+spl[0]+":m";
                key.append("u:").append(spl[0]).append(":m");
                pipeline.sadd(key.toString(), spl[1]);
                key.setLength(0);
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            System.out.println("bye" + e.getMessage());
        }

        pipeline.sync();
    }

    public static void main(String[] args) {
        MovieLens21MPipeline obj = new MovieLens21MPipeline();
        long startTime = System.currentTimeMillis();
        obj.push();
        long endTime = System.currentTimeMillis();
        double d = 0.0;
        d = (double) (endTime - startTime);
        System.out.println("Throughput: " + d);
    }
}

感谢任何帮助。

MOVED 表示您正在使用 Redis 集群。 ShardedJedis 不适用于 Redis 集群,因此您应该改用 JedisCluster。 请注意,JedisCluster 没有管道模式,因此您可能需要一个一个地发送您的操作。

希望对您有所帮助。

就像Lim说的,你是在集群模式下使用Redis。使用 JedisCluster 可以解决这个问题。另外,作为补充,JedisCluster为什么有效?

从JedisCluster的源码可以知道

private T runWithRetries(byte[] key, int attempts, boolean tryRandomNode, boolean asking) {
    if (attempts <= 0) {
        throw new JedisClusterMaxRedirectionsException("Too many Cluster redirections?");
    }

    Jedis connection = null;
    try {
        // omit ... get connection
        return execute(connection);

    } catch (JedisNoReachableClusterNodeException jnrcne) {
        throw jnrcne;
    } catch (JedisConnectionException jce) {
        // release current connection before recursion
        // omit

        return runWithRetries(key, attempts - 1, tryRandomNode, asking);
    } catch (JedisRedirectionException jre) {
        // if MOVED redirection occurred,
        if (jre instanceof JedisMovedDataException) {
            // here is the key point 
            // it rebuilds cluster's slot cache
            // recommended by Redis cluster specification
            // Jedis or ShardedJedis won't run this code
            this.connectionHandler.renewSlotCache(connection);
        }

        // omit ... 

        return runWithRetries(key, attempts - 1, false, asking);
    } finally {
        releaseConnection(connection);
    }
}