生产环境使用

让您的 Lettuce 应用做好生产准备

以下部分解释了如何处理生产环境中可能发生的情况。

超时

Lettuce 为许多操作提供了超时设置,例如命令执行、SSL 握手和 Sentinel 发现。默认情况下,Lettuce 对这些操作使用全局超时值 60 秒,但您可以为每个操作使用单独的超时值来覆盖全局超时值。

提示
选择合适的超时值对于应用程序的性能和稳定性至关重要,并且因环境而异。仅当默认值出现问题时才需要配置超时。在某些情况下,默认值基于特定于环境的设置(例如,操作系统设置),而在其他情况下,它们内置在 Lettuce 驱动程序中。有关设置特定超时的更多详细信息,请参阅 Lettuce 参考指南

先决条件

要设置 TCP 级别超时,您需要确保已安装 Netty 原生传输 之一。最常见的是 netty-transport-native-epoll,用于 Linux 系统。您可以通过在 pom.xml 文件中包含以下依赖项将其添加到您的项目

<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-transport-native-epoll</artifactId>
    <version>${netty.version}</version> <!-- e.g., 4.1.118.Final -->
    <classifier>linux-x86_64</classifier>
</dependency>

安装原生传输依赖项后,您可以使用以下代码进行验证

logger.info("Lettuce epool is available: {}", EpollProvider.isAvailable());

如果上面的代码片段返回 false,您需要为 io.lettuce.coreio.netty 启用调试日志,以查看为何原生传输不可用。

有关使用 Netty 原生传输的更多信息,请参阅 Lettuce 参考指南

设置超时

下面是设置套接字级别超时的一个示例。TCP_USER_TIMEOUT 设置对于服务器停止响应而未确认最后一个请求的场景很有用,而 KEEPALIVE 设置适合检测客户端和服务器之间没有流量的死连接。

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());
}

集群拓扑刷新

Redis 集群配置是动态的,可以在运行时更改。可以添加新节点,特定槽位的主节点也可以转移。Lettuce 自动处理 MOVEDASK 重定向,但为了增强应用程序的弹性,您应启用自适应拓扑刷新

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();
}

参考指南 中了解有关拓扑刷新配置设置的更多信息。

DNS 缓存与 Redis

当您连接到具有多个端点的 Redis 服务器时,例如 Redis Enterprise Active-Active,您**必须**禁用 JVM 的 DNS 缓存。如果服务器节点或代理失败,受故障影响的任何数据库的 IP 地址将发生变化。此时,如果启用了 DNS 缓存,您的应用程序将继续尝试使用过时的 IP 地址。

使用以下代码禁用 DNS 缓存

java.security.Security.setProperty("networkaddress.cache.ttl","0");
java.security.Security.setProperty("networkaddress.cache.negative.ttl", "0");
评价本页
返回顶部 ↑