From edde436f4285fd33ac1f584f5886be267991d4b6 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 2 Jul 2021 11:49:18 +0200 Subject: [PATCH] Avoid configuring the database number in JedisClientConfiguration used for Sentinels. We now no longer configure the database number configured for data node access through JedisClientConfiguration instances that are used for Sentinel node connectivity. Previously, the configured database number lead to issuing a SELECT command on Sentinel that doesn't support database isolation. Fixes: #2103. Original Pull Request: #2112 --- .../jedis/JedisConnectionFactory.java | 18 +++++---- ...ectionFactorySentinelIntegrationTests.java | 37 +++++++++++++++++++ 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactory.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactory.java index f09edff5a..f7af5cde4 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactory.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactory.java @@ -319,7 +319,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, */ public void afterPropertiesSet() { - clientConfig = createClientConfig(getRedisUsername(), getRedisPassword()); + clientConfig = createClientConfig(getDatabase(), getRedisUsername(), getRedisPassword()); if (shardInfo == null && clientConfiguration instanceof MutableJedisClientConfiguration) { @@ -360,7 +360,11 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, this.initialized = true; } - private JedisClientConfig createClientConfig(@Nullable String username, RedisPassword password) { + private JedisClientConfig createSentinelClientConfig(SentinelConfiguration sentinelConfiguration) { + return createClientConfig(0, null, sentinelConfiguration.getSentinelPassword()); + } + + private JedisClientConfig createClientConfig(int database, @Nullable String username, RedisPassword password) { DefaultJedisClientConfig.Builder builder = DefaultJedisClientConfig.builder(); @@ -368,7 +372,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, builder.connectionTimeoutMillis(getConnectTimeout()); builder.socketTimeoutMillis(getReadTimeout()); - builder.database(getDatabase()); + builder.database(database); if (!ObjectUtils.isEmpty(username)) { builder.user(username); @@ -405,9 +409,8 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, protected Pool createRedisSentinelPool(RedisSentinelConfiguration config) { GenericObjectPoolConfig poolConfig = getPoolConfig() != null ? getPoolConfig() : new JedisPoolConfig(); - String sentinelUser = null; - JedisClientConfig sentinelConfig = createClientConfig(sentinelUser, config.getSentinelPassword()); + JedisClientConfig sentinelConfig = createSentinelClientConfig(config); return new JedisSentinelPool(config.getMaster().getName(), convertToJedisSentinelSet(config.getSentinels()), poolConfig, this.clientConfig, sentinelConfig); } @@ -513,7 +516,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, SentinelConfiguration sentinelConfiguration = getSentinelConfiguration(); if (sentinelConfiguration != null) { - sentinelConfig = createClientConfig(null, sentinelConfiguration.getSentinelPassword()); + sentinelConfig = createSentinelClientConfig(sentinelConfiguration); } JedisConnection connection = (getUsePool() ? new JedisConnection(jedis, pool, this.clientConfig, sentinelConfig) @@ -904,7 +907,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, Assert.isTrue(RedisConfiguration.isSentinelConfiguration(configuration), "SentinelConfig must not be null!"); SentinelConfiguration sentinelConfiguration = (SentinelConfiguration) configuration; - JedisClientConfig clientConfig = createClientConfig(null, sentinelConfiguration.getSentinelPassword()); + JedisClientConfig clientConfig = createSentinelClientConfig(sentinelConfiguration); for (RedisNode node : sentinelConfiguration.getSentinels()) { Jedis jedis = null; @@ -929,6 +932,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean, throw new InvalidDataAccessResourceUsageException("No Sentinel found"); } + private static Set convertToJedisSentinelSet(Collection nodes) { if (CollectionUtils.isEmpty(nodes)) { diff --git a/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactorySentinelIntegrationTests.java b/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactorySentinelIntegrationTests.java index da4e7fc17..eaf8d7a4e 100644 --- a/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactorySentinelIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactorySentinelIntegrationTests.java @@ -17,11 +17,14 @@ package org.springframework.data.redis.connection.jedis; import static org.assertj.core.api.Assertions.*; +import java.io.IOException; + import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.RedisSentinelConfiguration; +import org.springframework.data.redis.connection.RedisSentinelConnection; import org.springframework.data.redis.test.condition.EnabledOnRedisSentinelAvailable; import org.springframework.lang.Nullable; @@ -48,6 +51,40 @@ class JedisConnectionFactorySentinelIntegrationTests { } } + @Test // GH-2103 + void shouldConnectDataNodeCorrectly() { + + RedisSentinelConfiguration configuration = new RedisSentinelConfiguration().master("mymaster") + .sentinel("127.0.0.1", 26379).sentinel("127.0.0.1", 26380); + configuration.setDatabase(5); + + factory = new JedisConnectionFactory(configuration); + factory.afterPropertiesSet(); + + RedisConnection connection = factory.getConnection(); + connection.flushAll(); + connection.set("key5".getBytes(), "value5".getBytes()); + + connection.select(0); + assertThat(connection.exists("key5".getBytes())).isFalse(); + connection.close(); + } + + @Test // GH-2103 + void shouldConnectSentinelNodeCorrectly() throws IOException { + + RedisSentinelConfiguration configuration = new RedisSentinelConfiguration().master("mymaster") + .sentinel("127.0.0.1", 26379).sentinel("127.0.0.1", 26380); + configuration.setDatabase(5); + + factory = new JedisConnectionFactory(configuration); + factory.afterPropertiesSet(); + + RedisSentinelConnection sentinelConnection = factory.getSentinelConnection(); + assertThat(sentinelConnection.masters()).isNotNull(); + sentinelConnection.close(); + } + @Test // DATAREDIS-574, DATAREDIS-765 void shouldInitializeWithSentinelConfiguration() {