

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 客户端最佳实践（Valkey 和 Redis OSS）
<a name="BestPractices.Clients.redis"></a>

了解常见场景的最佳实践，并遵循一些最常用的开源 Valkey 和 Redis OSS 客户端库（redis-py、PHPRedis 和 Lettuce）的代码示例，以及有关使用常用开源 Memcached 客户端库与 ElastiCache 资源进行交互的最佳实践。

**Topics**
+ [大量连接（Valkey 和 Redis OSS）](BestPractices.Clients.Redis.Connections.md)
+ [集群客户端发现和指数回退（Valkey 和 Redis OSS）](BestPractices.Clients.Redis.Discovery.md)
+ [配置客户端超时（Valkey 和 Redis OSS）](BestPractices.Clients.Redis.ClientTimeout.md)
+ [配置服务器端空闲超时（Valkey 和 Redis OSS）](BestPractices.Clients.Redis.ServerTimeout.md)
+ [Lua 脚本](BestPractices.Clients.Redis.LuaScripts.md)
+ [存储大型复合项目（Valkey 和 Redis OSS）](BestPractices.Clients.Redis.LargeItems.md)
+ [Lettuce 客户端配置（Valkey 和 Redis OSS）](BestPractices.Clients-lettuce.md)
+ [为双堆栈集群配置首选协议（Valkey 和 Redis OSS）](#network-type-configuring-dual-stack-redis)

## 为双堆栈集群配置首选协议（Valkey 和 Redis OSS）
<a name="network-type-configuring-dual-stack-redis"></a>

对于启用了集群模式的 Valkey 或 Redis OSS 集群，您可以使用 IP 发现参数控制客户端将用于连接到集群中的节点的协议。IP 发现参数可以设置为 IPv4 或 IPv6。

对于 Valkey 或 Redis OSS 集群，IP 发现参数可设置 [cluster slots ()](https://valkey.io/commands/cluster-slots/)、[cluster shards ()](https://valkey.io/commands/cluster-shards/) 和 [cluster nodes ()](https://valkey.io/commands/cluster-nodes/) 输出中使用的 IP 协议。客户端使用这些命令来发现集群拓扑。客户端使用这些命令中的 IP 连接到集群中的其他节点。

更改 IP 发现不会导致连接的客户端出现任何停机。但是，更改需要一些时间才能传播。要确定 Valkey 或 Redis OSS 集群的更改何时完全传播，请监控 `cluster slots` 的输出。一旦 cluster slots 命令返回的所有节点报告了使用新协议的 IP，就表明更改完成了传播。

使用 Redis-Py 的示例：

```
cluster = RedisCluster(host="xxxx", port=6379)
target_type = IPv6Address # Or IPv4Address if changing to IPv4

nodes = set()
while len(nodes) == 0 or not all((type(ip_address(host)) is target_type) for host in nodes):
    nodes = set()

   # This refreshes the cluster topology and will discovery any node updates.
   # Under the hood it calls cluster slots
    cluster.nodes_manager.initialize()
    for node in cluster.get_nodes():
        nodes.add(node.host)
    self.logger.info(nodes)

    time.sleep(1)
```

使用 Lettuce 的示例：

```
RedisClusterClient clusterClient = RedisClusterClient.create(RedisURI.create("xxxx", 6379));

Class targetProtocolType = Inet6Address.class; // Or Inet4Address.class if you're switching to IPv4

Set<String> nodes;
    
do {
   // Check for any changes in the cluster topology.
   // Under the hood this calls cluster slots
    clusterClient.refreshPartitions();
    Set<String> nodes = new HashSet<>();

    for (RedisClusterNode node : clusterClient.getPartitions().getPartitions()) {
        nodes.add(node.getUri().getHost());
    }

    Thread.sleep(1000);
} while (!nodes.stream().allMatch(node -> {
            try {
                return finalTargetProtocolType.isInstance(InetAddress.getByName(node));
            } catch (UnknownHostException ignored) {}
            return false;
}));
```