Previously, we were using Redis with cluster mode disabled via AWS ElastiCache.
Our Java code using Jedis was pointing to the primary single node endpoint, which was used for reads and writes.
We've now enabled cluster mode.
We have now changed the code to point to the configuration endpoint of the new Redis cluster however it is now throwing errors whenever receiving requests, see below:
Redis Unavailable. Continue using the Queue requestMessage instead. org.springframework.data.redis.ClusterRedirectException: Redirect: slot 2356 to [ipaddress]:6379.; nested exception is redis.clients.jedis.exceptions.JedisMovedDataException: MOVED 2356 [ipaddress]:6379
Our configuration code is as below:
@Bean(name = "redisTemplate")
public RedisTemplate<String, String> getRedisTemplate(JedisConnectionFactory jedisConnectionFactory) {
RedisTemplate template = new RedisTemplate();
template.setConnectionFactory(jedisConnectionFactory);
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(new StringRedisSerializer());
template.afterPropertiesSet();
return template;
}
@Bean
JedisConnectionFactory jedisConnectionFactory(Configuration config) {
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory();
jedisConnectionFactory.setHostName(config.get(HOST));
jedisConnectionFactory.setPort(config.getInt(PORT));
jedisConnectionFactory.setUsePool(true);
jedisConnectionFactory.setPoolConfig(createJedisPoolConfig(config));
jedisConnectionFactory.afterPropertiesSet();
return jedisConnectionFactory;
}
JedisPoolConfig createJedisPoolConfig(Config config) {
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(config.getInt(MAX, 8));
poolConfig.setMaxIdle(config.getInt(MAXIDLE, 8));
poolConfig.setMinIdle(config.getInt(MINIDLE, 1));
poolConfig.setTestOnBorrow(true);
poolConfig.setTestOnReturn(true);
return poolConfig;
}
Shouldn't just changing Jedis to point to the configuration endpoint be enough?
Do I need to change anything in my code?
Shouldn't just changing Jedis to point to the configuration endpoint be enough?
No, as the Redis client - Jedis in this instance - needs to be aware that it is connecting to a cluster and it currently isn't.
You are getting MOVED
as the Redis cluster is telling the client that the data being requested has now been 'resharded' to another node. Jedis, however, is not aware that a cluster is being used, and thus that there are any other nodes and therefore, can't even connect to them to retrieve data.
Do I need to change anything in my code?
You need to use JedisCluster
instead of JedisPool
for the discovery of the Redis nodes to happen & make the other relative changes within the codebase.
Note that you only need to reference the configuration endpoint:
Set<HostAndPort> jedisClusterNodes = new HashSet<HostAndPort>();
jedisClusterNodes.add(new HostAndPort(CONFIGURATION_ENDPOINT, 6379));
try (JedisCluster jedisCluster = new JedisCluster(jedisClusterNodes)) {
// ...
}