DATAREDIS-545 - Support connection-pooling for Redis Cluster with Lettuce.

We now support connection pooling for Cluster connections using Lettuce.

Original Pull Request: #297
This commit is contained in:
Mark Paluch
2017-12-18 14:23:38 +01:00
committed by Christoph Strobl
parent a3d4e4f771
commit 155f45c376
5 changed files with 62 additions and 29 deletions

View File

@@ -22,6 +22,7 @@ import io.lettuce.core.cluster.RedisClusterClient;
import io.lettuce.core.cluster.SlotHash;
import io.lettuce.core.cluster.api.StatefulRedisClusterConnection;
import io.lettuce.core.cluster.api.sync.RedisClusterCommands;
import io.lettuce.core.cluster.models.partitions.Partitions;
import lombok.RequiredArgsConstructor;
import java.time.Duration;
@@ -63,6 +64,7 @@ public class LettuceClusterConnection extends LettuceConnection implements Defau
new LettuceExceptionConverter());
private final Log log = LogFactory.getLog(getClass());
private final RedisClusterClient clusterClient;
private ClusterCommandExecutor clusterCommandExecutor;
private ClusterTopologyProvider topologyProvider;
@@ -114,10 +116,14 @@ public class LettuceClusterConnection extends LettuceConnection implements Defau
super(null, connectionProvider, RedisURI.DEFAULT_TIMEOUT_DURATION.toMillis(), 0);
topologyProvider = new LettuceClusterTopologyProvider(getClient());
clusterCommandExecutor = new ClusterCommandExecutor(topologyProvider,
Assert.isTrue(connectionProvider instanceof ClusterConnectionProvider,
"LettuceConnectionProvider must be a ClusterConnectionProvider.");
this.clusterClient = ((ClusterConnectionProvider) connectionProvider).getRedisClient();
this.topologyProvider = new LettuceClusterTopologyProvider(this.clusterClient);
this.clusterCommandExecutor = new ClusterCommandExecutor(this.topologyProvider,
new LettuceClusterNodeResourceProvider(getConnectionProvider()), exceptionConverter);
disposeClusterCommandExecutorOnClose = true;
this.disposeClusterCommandExecutorOnClose = true;
}
/**
@@ -147,30 +153,37 @@ public class LettuceClusterConnection extends LettuceConnection implements Defau
super(null, connectionProvider, timeout.toMillis(), 0);
Assert.notNull(executor, "ClusterCommandExecutor must not be null.");
Assert.isTrue(connectionProvider instanceof ClusterConnectionProvider,
"LettuceConnectionProvider must be a ClusterConnectionProvider.");
this.topologyProvider = new LettuceClusterTopologyProvider(getClient());
this.clusterClient = ((ClusterConnectionProvider) connectionProvider).getRedisClient();
this.topologyProvider = new LettuceClusterTopologyProvider(this.clusterClient);
this.clusterCommandExecutor = executor;
this.disposeClusterCommandExecutorOnClose = false;
}
/**
* Creates new {@link LettuceClusterConnection} given a shared {@link StatefulRedisClusterConnection}
* and{@link LettuceConnectionProvider} running commands across the cluster via given {@link ClusterCommandExecutor}.
* Creates new {@link LettuceClusterConnection} given a shared {@link StatefulRedisClusterConnection} and
* {@link LettuceConnectionProvider} running commands across the cluster via given {@link ClusterCommandExecutor}.
*
* @param sharedConnection must not be {@literal null}.
* @param sharedConnection may be {@literal null} if no shared connection used.
* @param connectionProvider must not be {@literal null}.
* @param clusterClient must not be {@literal null}.
* @param executor must not be {@literal null}.
* @param timeout must not be {@literal null}.
* @since 2.1
*/
public LettuceClusterConnection(StatefulRedisClusterConnection<byte[], byte[]> sharedConnection,
LettuceConnectionProvider connectionProvider, ClusterCommandExecutor executor, Duration timeout) {
LettuceClusterConnection(@Nullable StatefulRedisClusterConnection<byte[], byte[]> sharedConnection,
LettuceConnectionProvider connectionProvider, RedisClusterClient clusterClient, ClusterCommandExecutor executor,
Duration timeout) {
super(sharedConnection, connectionProvider, timeout.toMillis(), 0);
Assert.notNull(executor, "ClusterCommandExecutor must not be null.");
Assert.notNull(clusterClient, "RedisClusterClient must not be null.");
this.topologyProvider = new LettuceClusterTopologyProvider(getClient());
this.clusterClient = clusterClient;
this.topologyProvider = new LettuceClusterTopologyProvider(clusterClient);
this.clusterCommandExecutor = executor;
this.disposeClusterCommandExecutorOnClose = false;
}
@@ -190,6 +203,14 @@ public class LettuceClusterConnection extends LettuceConnection implements Defau
connectionProvider.getClass().getName()));
}
/**
* @return access to {@link RedisClusterClient} for non-connection access.
*/
private Partitions getPartitions() {
return clusterClient.getPartitions();
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.lettuce.LettuceConnection#geoCommands()
@@ -308,7 +329,7 @@ public class LettuceClusterConnection extends LettuceConnection implements Defau
@Override
public RedisClusterNode clusterGetNodeForSlot(int slot) {
return LettuceConverters.toRedisClusterNode(getClient().getPartitions().getPartitionBySlot(slot));
return LettuceConverters.toRedisClusterNode(getPartitions().getPartitionBySlot(slot));
}
/*
@@ -515,7 +536,7 @@ public class LettuceClusterConnection extends LettuceConnection implements Defau
return doGetClusterKeyCommands().keys(node, pattern);
}
/*
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisClusterConnection#scan(org.springframework.data.redis.connection.RedisClusterNode, org.springframework.data.redis.core.ScanOptions)
*/
@@ -524,7 +545,7 @@ public class LettuceClusterConnection extends LettuceConnection implements Defau
return doGetClusterKeyCommands().scan(node, options);
}
/*
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisClusterConnection#randomKey(org.springframework.data.redis.connection.RedisClusterNode)
*/
@@ -552,7 +573,7 @@ public class LettuceClusterConnection extends LettuceConnection implements Defau
*/
@Override
public List<RedisClusterNode> clusterGetNodes() {
return LettuceConverters.partitionsToClusterNodes(getClient().getPartitions());
return LettuceConverters.partitionsToClusterNodes(getPartitions());
}
/*

View File

@@ -241,7 +241,7 @@ public class LettuceConnection extends AbstractRedisConnection {
* @param defaultDbIndex The db index to use along with {@link RedisClient} when establishing a dedicated connection.
* @since 2.0
*/
public LettuceConnection(StatefulRedisConnection<byte[], byte[]> sharedConnection,
public LettuceConnection(@Nullable StatefulRedisConnection<byte[], byte[]> sharedConnection,
LettuceConnectionProvider connectionProvider, long timeout, int defaultDbIndex) {
this((StatefulConnection<byte[], byte[]>) sharedConnection, connectionProvider, timeout, defaultDbIndex);
}
@@ -254,7 +254,8 @@ public class LettuceConnection extends AbstractRedisConnection {
* @param defaultDbIndex The db index to use along with {@link RedisClient} when establishing a dedicated connection.
* @since 2.1
*/
LettuceConnection(StatefulConnection<byte[], byte[]> sharedConnection, LettuceConnectionProvider connectionProvider,
LettuceConnection(@Nullable StatefulConnection<byte[], byte[]> sharedConnection,
LettuceConnectionProvider connectionProvider,
long timeout, int defaultDbIndex) {
Assert.notNull(connectionProvider, "LettuceConnectionProvider must not be null.");

View File

@@ -345,12 +345,14 @@ public class LettuceConnectionFactory
throw new InvalidDataAccessApiUsageException("Cluster is not configured!");
}
RedisClusterClient clusterClient = (RedisClusterClient) client;
return getShareNativeConnection()
? new LettuceClusterConnection(
(StatefulRedisClusterConnection<byte[], byte[]>) getOrCreateSharedConnection().getConnection(),
connectionProvider, clusterCommandExecutor, clientConfiguration.getCommandTimeout())
: new LettuceClusterConnection(connectionProvider, clusterCommandExecutor,
clientConfiguration.getCommandTimeout());
connectionProvider, clusterClient, clusterCommandExecutor, clientConfiguration.getCommandTimeout())
: new LettuceClusterConnection(null, connectionProvider, clusterClient, clusterCommandExecutor,
clientConfiguration.getCommandTimeout());
}
/*