Configurazione del client Lettuce (Valkey e Redis OSS) - Amazon ElastiCache

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

Configurazione del client Lettuce (Valkey e Redis OSS)

Questa sezione descrive le opzioni di configurazione consigliate per Java e Lettuce e come si applicano ai cluster. ElastiCache

I suggerimenti in questa sezione sono stati testati con Lettuce versione 6.2.2.

TTL della cache DNS Java

Java Virtual Machine (JVM) memorizza nella cache le ricerche dei nomi DNS. Quando la JVM risolve un nome host in un indirizzo IP, memorizza l'indirizzo IP nella cache per un periodo di tempo specificato, noto come (TTL). time-to-live

La scelta di un valore TTL è un compromesso tra latenza e reattività al cambiamento. Con tempi più brevi TTLs, i resolver DNS notano gli aggiornamenti nel DNS del cluster più velocemente. Ciò può far sì che l'applicazione risponda più rapidamente alle sostituzioni o ad altri flussi di lavoro a cui è sottoposto il cluster. Tuttavia, se il TTL è troppo basso, aumenta il volume delle query, il che può aumentare la latenza dell'applicazione. Sebbene non esista un valore TTL corretto, quando si imposta il valore TTL è opportuno valutare il tempo che è possibile attendere affinché una modifica abbia effetto.

Poiché ElastiCache i nodi utilizzano voci di nome DNS che potrebbero cambiare, consigliamo di configurare la JVM con un TTL basso, compreso tra 5 e 10 secondi. In tal modo si garantisce che quando l'indirizzo IP di un nodo cambia, l'applicazione potrà ricevere e utilizzare il nuovo indirizzo IP della risorsa richiedendo la voce DNS.

In alcune configurazioni Java, il TTL predefinito di JVM è impostato in modo da non aggiornare mai le voci DNS finché JVM non viene riavviato.

Per dettagli su come impostare il TTL JVM, consulta How to set the JVM TTL (Come impostare il TTL JVM).

Versione Lettuce

Consigliamo la versione Lettuce 6.2.2 o versioni successive.

Endpoints

Quando si utilizzano cluster abilitati in modalità cluster, impostare redisUri sull'endpoint di configurazione del cluster. La ricerca DNS per questo URI restituisce un elenco di tutti i nodi disponibili nel cluster e viene risolta casualmente in uno di essi durante l'inizializzazione del cluster. Per ulteriori dettagli su come funziona l'aggiornamento della topologia, vedere più avanti in questo argomento. dynamicRefreshResources

SocketOption

Abilita le KeepAlive. L'abilitazione di questa opzione riduce la necessità di gestire le connessioni non riuscite durante il runtime del comando.

Assicurarsi di impostare il timeout di connessione in base ai requisiti dell'applicazione e al carico di lavoro. Per ulteriori informazioni, consulta la sezione relativa ai timeout più avanti in questo argomento.

ClusterClientOption: opzioni client abilitate per la modalità cluster

Abilita in AutoReconnectcaso di interruzione della connessione.

Imposta CommandTimeout. Per ulteriori dettagli, consulta la sezione relativa ai timeout più avanti in questo argomento.

Impostare NodeFilter per filtrare i nodi non riusciti dalla topologia. Lettuce salva tutti i nodi che si trovano nell'output dei "nodi del cluster" (inclusi i nodi con stato PFAIL/FAIL) nelle "partizioni" del client (note anche come partizioni). Durante il processo di creazione della topologia del cluster, tenta di connettersi a tutti i nodi della partizione. Questo comportamento di Lettuce, che consiste nell'aggiungere nodi non riusciti, può causare errori di connessione (o avvisi) quando i nodi vengono sostituiti per qualsiasi motivo.

Ad esempio, al termine di un failover e quando il cluster avvia il processo di ripristino, mentre clusterTopology si aggiorna, la mappa dei nodi del bus del cluster prevede un breve periodo di tempo in cui il nodo inattivo viene elencato come nodo non riuscito (FAIL), prima che venga completamente rimosso dalla topologia. Durante questo periodo, il client Lettuce lo considera un nodo sano e si connette continuamente ad esso. Ciò causa un errore dopo che il nuovo tentativo è esaurito.

Per esempio:

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

Il filtraggio dei nodi viene utilizzato al meglio con DynamicRefreshSources set to true. Altrimenti, se la vista della topologia viene presa da un singolo nodo di origine problematico, che rileva un nodo primario non riuscito di qualche partizione, filtrerà questo nodo primario, il che comporterà la mancata copertura degli slot. La presenza di più nodi iniziali (quando DynamicRefreshSources è vero) riduce la probabilità che si verifichi questo problema, poiché almeno alcuni nodi iniziali dovrebbero avere una vista topologica aggiornata dopo un failover con il primario appena promosso.

ClusterTopologyRefreshOptions: opzioni per controllare l'aggiornamento della topologia del cluster del client Cluster Mode Enabled

Nota

I cluster con la modalità cluster disabilitata non supportano i comandi di rilevamento del cluster e non sono compatibili con la funzionalità di rilevamento della topologia dinamica di tutti i client.

La modalità cluster disabilitata con ElastiCache non è compatibile con Lettuce's. MasterSlaveTopologyRefresh Invece, per la modalità cluster disabilitata è possibile configurare un StaticMasterReplicaTopologyProvider e fornire gli endpoint di lettura e scrittura del cluster.

Per ulteriori informazioni sulla connessione a cluster disattivati, consulta Individuazione degli endpoint (console) del cluster Valkey o Redis OSS (modalità cluster disabilitata).

Se desideri utilizzare la funzionalità di rilevamento della topologia dinamica di Lettuce, puoi creare un cluster con la modalità cluster abilitata con la stessa configurazione di partizioni del cluster esistente. Tuttavia, per i cluster abilitati alla modalità cluster, consigliamo di configurare almeno 3 shard con almeno una replica per supportare il failover rapido.

Abilita le enablePeriodicRefresh. Ciò consente aggiornamenti periodici della topologia del cluster in modo che il client aggiorni la topologia del cluster negli intervalli refreshPeriod (impostazione predefinita: 60 secondi). Quando è disabilitato, il client aggiorna la topologia del cluster solo quando si verificano errori quando tenta di eseguire comandi sul cluster.

Con questa opzione abilitata, è possibile ridurre la latenza associata all'aggiornamento della topologia del cluster aggiungendo questo processo a un'attività in background. Sebbene l'aggiornamento della topologia venga eseguito in un processo in background, può essere piuttosto lento per i cluster con molti nodi. Questo perché vengono eseguite query sulle viste di tutti i nodi per ottenere la vista del cluster più aggiornata. Se si gestisce un cluster di grandi dimensioni, si potrebbe voler aumentare il periodo.

Abilita le enableAllAdaptiveRefreshTriggers. Ciò consente l'aggiornamento adattivo della topologia che utilizza tutti i trigger: MOVED_REDIRECT, ASK_REDIRECT, PERSISTENT_RECONNECTS, UNCOVERED_SLOT, UNKNOWN_NODE. I trigger di aggiornamento adattivi avviano gli aggiornamenti della visualizzazione della topologia in base agli eventi che si verificano durante le operazioni del cluster Valkey o Redis OSS. L'attivazione di questa opzione comporta un aggiornamento immediato della topologia quando si verifica uno dei trigger precedenti. Gli aggiornamenti attivati adattivi hanno una frequenza limitata mediante un timeout perché gli eventi possono verificarsi su larga scala (timeout predefinito tra gli aggiornamenti: 30).

Abilita le closeStaleConnections. Ciò consente di chiudere le connessioni obsolete durante l'aggiornamento della topologia del cluster. Entra in vigore solo se. ClusterTopologyRefreshOptions isPeriodicRefreshEnabled () è vero. Quando è abilitato, il client può chiudere le connessioni obsolete e crearne di nuove in background. Ciò riduce la necessità di gestire le connessioni non riuscite durante il runtime del comando.

Abilita le dynamicRefreshResources. Ti consigliamo di abilitarlo dynamicRefreshResources per i cluster di piccole dimensioni e di disabilitarlo per i cluster di grandi dimensioni. dynamicRefreshResourcesconsente di scoprire i nodi del cluster dal nodo iniziale fornito (ad esempio, l'endpoint di configurazione del cluster). Utilizza tutti i nodi rilevati come origine per aggiornare la topologia del cluster.

Utilizzando l'aggiornamento dinamico, esegue query su tutti i nodi rilevati per la topologia del cluster e tenta di scegliere la vista del cluster più accurata. Se è impostato su false, solo i nodi di origine iniziali vengono utilizzati come origini per l'individuazione della topologia e il numero di client viene ottenuto solo per i nodi di origine iniziali. Quando è disabilitato, se l'endpoint di configurazione del cluster viene risolto in un nodo non riuscito, il tentativo di aggiornare la vista del cluster restituisce un errore e genera delle eccezioni. Questo scenario può verificarsi perché è necessario del tempo prima che un nodo non riuscito venga rimosso dall'endpoint di configurazione del cluster. Pertanto, l'endpoint di configurazione può ancora essere risolto casualmente in un nodo non riuscito per un breve lasso di tempo.

Quando è abilitato, tuttavia, utilizziamo tutti i nodi del cluster ricevuti dalla vista del cluster per eseguire query sulla vista corrente. Poiché filtriamo i nodi non riusciti da quella vista, l'aggiornamento della topologia avverrà correttamente. Tuttavia, quando dynamicRefreshSources è vero, Lettuce interroga tutti i nodi per ottenere la visualizzazione del cluster e quindi confronta i risultati. Pertanto, l'operazione può essere costosa per i cluster con molti nodi. Consigliamo di disattivare questa funzionalità per i cluster con molti nodi.

final ClusterTopologyRefreshOptions topologyOptions = ClusterTopologyRefreshOptions.builder() .enableAllAdaptiveRefreshTriggers() .enablePeriodicRefresh() .dynamicRefreshSources(true) .build();

ClientResources

Configura DnsResolver con DirContextDnsResolver. Il resolver DNS è basato su com.sun.jndi.dns di Java. DnsContextFactory.

Configurazione di reconnectDelay con backoff esponenziale e jitter completo. Lettuce ha meccanismi di ripetizione incorporati basati sulle strategie di backoff esponenziale. Per maggiori dettagli, consulta Exponential Backoff and Jitter sul blog di architettura. AWS Per ulteriori informazioni sull'importanza di adottare una strategia di backoff tra tentativi ripetuti, consulta le sezioni sulla logica di backoff del post sulle best practice sul Database Blog. AWS

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

Timeout

Usa un valore di timeout di connessione inferiore rispetto al timeout dei comandi. Lettuce utilizza l'avvio lento della connessione. Quindi, se il timeout di connessione è superiore al timeout del comando, si può avere un periodo di errore persistente dopo un aggiornamento della topologia se Lettuce tenta di connettersi a un nodo non integro e il timeout del comando viene sempre superato.

Utilizzo di un timeout dinamico dei comandi per diversi comandi. Consigliamo di impostare il timeout dei comandi in base alla durata prevista dei comandi. Ad esempio, utilizzare un timeout più lungo per i comandi che iterano su più chiavi, come FLUSHDB, FLUSHALL, KEYS, SMEMBERS o gli script Lua. Utilizzare timeout più brevi per i comandi a chiave singola, come SET, GET e HSET.

Nota

I timeout configurati nell'esempio seguente riguardano i test che eseguono comandi SET/GET con chiavi e valori lunghi fino a 20 byte. Il tempo di elaborazione può essere più lungo quando i comandi sono complessi o le chiavi e i valori sono più grandi. È necessario impostare i timeout in base al caso d'uso dell'applicazione.

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