Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.
Configuración del cliente de Lettuce (Valkey y Redis OSS)
En esta sección se describen las opciones de configuración recomendadas de Java y Lettuce y cómo se aplican a ElastiCache los clústeres.
Las recomendaciones de esta sección se probaron con la versión 6.2.2 de Lettuce.
Temas
TTL de la caché DNS de Java
La máquina virtual de Java (JVM) almacena en caché las búsquedas de nombres DNS. Cuando la JVM convierte un nombre de host en una dirección IP, almacena en caché la dirección IP durante un período de tiempo específico, conocido como TTL time-to-live.
La elección del valor de TTL implica un compromiso entre latencia y la capacidad de respuesta a los cambios. Con una versión más corta TTLs, los solucionadores de DNS detectan las actualizaciones en el DNS del clúster con mayor rapidez. Esto puede hacer que la aplicación responda más rápido a las sustituciones u otros flujos de trabajo a los que se somete el clúster. Sin embargo, si el TTL es demasiado bajo, aumenta el volumen de consultas, lo que puede aumentar la latencia de la aplicación. Aunque no existe un valor de TTL correcto, vale la pena esperar a que surta efecto un cambio cuando se configura el valor de TTL.
Como ElastiCache los nodos utilizan entradas de nombres DNS que pueden cambiar, le recomendamos que configure la JVM con un TTL bajo, de 5 a 10 segundos. Con esto, se asegurará de que, cuando cambie la dirección IP de un nodo, su aplicación pueda recibir y utilizar la nueva dirección IP del recurso volviendo a consultar la entrada de DNS.
En algunas configuraciones de Java, el TTL predeterminado de JVM está establecido de forma que nunca se actualicen las entradas DNS hasta que se reinicie la JVM.
Para obtener más información sobre cómo configurar el TTL de JVM, consulte Cómo configurar el TTL de JVM.
Versión de Lettuce
Recomendamos usar la versión 6.2.2 o posterior de Lettuce.
Puntos de conexión
Cuando utilice clústeres habilitados para el modo de clúster, establezca redisUri
en el punto de conexión de configuración del clúster. La búsqueda de DNS para este URI devuelve una lista de todos los nodos disponibles en el clúster y se resuelve aleatoriamente en uno de ellos durante la inicialización del clúster. Para obtener más información sobre cómo funciona la actualización de la topología, consulte dynamicRefreshResourcesmás adelante en este tema.
SocketOption
Habilite KeepAlive
Asegúrese de configurar el Tiempo de espera de la conexión
ClusterClientOption: Opciones de cliente habilitadas para el modo de clúster
Se activa AutoReconnect
Configurar CommandTimeout
Establezca nodeFilter
Por ejemplo, una vez que finaliza una conmutación por error y el clúster inicia el proceso de recuperación, mientras se actualiza la topología del clúster, el mapa de nodos del bus del clúster tiene un breve periodo de tiempo en el que el nodo inactivo se muestra como nodo FAIL, antes de que se elimine por completo de la topología. Durante este periodo, el cliente de Lettuce lo considera un nodo en buen estado y se conecta continuamente a él. Esto provoca un error cuando se agota el reintento.
Por ejemplo:
final ClusterClientOptions clusterClientOptions = ClusterClientOptions.builder() ... // other options .nodeFilter(it -> ! (it.is(RedisClusterNode.NodeFlag.FAIL) || it.is(RedisClusterNode.NodeFlag.EVENTUAL_FAIL) || it.is(RedisClusterNode.NodeFlag.HANDSHAKE) || it.is(RedisClusterNode.NodeFlag.NOADDR))) .validateClusterNodeMembership(false) .build(); redisClusterClient.setOptions(clusterClientOptions);
nota
El filtrado de nodos se utiliza mejor si se DynamicRefreshSources establece en true. De lo contrario, si la vista de topología se toma de un solo nodo raíz problemático, que ve que un nodo principal de alguna partición está produciendo un error, filtrará este nodo principal, lo que hará que las ranuras no queden cubiertas. Tener varios nodos iniciales (si DynamicRefreshSources es cierto) reduce la probabilidad de que se produzca este problema, ya que al menos algunos de los nodos iniciales deberían tener una vista de topología actualizada tras una conmutación por error con el nodo principal recién promocionado.
ClusterTopologyRefreshOptions: Opciones para controlar la actualización de la topología del clúster del cliente con el modo de clúster activado
nota
Los clústeres desactivados en modo de clúster no admiten los comandos de detección de clústeres y no son compatibles con la funcionalidad de detección de topología dinámica de todos los clientes.
El modo de clúster desactivado con ElastiCache no es compatible con el de Lettuce. MasterSlaveTopologyRefresh
En cambio, para el modo de clúster desactivado puede configurar StaticMasterReplicaTopologyProvider
y proporcionar los puntos de conexión de lectura y escritura del clúster.
Para obtener más información acerca de la conexión a clústeres desactivados en modo de clúster, consulte Búsqueda de puntos de conexión de un clúster de Valkey o Redis OSS (modo de clúster deshabilitado) (consola).
Si desea utilizar la funcionalidad de detección de topología dinámica de Lettuce, puede crear un clúster habilitado para el modo de clúster con la configuración del mismo fragmento que el clúster existente. Sin embargo, para los clústeres habilitados para el modo de clúster, recomendamos configurar al menos 3 particiones con al menos 1 réplica para admitir una conmutación por error rápida.
Habilite enablePeriodicRefresh
Con esta opción habilitada, puede reducir la latencia asociada a la actualización de la topología del clúster agregando este trabajo a una tarea que se esté ejecutando en segundo plano. Aunque la actualización de la topología se realiza en un trabajo que se esté ejecutando en segundo plano, puede resultar algo lenta para los clústeres con muchos nodos. Esto se debe a que se están consultando las vistas de todos los nodos para obtener la vista de clúster más actualizada. Si ejecuta un clúster grande, es posible que desee aumentar el periodo.
Habilite enableAllAdaptiveRefreshTriggers
Habilite closeStaleConnections
Habilite dynamicRefreshResources
El uso de la actualización dinámica consulta todos los nodos detectados para la topología del clúster e intenta elegir la vista de clúster más precisa. Si se establece en falso, solo se utilizan los nodos raíz iniciales como orígenes para la detección de la topología y el número de clientes se obtiene solo para los nodos raíz iniciales. Cuando se desactiva, si el punto de conexión de la configuración del clúster se resuelve como un nodo con errores, se produce un error al intentar actualizar la vista del clúster y se producen excepciones. Este escenario se puede producir porque pasa algún tiempo hasta que la entrada de un nodo con errores se elimina del punto de conexión de la configuración del clúster. Por lo tanto, el punto de conexión de la configuración aún se puede resolver aleatoriamente en un nodo erróneo durante un breve periodo de tiempo.
Sin embargo, cuando se habilita, utilizamos todos los nodos del clúster que se reciben de la vista de clústeres para consultar la vista actual. Como filtramos los nodos con errores de esa vista, la actualización de la topología se realizará correctamente. Sin embargo, cuando dynamicRefreshSources es cierto, Lettuce consulta todos los nodos para obtener la vista del clúster y, a continuación, compara los resultados. Por lo tanto, puede resultar caro para los clústeres con muchos nodos. Le sugerimos que desactive esta característica para los clústeres con muchos nodos.
final ClusterTopologyRefreshOptions topologyOptions = ClusterTopologyRefreshOptions.builder() .enableAllAdaptiveRefreshTriggers() .enablePeriodicRefresh() .dynamicRefreshSources(true) .build();
ClientResources
Configurar DnsResolver
Configure reconnectDelay
ClientResources clientResources = DefaultClientResources.builder() .dnsResolver(new DirContextDnsResolver()) .reconnectDelay( Delay.fullJitter( Duration.ofMillis(100), // minimum 100 millisecond delay Duration.ofSeconds(10), // maximum 10 second delay 100, TimeUnit.MILLISECONDS)) // 100 millisecond base .build();
Tiempos de espera
Utilice un valor de tiempo de espera de conexión inferior al tiempo de espera del comando. Lettuce utiliza un establecimiento de conexión diferida. Por lo tanto, si el tiempo de espera de conexión es superior al tiempo de espera del comando, puede producirse un periodo de error persistente tras una actualización de la topología si Lettuce intenta conectarse a un nodo en mal estado y siempre se supera el tiempo de espera del comando.
Utilice un tiempo de espera de comando dinámico para diferentes comandos. Le recomendamos que establezca el tiempo de espera del comando en función de la duración esperada del comando. Por ejemplo, utilice un tiempo de espera más largo para los comandos que se repiten en varias claves, como los scripts FLUSHDB, FLUSHALL, KEYS, SMEMBERS o Lua. Utilice tiempos de espera más cortos para los comandos de una sola clave, como SET, GET y HSET.
nota
Los tiempos de espera que se configuran en el siguiente ejemplo son para pruebas que ejecutaron comandos SET/GET con claves y valores de hasta 20 bytes de longitud. El tiempo de procesamiento puede ser mayor cuando los comandos son complejos o las claves y los valores son más grandes. Debe establecer los tiempos de espera en función del caso de uso de la aplicación.
private static final Duration META_COMMAND_TIMEOUT = Duration.ofMillis(1000); private static final Duration DEFAULT_COMMAND_TIMEOUT = Duration.ofMillis(250); // Socket connect timeout should be lower than command timeout for Lettuce private static final Duration CONNECT_TIMEOUT = Duration.ofMillis(100); SocketOptions socketOptions = SocketOptions.builder() .connectTimeout(CONNECT_TIMEOUT) .build(); class DynamicClusterTimeout extends TimeoutSource { private static final Set<ProtocolKeyword> META_COMMAND_TYPES = ImmutableSet.<ProtocolKeyword>builder() .add(CommandType.FLUSHDB) .add(CommandType.FLUSHALL) .add(CommandType.CLUSTER) .add(CommandType.INFO) .add(CommandType.KEYS) .build(); private final Duration defaultCommandTimeout; private final Duration metaCommandTimeout; DynamicClusterTimeout(Duration defaultTimeout, Duration metaTimeout) { defaultCommandTimeout = defaultTimeout; metaCommandTimeout = metaTimeout; } @Override public long getTimeout(RedisCommand<?, ?, ?> command) { if (META_COMMAND_TYPES.contains(command.getType())) { return metaCommandTimeout.toMillis(); } return defaultCommandTimeout.toMillis(); } } // Use a dynamic timeout for commands, to avoid timeouts during // cluster management and slow operations. TimeoutOptions timeoutOptions = TimeoutOptions.builder() .timeoutSource( new DynamicClusterTimeout(DEFAULT_COMMAND_TIMEOUT, META_COMMAND_TIMEOUT)) .build();