others-How to solve ClusterRedirectException(JedisMovedDataException: MOVED)

1. The purpose of this post

I would demo how to solve this error when using SpringBoot and Redis cluster

INFO   | jvm 1    | 2019/07/19 15:19:56 | org.springframework.data.redis.ClusterRedirectException: Redirect: slot 6210 to 10.252.227.96:6379.; nested exception is redis.clients.jedis.exceptions.JedisMovedDataException: MOVED 6210 10.252.227.96:6379
INFO   | jvm 1    | 2019/07/19 15:19:56 |   at org.springframework.data.redis.connection.jedis.JedisExceptionConverter.convert(JedisExceptionConverter.java:56) ~[spring-data-redis-1.8.9.RELEASE.jar:na]
INFO   | jvm 1    | 2019/07/19 15:19:56 |   at org.springframework.data.redis.connection.jedis.JedisExceptionConverter.convert(JedisExceptionConverter.java:41) ~[spring-data-redis-1.8.9.RELEASE.jar:na]
INFO   | jvm 1    | 2019/07/19 15:19:56 |   at org.springframework.data.redis.PassThroughExceptionTranslationStrategy.translate(PassThroughExceptionTranslationStrategy.java:37) ~[spring-data-redis-1.8.9.RELEASE.jar:na]
INFO   | jvm 1    | 2019/07/19 15:19:56 |   at org.springframework.data.redis.FallbackExceptionTranslationStrategy.translate(FallbackExceptionTranslationStrategy.java:37) ~[spring-data-redis-1.8.9.RELEASE.jar:na]
INFO   | jvm 1    | 2019/07/19 15:19:56 |   at org.springframework.data.redis.connection.jedis.JedisConnection.convertJedisAccessException(JedisConnection.java:241) ~[spring-data-redis-1.8.9.RELEASE.jar:na]
INFO   | jvm 1    | 2019/07/19 15:19:56 |   at org.springframework.data.redis.connection.jedis.JedisConnection.sMembers(JedisConnection.java:2087) ~[spring-data-redis-1.8.9.RELEASE.jar:na]
INFO   | jvm 1    | 2019/07/19 15:19:56 |   at org.springframework.data.redis.connection.DefaultStringRedisConnection.sMembers(DefaultStringRedisConnection.java:827) ~[spring-data-redis-1.8.9.RELEASE.jar:na]
INFO   | jvm 1    | 2019/07/19 15:19:56 |   at org.springframework.data.redis.core.DefaultSetOperations$7.doInRedis(DefaultSetOperations.java:129) ~[spring-data-redis-1.8.9.RELEASE.jar:na]
INFO   | jvm 1    | 2019/07/19 15:19:56 |   at org.springframework.data.redis.core.DefaultSetOperations$7.doInRedis(DefaultSetOperations.java:126) ~[spring-data-redis-1.8.9.RELEASE.jar:na]
INFO   | jvm 1    | 2019/07/19 15:19:56 |   at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:207) ~[spring-data-redis-1.8.9.RELEASE.jar:na]
INFO   | jvm 1    | 2019/07/19 15:19:56 |   at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:169) ~[spring-data-redis-1.8.9.RELEASE.jar:na]
INFO   | jvm 1    | 2019/07/19 15:19:56 |   at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:91) ~[spring-data-redis-1.8.9.RELEASE.jar:na]
INFO   | jvm 1    | 2019/07/19 15:19:56 |   at org.springframework.data.redis.core.DefaultSetOperations.members(DefaultSetOperations.java:126) ~[spring-data-redis-1.8.9.RELEASE.jar:na]

2. Environments

  • java 1.8+
  • SpringBoot 1.x or 2.x
  • Redis Cluster

3. Solution and Code

You can connecting a node in redis cluster using a non-cluster mode.

wrong way:connect redis cluster using non-cluster mode

According to redis official documents:

Keys distribution model The key space is split into 16384 slots, effectively setting an upper limit for the cluster size of 16384 master nodes (however the suggested max size of nodes is in the order of ~ 1000 nodes).

Each master node in a cluster handles a subset of the 16384 hash slots. The cluster is stable when there is no cluster reconfiguration in progress (i.e. where hash slots are being moved from one node to another). When the cluster is stable, a single hash slot will be served by a single node (however the serving node can have one or more slaves that will replace it in the case of net splits or failures, and that can be used in order to scale read operations where reading stale data is acceptable).

3.1 Solution 1

Connect your redis cluster using cluster mode like this: correct way:connect redis cluster using cluster mode

@Bean
@Primary
@ConfigurationProperties(prefix="redis.cluster")
public RedisConnectionFactory redisConnectionFactory(
        RedisClusterConfiguration redisClusterConfiguration,
        RedisSentinelConfiguration redisSentinelConfiguration,
        JedisPoolConfig jedisPoolConfig) {

    logger.info("Using redis cluster: [{}]", redisClusterConfiguration.getClusterNodes());
    return new JedisConnectionFactory(redisClusterConfiguration);
}

3.2 Solution 2

Setup a single-node redis server, and connect to it: correct way:connect redis single server using single server mode

@Bean
public RedisConnectionFactory anotherRedisConnectionFactory(JedisPoolConfig jedisPoolConfig) {
    JedisConnectionFactory redisConnectionFactory = new JedisConnectionFactory();
    redisConnectionFactory.setHostName(host);
    redisConnectionFactory.setPort(port);
    redisConnectionFactory.setUsePool(true);
    redisConnectionFactory.setPoolConfig(jedisPoolConfig);
    redisConnectionFactory.setTimeout(timeout);
    return redisConnectionFactory;
}