Connecting to Redis on Lettuce (Java)
This section describes how to access a DCS Redis instance on Lettuce. For more information about how to use other Redis clients, visit the Redis official website.
In Spring Boot projects, Spring Data Redis has been already integrated with Jedis and Lettuce. Spring Boot 1.x is integrated with Jedis, and Spring Boot 2.x is integrated with Lettuce by default. Therefore, you do not need to manually import the Lettuce dependency in Spring Boot 2.x or later.
Notes and Constraints
Spring Boot must be 2.3.12.RELEASE or later, Lettuce must be 6.3.0.RELEASE or later, and Netty must be 4.1.100.Final or later.
Prerequisites
- A Redis instance is created, and is in the Running state. To create a Redis instance, see Buying a DCS Redis Instance.
- You have obtained the IP address/domain name and port number of the target Redis instance. For details, see Viewing and Modifying Basic Information About a DCS Instance.
- Connectivity between the client and the Redis instance has been established. For details, see Network Conditions for Accessing DCS Redis.
Pom Configuration
<!-- Import the spring-data-redis component. By default, the Lettuce SDK has been integrated. -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>6.3.0.RELEASE</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-epoll</artifactId>
<version>4.1.100.Final</version>
<classifier>linux-x86_64</classifier>
</dependency> Configuration Based on the application.properties File
The configuration varies depending on the Spring Boot version. The following are the configurations for Spring Boot 2.x and Spring Boot 3.x.
- Configuration for single-node, master/standby, read/write splitting, and Proxy Cluster instances
# Redis host spring.redis.host=<host> # Redis port spring.redis.port=<port> # Redis database index spring.redis.database=0 # Redis password spring.redis.password=<password> # Redis read/write timeout spring.redis.timeout=2000
- Configuration for Cluster instances
# Redis Cluster node information spring.redis.cluster.nodes=<ip:port>,<ip:port>,<ip:port> # Maximum number of Redis Cluster redirections spring.redis.cluster.max-redirects=3 # Password of the Redis Cluster node spring.redis.password=<password> # Redis Cluster timeout spring.redis.timeout=2000 # Whether to enable adaptive topology refresh spring.redis.lettuce.cluster.refresh.adaptive=true # Interval for adaptive topology refresh spring.redis.lettuce.cluster.refresh.period=10S
- Configuration for single-node, master/standby, read/write splitting, and Proxy Cluster instances
# Redis host spring.data.redis.host=<host> # Redis port spring.data.redis.port=<port> # Redis database index spring.data.redis.database=0 # Redis password spring.data.redis.password=<password> # Redis read/write timeout spring.data.redis.timeout=2000
- Configuration for Cluster instances
# Redis Cluster node information spring.data.redis.cluster.nodes=<ip:port>,<ip:port>,<ip:port> # Maximum number of Redis Cluster redirections spring.data.redis.cluster.max-redirects=3 # Password of the Redis Cluster node spring.data.redis.password=<password> # Redis Cluster timeout spring.data.redis.timeout=2000 # Whether to enable adaptive topology refresh spring.data.redis.lettuce.cluster.refresh.adaptive=true # Interval for adaptive topology refresh spring.data.redis.lettuce.cluster.refresh.period=10S
Bean-based Configuration
- Configuration for single-node, master/standby, read/write splitting, and Proxy Cluster instances
import java.time.Duration; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisStandaloneConfiguration; import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import io.lettuce.core.ClientOptions; import io.lettuce.core.SocketOptions; /** * Lettuce non-pooling configuration (use either this or the application.properties configuration) */ @Configuration public class RedisConfiguration { @Value("${redis.host}") private String redisHost; @Value("${redis.port:6379}") private Integer redisPort = 6379; @Value("${redis.database:0}") private Integer redisDatabase = 0; @Value("${redis.password:}") private String redisPassword; @Value("${redis.connect.timeout:2000}") private Integer redisConnectTimeout = 2000; @Value("${redis.read.timeout:2000}") private Integer redisReadTimeout = 2000; /** * TCP_KEEPALIVE configuration parameters: * Interval between two Keepalive probes = TCP_KEEPALIVE_TIME = 30 * Time when a connection must be idle before TCP Keepalive probes are sent = TCP_KEEPALIVE_TIME/3 = 10 * Number of Keepalive probes before a connection is dropped = TCP_KEEPALIVE_COUNT = 3 */ private static final int TCP_KEEPALIVE_TIME = 30; /** * TCP_USER_TIMEOUT Connection idle timeout, to resolve prolonged Lettuce client timeouts * refer: https://github.com/lettuce-io/lettuce-core/issues/2082 */ private static final int TCP_USER_TIMEOUT = 30; @Bean public RedisConnectionFactory redisConnectionFactory(LettuceClientConfiguration clientConfiguration) { RedisStandaloneConfiguration standaloneConfiguration = new RedisStandaloneConfiguration(); standaloneConfiguration.setHostName(redisHost); standaloneConfiguration.setPort(redisPort); standaloneConfiguration.setDatabase(redisDatabase); standaloneConfiguration.setPassword(redisPassword); LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(standaloneConfiguration, clientConfiguration); connectionFactory.setDatabase(redisDatabase); return connectionFactory; } @Bean public LettuceClientConfiguration clientConfiguration() { SocketOptions socketOptions = SocketOptions.builder() .keepAlive(SocketOptions.KeepAliveOptions.builder() // Interval between two Keepalive probes .idle(Duration.ofSeconds(TCP_KEEPALIVE_TIME)) // Time when a connection must be idle before TCP Keepalive probes are sent .interval(Duration.ofSeconds(TCP_KEEPALIVE_TIME/3)) // Number of Keepalive probes before a connection is dropped .count(3) // Whether to enable Keepalive .enable() .build()) .tcpUserTimeout(SocketOptions.TcpUserTimeoutOptions.builder() // Resolve the prolonged timeouts caused by server RST. .tcpUserTimeout(Duration.ofSeconds(TCP_USER_TIMEOUT)) .enable() .build()) // Set the TCP connection timeout. .connectTimeout(Duration.ofMillis(redisConnectTimeout)) .build(); ClientOptions clientOptions = ClientOptions.builder() .autoReconnect(true) .pingBeforeActivateConnection(true) .cancelCommandsOnReconnectFailure(false) .disconnectedBehavior(ClientOptions.DisconnectedBehavior.ACCEPT_COMMANDS) .socketOptions(socketOptions) .build(); LettuceClientConfiguration clientConfiguration = LettuceClientConfiguration.builder() .commandTimeout(Duration.ofMillis(redisReadTimeout)) // You do not need to set readFrom for Proxy Cluster instances. .readFrom(ReadFrom.MASTER) .clientOptions(clientOptions) .build(); return clientConfiguration; } } - Pooling configuration for single-node, master/standby, read/write splitting, and Proxy Cluster instances Importing pooling components
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> <version>2.11.1</version> </dependency>Code configuration
import java.time.Duration; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisStandaloneConfiguration; import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration; import io.lettuce.core.ClientOptions; import io.lettuce.core.SocketOptions; /** * Lettuce pooling configuration */ @Configuration public class RedisPoolConfiguration { @Value("${redis.host}") private String redisHost; @Value("${redis.port:6379}") private Integer redisPort = 6379; @Value("${redis.database:0}") private Integer redisDatabase = 0; @Value("${redis.password:}") private String redisPassword; @Value("${redis.connect.timeout:2000}") private Integer redisConnectTimeout = 2000; @Value("${redis.read.timeout:2000}") private Integer redisReadTimeout = 2000; @Value("${redis.pool.minSize:50}") private Integer redisPoolMinSize = 50; @Value("${redis.pool.maxSize:200}") private Integer redisPoolMaxSize = 200; @Value("${redis.pool.maxWaitMillis:2000}") private Integer redisPoolMaxWaitMillis = 2000; @Value("${redis.pool.softMinEvictableIdleTimeMillis:1800000}") private Integer redisPoolSoftMinEvictableIdleTimeMillis = 30 * 60 * 1000; @Value("${redis.pool.timeBetweenEvictionRunsMillis:60000}") private Integer redisPoolBetweenEvictionRunsMillis = 60 * 1000; /** * TCP_KEEPALIVE configuration parameters: * Interval between two Keepalive probes = TCP_KEEPALIVE_TIME = 30 * Time when a connection must be idle before TCP Keepalive probes are sent = TCP_KEEPALIVE_TIME/3 = 10 * Number of Keepalive probes before a connection is dropped = TCP_KEEPALIVE_COUNT = 3 */ private static final int TCP_KEEPALIVE_TIME = 30; /** * TCP_USER_TIMEOUT Connection idle timeout, to resolve prolonged Lettuce client timeouts * refer: https://github.com/lettuce-io/lettuce-core/issues/2082 */ private static final int TCP_USER_TIMEOUT = 30; @Bean public RedisConnectionFactory redisConnectionFactory(LettuceClientConfiguration clientConfiguration) { RedisStandaloneConfiguration standaloneConfiguration = new RedisStandaloneConfiguration(); standaloneConfiguration.setHostName(redisHost); standaloneConfiguration.setPort(redisPort); standaloneConfiguration.setDatabase(redisDatabase); standaloneConfiguration.setPassword(redisPassword); LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(standaloneConfiguration, clientConfiguration); connectionFactory.setDatabase(redisDatabase); // Disable connection sharing to allow connection pooling to take effect. connectionFactory.setShareNativeConnection(false); return connectionFactory; } @Bean public LettuceClientConfiguration clientConfiguration() { SocketOptions socketOptions = SocketOptions.builder() .keepAlive(SocketOptions.KeepAliveOptions.builder() // Interval between two Keepalive probes .idle(Duration.ofSeconds(TCP_KEEPALIVE_TIME)) // Time when a connection must be idle before TCP Keepalive probes are sent .interval(Duration.ofSeconds(TCP_KEEPALIVE_TIME/3)) // Number of Keepalive probes before a connection is dropped .count(3) // Whether to enable Keepalive .enable() .build()) .tcpUserTimeout(SocketOptions.TcpUserTimeoutOptions.builder() // Resolve the prolonged timeouts caused by server RST. .tcpUserTimeout(Duration.ofSeconds(TCP_USER_TIMEOUT)) .enable() .build()) // Set the TCP connection timeout. .connectTimeout(Duration.ofMillis(redisConnectTimeout)) .build(); ClientOptions clientOptions = ClientOptions.builder() .autoReconnect(true) .pingBeforeActivateConnection(true) .cancelCommandsOnReconnectFailure(false) .disconnectedBehavior(ClientOptions.DisconnectedBehavior.ACCEPT_COMMANDS) .socketOptions(socketOptions) .build(); LettucePoolingClientConfiguration clientConfiguration = LettucePoolingClientConfiguration.builder() .poolConfig(poolConfig()) .commandTimeout(Duration.ofMillis(redisReadTimeout)) .clientOptions(clientOptions) // You do not need to set readFrom for Proxy Cluster instances. .readFrom(ReadFrom.MASTER) .build(); return clientConfiguration; } private GenericObjectPoolConfig redisPoolConfig() { GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); // Minimum number of connections in the connection pool poolConfig.setMinIdle(redisPoolMinSize); // Maximum number of idle connections in the connection pool poolConfig.setMaxIdle(redisPoolMaxSize); // Maximum number of connections in the connection pool poolConfig.setMaxTotal(redisPoolMaxSize); // Whether to wait for an available connection when the connection pool is exhausted. The default value true indicates to wait. setMaxWait takes effect only when the value is true. poolConfig.setBlockWhenExhausted(true); // Maximum wait time for obtaining a connection from the pool when the pool is exhausted. The default value -1 indicates to wait indefinitely for a connection to become available. poolConfig.setMaxWait(Duration.ofMillis(redisPoolMaxWaitMillis)); // Whether to validate a new connection using a ping command after it is created. The default value is false. poolConfig.setTestOnCreate(false); // Whether to validate a connection using a ping command every time a connection is borrowed from the pool. The default value is false. When the service traffic is heavy, you are advised to set this parameter to false to reduce overhead. poolConfig.setTestOnBorrow(true); // Whether to validate a connection using a ping command every time a connection is returned to the pool. The default value is false. When the service traffic is heavy, you are advised to set this parameter to false to reduce overhead. poolConfig.setTestOnReturn(false); // Whether to check for idle connections. If the value is false, idle connections are not evicted. poolConfig.setTestWhileIdle(true); // Duration after which an idle connection is evicted. If the actual idle duration of a connection is greater than this value and the number of idle connections is greater than the minimum number of idle connections, the connection is directly evicted. poolConfig.setSoftMinEvictableIdleTime(Duration.ofMillis(redisPoolSoftMinEvictableIdleTimeMillis)); // Disable eviction of idle connections based on MinEvictableIdleTimeMillis. poolConfig.setMinEvictableIdleTime(Duration.ofMillis(-1)); // Interval for checking and evicting idle connections. The default value is 60s. poolConfig.setTimeBetweenEvictionRuns(Duration.ofMillis(redisPoolBetweenEvictionRunsMillis)); return poolConfig; } }
- Configuration for Cluster instances
import java.time.Duration; import java.util.ArrayList; import java.util.List; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisClusterConfiguration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisNode; import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import io.lettuce.core.ClientOptions; import io.lettuce.core.SocketOptions; import io.lettuce.core.cluster.ClusterClientOptions; import io.lettuce.core.cluster.ClusterTopologyRefreshOptions; /** * Lettuce Cluster non-pooling configuration (use either this or the application.properties configuration) */ @Configuration public class RedisConfiguration { @Value("${redis.cluster.nodes}") private String redisClusterNodes; @Value("${redis.cluster.maxDirects:3}") private Integer redisClusterMaxDirects; @Value("${redis.password:}") private String redisPassword; @Value("${redis.connect.timeout:2000}") private Integer redisConnectTimeout = 2000; @Value("${redis.read.timeout:2000}") private Integer redisReadTimeout = 2000; @Value("${redis.cluster.topology.refresh.period.millis:10000}") private Integer redisClusterTopologyRefreshPeriodMillis = 10000; /** * TCP_KEEPALIVE configuration parameters: * Interval between two Keepalive probes = TCP_KEEPALIVE_TIME = 30 * Time when a connection must be idle before TCP Keepalive probes are sent = TCP_KEEPALIVE_TIME/3 = 10 * Number of Keepalive probes before a connection is dropped = TCP_KEEPALIVE_COUNT = 3 */ private static final int TCP_KEEPALIVE_TIME = 30; /** * TCP_USER_TIMEOUT Connection idle timeout, to resolve prolonged Lettuce client timeouts * refer: https://github.com/lettuce-io/lettuce-core/issues/2082 */ private static final int TCP_USER_TIMEOUT = 30; @Bean public RedisConnectionFactory redisConnectionFactory(LettuceClientConfiguration clientConfiguration) { RedisClusterConfiguration clusterConfiguration = new RedisClusterConfiguration(); List<RedisNode> clusterNodes = new ArrayList<>(); for (String clusterNodeStr : redisClusterNodes.split(",")) { String[] nodeInfo = clusterNodeStr.split(":"); clusterNodes.add(new RedisNode(nodeInfo[0], Integer.valueOf(nodeInfo[1]))); } clusterConfiguration.setClusterNodes(clusterNodes); clusterConfiguration.setPassword(redisPassword); clusterConfiguration.setMaxRedirects(redisClusterMaxDirects); LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(clusterConfiguration, clientConfiguration); return connectionFactory; } @Bean public LettuceClientConfiguration clientConfiguration() { SocketOptions socketOptions = SocketOptions.builder() .keepAlive(SocketOptions.KeepAliveOptions.builder() // Interval between two Keepalive probes .idle(Duration.ofSeconds(TCP_KEEPALIVE_TIME)) // Time when a connection must be idle before TCP Keepalive probes are sent .interval(Duration.ofSeconds(TCP_KEEPALIVE_TIME/3)) // Number of Keepalive probes before a connection is dropped .count(3) // Whether to enable Keepalive .enable() .build()) .tcpUserTimeout(SocketOptions.TcpUserTimeoutOptions.builder() // Resolve the prolonged timeouts caused by server RST. .tcpUserTimeout(Duration.ofSeconds(TCP_USER_TIMEOUT)) .enable() .build()) // Set the TCP connection timeout. .connectTimeout(Duration.ofMillis(redisConnectTimeout)) .build(); ClusterTopologyRefreshOptions topologyRefreshOptions = ClusterTopologyRefreshOptions.builder() .enableAllAdaptiveRefreshTriggers() .enablePeriodicRefresh(Duration.ofMillis(redisClusterTopologyRefreshPeriodMillis)) .build(); ClusterClientOptions clientOptions = ClusterClientOptions.builder() .autoReconnect(true) .pingBeforeActivateConnection(true) .cancelCommandsOnReconnectFailure(false) .disconnectedBehavior(ClientOptions.DisconnectedBehavior.ACCEPT_COMMANDS) .socketOptions(socketOptions) .topologyRefreshOptions(topologyRefreshOptions) .build(); LettuceClientConfiguration clientConfiguration = LettuceClientConfiguration.builder() .commandTimeout(Duration.ofMillis(redisReadTimeout)) .readFrom(ReadFrom.MASTER) .clientOptions(clientOptions) .build(); return clientConfiguration; } } - Cluster instance pooling configuration Importing pooling components
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> <version>2.11.1</version> </dependency>Code configuration
import java.time.Duration; import java.util.ArrayList; import java.util.List; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisClusterConfiguration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisNode; import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration; import io.lettuce.core.ClientOptions; import io.lettuce.core.SocketOptions; import io.lettuce.core.cluster.ClusterClientOptions; import io.lettuce.core.cluster.ClusterTopologyRefreshOptions; /** * Lettuce pooling configuration */ @Configuration public class RedisPoolConfiguration { @Value("${redis.cluster.nodes}") private String redisClusterNodes; @Value("${redis.cluster.maxDirects:3}") private Integer redisClusterMaxDirects; @Value("${redis.password:}") private String redisPassword; @Value("${redis.connect.timeout:2000}") private Integer redisConnectTimeout = 2000; @Value("${redis.read.timeout:2000}") private Integer redisReadTimeout = 2000; @Value("${redis.cluster.topology.refresh.period.millis:10000}") private Integer redisClusterTopologyRefreshPeriodMillis = 10000; @Value("${redis.pool.minSize:50}") private Integer redisPoolMinSize = 50; @Value("${redis.pool.maxSize:200}") private Integer redisPoolMaxSize = 200; @Value("${redis.pool.maxWaitMillis:2000}") private Integer redisPoolMaxWaitMillis = 2000; @Value("${redis.pool.softMinEvictableIdleTimeMillis:1800000}") private Integer redisPoolSoftMinEvictableIdleTimeMillis = 30 * 60 * 1000; @Value("${redis.pool.timeBetweenEvictionRunsMillis:60000}") private Integer redisPoolBetweenEvictionRunsMillis = 60 * 1000; /** * TCP_KEEPALIVE configuration parameters: * Interval between two Keepalive probes = TCP_KEEPALIVE_TIME = 30 * Time when a connection must be idle before TCP Keepalive probes are sent = TCP_KEEPALIVE_TIME/3 = 10 * Number of Keepalive probes before a connection is dropped = TCP_KEEPALIVE_COUNT = 3 */ private static final int TCP_KEEPALIVE_TIME = 30; /** * TCP_USER_TIMEOUT Connection idle timeout, to resolve prolonged Lettuce client timeouts * refer: https://github.com/lettuce-io/lettuce-core/issues/2082 */ private static final int TCP_USER_TIMEOUT = 30; @Bean public RedisConnectionFactory redisConnectionFactory(LettuceClientConfiguration clientConfiguration) { RedisClusterConfiguration clusterConfiguration = new RedisClusterConfiguration(); List<RedisNode> clusterNodes = new ArrayList<>(); for (String clusterNodeStr : redisClusterNodes.split(",")) { String[] nodeInfo = clusterNodeStr.split(":"); clusterNodes.add(new RedisNode(nodeInfo[0], Integer.valueOf(nodeInfo[1]))); } clusterConfiguration.setClusterNodes(clusterNodes); clusterConfiguration.setPassword(redisPassword); clusterConfiguration.setMaxRedirects(redisClusterMaxDirects); LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(clusterConfiguration, clientConfiguration); // Disable connection sharing to allow connection pooling to take effect. connectionFactory.setShareNativeConnection(false); return connectionFactory; } @Bean public LettuceClientConfiguration clientConfiguration() { SocketOptions socketOptions = SocketOptions.builder() .keepAlive(SocketOptions.KeepAliveOptions.builder() // Interval between two Keepalive probes .idle(Duration.ofSeconds(TCP_KEEPALIVE_TIME)) // Time when a connection must be idle before TCP Keepalive probes are sent .interval(Duration.ofSeconds(TCP_KEEPALIVE_TIME/3)) // Number of Keepalive probes before a connection is dropped .count(3) // Whether to enable Keepalive .enable() .build()) .tcpUserTimeout(SocketOptions.TcpUserTimeoutOptions.builder() // Resolve the prolonged timeouts caused by server RST. .tcpUserTimeout(Duration.ofSeconds(TCP_USER_TIMEOUT)) .enable() .build()) // Set the TCP connection timeout. .connectTimeout(Duration.ofMillis(redisConnectTimeout)) .build(); ClusterTopologyRefreshOptions topologyRefreshOptions = ClusterTopologyRefreshOptions.builder() .enableAllAdaptiveRefreshTriggers() .enablePeriodicRefresh(Duration.ofMillis(redisClusterTopologyRefreshPeriodMillis)) .build(); ClusterClientOptions clientOptions = ClusterClientOptions.builder() .autoReconnect(true) .pingBeforeActivateConnection(true) .cancelCommandsOnReconnectFailure(false) .disconnectedBehavior(ClientOptions.DisconnectedBehavior.ACCEPT_COMMANDS) .socketOptions(socketOptions) .topologyRefreshOptions(topologyRefreshOptions) .build(); LettucePoolingClientConfiguration clientConfiguration = LettucePoolingClientConfiguration.builder() .poolConfig(poolConfig()) .commandTimeout(Duration.ofMillis(redisReadTimeout)) .clientOptions(clientOptions) .readFrom(ReadFrom.MASTER) .build(); return clientConfiguration; } private GenericObjectPoolConfig poolConfig() { GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); // Minimum number of connections in the connection pool poolConfig.setMinIdle(redisPoolMinSize); // Maximum number of idle connections in the connection pool poolConfig.setMaxIdle(redisPoolMaxSize); // Maximum number of connections in the connection pool poolConfig.setMaxTotal(redisPoolMaxSize); // Whether to wait for an available connection when the connection pool is exhausted. The default value true indicates to wait. setMaxWait takes effect only when the value is true. poolConfig.setBlockWhenExhausted(true); // Maximum wait time for obtaining a connection from the pool when the pool is exhausted. The default value -1 indicates to wait indefinitely for a connection to become available. poolConfig.setMaxWait(Duration.ofMillis(redisPoolMaxWaitMillis)); // Whether to validate a new connection using a ping command after it is created. The default value is false. poolConfig.setTestOnCreate(false); // Whether to validate a connection using a ping command every time a connection is borrowed from the pool. The default value is false. When the service traffic is heavy, you are advised to set this parameter to false to reduce overhead. poolConfig.setTestOnBorrow(true); // Whether to validate a connection using a ping command every time a connection is returned to the pool. The default value is false. When the service traffic is heavy, you are advised to set this parameter to false to reduce overhead. poolConfig.setTestOnReturn(false); // Whether to check for idle connections. If the value is false, idle connections are not evicted. poolConfig.setTestWhileIdle(true); // Validate connections while they are idle in the pool. poolConfig.setMinEvictableIdleTime(Duration.ofMillis(-1)); // Duration after which an idle connection is evicted. If the actual idle duration of a connection is greater than this value and the number of idle connections is greater than the minimum number of idle connections, the connection is directly evicted without following the default eviction policy MinEvictableIdleTimeMillis. poolConfig.setSoftMinEvictableIdleTime(Duration.ofMillis(redisPoolSoftMinEvictableIdleTimeMillis)); // Interval for checking and evicting idle connections. The default value is 60s. poolConfig.setTimeBetweenEvictionRuns(Duration.ofMillis(redisPoolBetweenEvictionRunsMillis)); return poolConfig; } }
(Optional) SSL Connection Configuration
If SSL is enabled for the instance, use the following content to replace the LettuceClientConfiguration constructor clientConfiguration() in Bean-based Configuration for connecting to the instance via SSL. For details about whether your Redis instances support SSL, see Transmitting DCS Redis Data with SSL Encryption.
- Configuration for single-node, master/standby, read/write splitting, and Proxy Cluster instances
@Bean public LettuceClientConfiguration clientConfiguration() { SocketOptions socketOptions = SocketOptions.builder() .keepAlive(SocketOptions.KeepAliveOptions.builder() // Interval between two Keepalive probes .idle(Duration.ofSeconds(TCP_KEEPALIVE_TIME)) // Time when a connection must be idle before TCP Keepalive probes are sent .interval(Duration.ofSeconds(TCP_KEEPALIVE_TIME/3)) // Number of Keepalive probes before a connection is dropped .count(3) // Whether to enable Keepalive .enable() .build()) .tcpUserTimeout(SocketOptions.TcpUserTimeoutOptions.builder() // Resolve the prolonged timeouts caused by server RST. .tcpUserTimeout(Duration.ofSeconds(TCP_USER_TIMEOUT)) .enable() .build()) // Set the TCP connection timeout. .connectTimeout(Duration.ofMillis(redisConnectTimeout)) .build(); SslOptions sslOptions = SslOptions.builder() .trustManager(new File(certificationPath)) .build(); ClientOptions clientOptions = ClientOptions.builder() .sslOptions(sslOptions) .autoReconnect(true) .pingBeforeActivateConnection(true) .cancelCommandsOnReconnectFailure(false) .disconnectedBehavior(ClientOptions.DisconnectedBehavior.ACCEPT_COMMANDS) .socketOptions(socketOptions) .build(); LettuceClientConfiguration clientConfiguration = LettuceClientConfiguration.builder() .commandTimeout(Duration.ofMillis(redisReadTimeout)) // You do not need to set readFrom for Proxy Cluster instances. .readFrom(ReadFrom.MASTER) .clientOptions(clientOptions) .useSsl() .build(); return clientConfiguration; } - Configuration for Cluster instances
@Bean public LettuceClientConfiguration clientConfiguration() { SocketOptions socketOptions = SocketOptions.builder() .keepAlive(SocketOptions.KeepAliveOptions.builder() // Interval between two Keepalive probes .idle(Duration.ofSeconds(TCP_KEEPALIVE_TIME)) // Time when a connection must be idle before TCP Keepalive probes are sent .interval(Duration.ofSeconds(TCP_KEEPALIVE_TIME/3)) // Number of Keepalive probes before a connection is dropped .count(3) // Whether to enable Keepalive .enable() .build()) .tcpUserTimeout(SocketOptions.TcpUserTimeoutOptions.builder() // Resolve the prolonged timeouts caused by server RST. .tcpUserTimeout(Duration.ofSeconds(TCP_USER_TIMEOUT)) .enable() .build()) // Set the TCP connection timeout. .connectTimeout(Duration.ofMillis(redisConnectTimeout)) .build(); SslOptions sslOptions = SslOptions.builder() .trustManager(new File(certificationPath)) .build(); ClusterTopologyRefreshOptions topologyRefreshOptions = ClusterTopologyRefreshOptions.builder() .enableAllAdaptiveRefreshTriggers() .enablePeriodicRefresh(Duration.ofMillis(redisClusterTopologyRefreshPeriodMillis)) .build(); ClusterClientOptions clientOptions = ClusterClientOptions.builder() .sslOptions(sslOptions) .autoReconnect(true) .pingBeforeActivateConnection(true) .cancelCommandsOnReconnectFailure(false) .disconnectedBehavior(ClientOptions.DisconnectedBehavior.ACCEPT_COMMANDS) .socketOptions(socketOptions) .topologyRefreshOptions(topologyRefreshOptions) .build(); LettuceClientConfiguration clientConfiguration = LettuceClientConfiguration.builder() .commandTimeout(Duration.ofMillis(redisReadTimeout)) .readFrom(ReadFrom.MASTER) .clientOptions(clientOptions) .useSsl() .build(); return clientConfiguration; }
Parameters
| Parameter | Type | Default Value | Description |
|---|---|---|---|
| configuration | RedisConfiguration | - | Redis connection configuration. The following two subclasses are commonly used:
|
| clientConfiguration | LettuceClientConfiguration | - | Client configuration. The following subclass is commonly used: LettucePoolingClientConfiguration (used for pooling) |
| shareNativeConnection | boolean | true | Whether to use shared connections. The default value is true. If a connection pool is used, set this parameter to false. |
| Parameter | Default Value | Description |
|---|---|---|
| hostName | localhost | IP address/domain name for connecting to a DCS Redis instance. |
| port | 6379 | Port number for setting up the connection. |
| database | 0 | Database index. |
| password | - | Password for connecting to a DCS Redis instance. If password-free access is enabled for the instance, you do not need to enter the password. If you forget the password or need to reset it, see Resetting an Instance Password.
|
| Parameter | Description |
|---|---|
| clusterNodes | Cluster node connection information, including the node IP address and port number. |
| maxRedirects | Maximum number of Cluster redirections. The recommended value is 3. |
| password | Password for connecting to a DCS Redis instance. If password-free access is enabled for the instance, you do not need to enter the password. If you forget the password or need to reset it, see Resetting an Instance Password.
|
| Parameter | Type | Default Value | Description |
|---|---|---|---|
| timeout | Duration | 60s | Command timeout: The recommended value is 2s. |
| clientOptions | ClientOptions | - | Configuration options. |
| readFrom | readFrom | MASTER | Read mode. The recommended value is MASTER. Other configurations may cause access failures in failover scenarios. |
| Parameter | Type | Default Value | Description |
|---|---|---|---|
| timeout | Duration | 60s | Command timeout: The recommended value is 2s. |
| clientOptions | ClientOptions | - | Configuration options. |
| poolConfig | GenericObjectPoolConfig | - | Connection pool configurations. |
| readFrom | readFrom | MASTER | Read mode. The recommended value is MASTER. Other configurations may cause access failures in failover scenarios. |
| Parameter | Type | Default Value | Description |
|---|---|---|---|
| autoReconnect | boolean | true | Whether to automatically initiate a reconnection after a disconnection. The recommended value is true. |
| pingBeforeActivateConnection | boolean | true | Whether to use the PING/PONG mechanism to test connectivity after a connection is created. The recommended value is true. |
| cancelCommandsOnReconnectFailure | boolean | true | Whether to cancel the commands in the queue when the reconnection fails. The recommended value is false. |
| disconnectedBehavior | DisconnectedBehavior | DisconnectedBehavior.DEFAULT | Action to be taken when the connection is dropped. The recommended value is ACCEPT_COMMANDS.
|
| socketOptions | SocketOptions | - | Network configurations. |
| Parameter | Default Value | Description |
|---|---|---|
| connectTimeout | 10s | Connection timeout: The recommended value is 2s. |
| Parameter | Default Value | Description |
|---|---|---|
| minIdle | - | Minimum number of connections in the connection pool. |
| maxIdle | - | Maximum number of idle connections in the connection pool. |
| maxTotal | - | Maximum number of connections in the connection pool. |
| blockWhenExhausted | true | Whether to wait for an available connection when the connection pool is exhausted. The default value true indicates to wait. maxWaitMillis takes effect only when this parameter is set to true. |
| maxWaitMillis | -1 | Maximum wait time for obtaining a connection from the pool when the pool is exhausted. The default value -1 indicates to wait indefinitely for a connection to become available. |
| testOnCreate | false | Whether to validate a new connection using a ping command after it is created. The default value is false. |
| testOnBorrow | false | Whether to validate a connection using a ping command every time a connection is borrowed from the pool. The default value is false. When the service traffic is heavy, you are advised to set this parameter to false to reduce overhead. |
| testOnReturn | false | Whether to validate a connection using a ping command every time a connection is returned to the pool. The default value is false. When the service traffic is heavy, you are advised to set this parameter to false to reduce overhead. |
| testWhileIdle | false | Whether to check for idle connections. If the value is false, idle connections are not evicted. The recommended value is true. |
| softMinEvictableIdleTimeMillis | -1 | Duration after which an idle connection is evicted, in milliseconds. If the actual idle duration of a connection is greater than this value and the number of idle connections is greater than the minimum number of idle connections, the connection is directly evicted. The recommended value is 1800000. |
| minEvictableIdleTimeMillis | 1800000 | Minimum time a connection may remain idle in the pool before it is eligible for eviction. The recommended value is -1, indicating that this policy is disabled, and the softMinEvictableIdleTimeMillis policy is used. |
| timeBetweenEvictionRunsMillis | -1 | Interval for checking and evicting idle connections, in milliseconds. The recommended value is 60000. |
Recommended DCS Instance Configurations
- Connection pooling
Unlike Jedis relying on the Blocking I/O (BIO) model, Lettuce communicates with the Redis server via an underlying Netty-based Non-blocking I/O (NIO) framework. By leveraging long-lived connections and command queues, Lettuce utilizes TCP's ordered delivery to enable request pipelining. While a single connection can sustain 3000 to 5000 QPS, it is recommended to keep the production traffic no more than 3000 QPS. Lettuce does not support pooling, and pooling is disabled by default in Spring Boot. To enable pooling, you need to manually import the commons-pool2 component and disable LettuceConnectionFactory.shareNativeConnection (connection sharing).
By default, each Lettuce connection requires an I/O thread pool and a computation thread pool to support I/O event reads and asynchronous event processing. If you configure Lettuce with a connection pool, every connection spins up two thread pools, leading to excessive memory overhead. Due to Lettuce's underlying model implementation and its efficient processing for single connections, you are not advised to use Lettuce with a connection pool.
- Topology refresh
When connecting to a Redis Cluster instance, Lettuce randomly selects a node from the seed list and executes CLUSTER NODES during initialization to obtain the cluster's slot topology. Subsequent operations such as cluster scaling and master/standby switchover will cause topology changes. By default, Lettuce is unaware of these changes. You need to manually enable adaptive topology refresh.
- Configuration based on the application.properties file
# Enable adaptive topology refresh. spring.redis.lettuce.cluster.refresh.adaptive=true # Allow the topology to be refreshed every 10 seconds. spring.redis.lettuce.cluster.refresh.period=10S
- Configuration by calling APIs
ClusterTopologyRefreshOptions topologyRefreshOptions = ClusterTopologyRefreshOptions.builder() .enableAllAdaptiveRefreshTriggers() .enablePeriodicRefresh(Duration.ofMillis(redisClusterTopologyRefreshPeriodMillis)) .build(); ClusterClientOptions clientOptions = ClusterClientOptions.builder() ... ... .topologyRefreshOptions(topologyRefreshOptions) .build();
- Configuration based on the application.properties file
- Blast radius
Lettuce couples single long-lived connections with command queues in its underlying design. Any network jitter, intermittent disconnection, or connection deadness will adversely affect all requests. In particular, if a connection becomes inactive, TCP retransmission is triggered until the retransmission times out and the connection is torn down. Requests cannot be restored until the connection is reestablished. During the retransmission, requests continuously back up within the queue, making it highly likely for upper-layer services to experience cascading timeouts. Additionally, if the retransmission timeout is excessively long due to default OS kernel configurations, the service system may remain unavailable for an extended period. Therefore, you are advised to use Jedis instead of Lettuce.
Related Document
When accessing Redis fails, see Troubleshooting Redis Connection Failures.
What is your overall rating for this page?
Thank you very much for your feedback. We will continue working to improve the documentation.See the reply and handling status in My Cloud VOC.
For any further questions, feel free to contact us through the chatbot.
Chatbot