Production usage
Get your Lettuce app ready for production
The following sections explain how to handle situations that may occur in your production environment.
Timeouts
Lettuce provides timeouts for many operations, such as command execution, SSL handshake, and Sentinel discovery. By default, Lettuce uses a global timeout value of 60 seconds for these operations, but you can override the global timeout value with individual timeout values for each operation.
Below is an example of setting socket-level timeouts. The TCP_USER_TIMEOUT
setting is useful for scenarios where the server stops responding without acknowledging the last request, while the KEEPALIVE
setting is good for detecting dead connections where there is no traffic between the client and the server.
RedisURI redisURI = RedisURI.Builder
.redis("localhost")
// set the global default from the default 60 seconds to 30 seconds
.withTimeout(Duration.ofSeconds(30))
.build();
try (RedisClient client = RedisClient.create(redisURI)) {
// or set specific timeouts for things such as the TCP_USER_TIMEOUT and TCP_KEEPALIVE
// A good general rule of thumb is to follow the rule
// TCP_USER_TIMEOUT = TCP_KEEP_IDLE+TCP_KEEPINTVL * TCP_KEEPCNT
// in this case, 20 = 5 + 5 * 3
SocketOptions.TcpUserTimeoutOptions tcpUserTimeout = SocketOptions.TcpUserTimeoutOptions.builder()
.tcpUserTimeout(Duration.ofSeconds(20))
.enable().build();
SocketOptions.KeepAliveOptions keepAliveOptions = SocketOptions.KeepAliveOptions.builder()
.interval(Duration.ofSeconds(5))
.idle(Duration.ofSeconds(5))
.count(3).enable().build();
SocketOptions socketOptions = SocketOptions.builder()
.tcpUserTimeout(tcpUserTimeout)
.keepAlive(keepAliveOptions)
.build();
client.setOptions(ClientOptions.builder()
.socketOptions(socketOptions)
.build());
StatefulRedisConnection<String, String> connection = client.connect();
System.out.println(connection.sync().ping());
}
Cluster topology refresh
The Redis Cluster configuration is dynamic and can change at runtime. New nodes may be added, and the primary node for a specific slot can shift. Lettuce automatically handles MOVED and ASK redirects, but to enhance your application's resilience, you should enable adaptive topology refreshing:
RedisURI redisURI = RedisURI.Builder
.redis("localhost")
// set the global default from the default 60 seconds to 30 seconds
.withTimeout(Duration.ofSeconds(30))
.build();
// Create a RedisClusterClient with adaptive topology refresh
try (RedisClusterClient clusterClient = RedisClusterClient.create(redisURI)) {
// Enable TCP keep-alive and TCP user timeout just like in the standalone example
SocketOptions.TcpUserTimeoutOptions tcpUserTimeout = SocketOptions.TcpUserTimeoutOptions.builder()
.tcpUserTimeout(Duration.ofSeconds(20))
.enable()
.build();
SocketOptions.KeepAliveOptions keepAliveOptions = SocketOptions.KeepAliveOptions.builder()
.interval(Duration.ofSeconds(5))
.idle(Duration.ofSeconds(5))
.count(3)
.enable()
.build();
SocketOptions socketOptions = SocketOptions.builder()
.tcpUserTimeout(tcpUserTimeout)
.keepAlive(keepAliveOptions)
.build();
// Enable adaptive topology refresh
// Configure adaptive topology refresh options
ClusterTopologyRefreshOptions topologyRefreshOptions = ClusterTopologyRefreshOptions.builder()
.enableAllAdaptiveRefreshTriggers()
.adaptiveRefreshTriggersTimeout(Duration.ofSeconds(30))
.build();
ClusterClientOptions options = ClusterClientOptions.builder()
.topologyRefreshOptions(topologyRefreshOptions)
.socketOptions(socketOptions).build();
clusterClient.setOptions(options);
StatefulRedisClusterConnection<String, String> connection = clusterClient.connect();
System.out.println(connection.sync().ping());
connection.close();
}
Learn more about topology refresh configuration settings in the reference guide.
DNS cache and Redis
When you connect to a Redis server with multiple endpoints, such as Redis Enterprise Active-Active, you must disable the JVM's DNS cache. If a server node or proxy fails, the IP address for any database affected by the failure will change. When this happens, your app will keep trying to use the stale IP address if DNS caching is enabled.
Use the following code to disable the DNS cache:
java.security.Security.setProperty("networkaddress.cache.ttl","0");
java.security.Security.setProperty("networkaddress.cache.negative.ttl", "0");