Questa pagina fornisce indicazioni sull'utilizzo ottimale di Memorystore for Redis. Questa pagina segnala anche i potenziali problemi da evitare.
Per un elenco di scenari di risoluzione dei problemi, consulta Risoluzione dei problemi.
Best practice per l'alta affidabilità e la durabilità dei dati
Ti consigliamo di utilizzare il livello Standard come meccanismo principale per l'alta affidabilità (HA). Il livello Standard fornisce un'istanza ad alta affidabilità con più repliche e consente un recupero rapido utilizzando il failover automatico in caso di errore dell'istanza principale. Inoltre, l'attivazione degli snapshot RDB sulle istanze di livello Standard fornisce una protezione aggiuntiva dagli errori dei nodi.
In alcuni scenari, potresti anche voler assicurarti di poter recuperare i dati dai backup degli snapshot. In questi scenari, i backup e la possibilità di ripristinare i dati dagli snapshot RDB possono fornire una protezione aggiuntiva contro la perdita di dati.
Se abiliti gli snapshot RDB e devi recuperare i dati, Memorystore for Redis può farlo dall'ultimo snapshot. Questi snapshot sono solo per il recupero interno del sistema e non puoi accedervi.
Limitazioni e best practice relative alla durabilità
Sebbene il livello Standard fornisca l'alta affidabilità tramite la replica e il failover automatico, l'alta affidabilità non garantisce la completa durabilità dei dati. Memorystore for Redis non può fornire una durabilità completa dei dati anche con l'alta affidabilità abilitata durante determinati eventi catastrofici, come errori temporanei a livello di regione.
Per proteggere i tuoi dati e fornire un livello di persistenza di base, gli snapshot RDB sono abilitati per impostazione predefinita quando crei un'istanza Memorystore for Redis utilizzando la console Google Cloud .
Per i workload di produzione, prendi in considerazione le seguenti best practice per migliorare ulteriormente la resilienza dei dati:
- Disaster recovery: Memorystore for Redis non supporta la replica tra regioni. Se la tua strategia di ripristino di emergenza richiede la replica tra regioni per una vera resilienza a livello di regione, ti consigliamo di utilizzare un'istanza Memorystore for Valkey. Per saperne di più sulla configurazione e sulla gestione delle istanze secondarie tra regioni, consulta Utilizza la replica tra regioni nella documentazione di Memorystore for Valkey.
- Durabilità massima: se la tua applicazione richiede il livello più alto possibile di durabilità dei dati, ti consigliamo di utilizzare un'istanza Memorystore for Valkey configurata con replica tra regioni, backup giornalieri automatici e persistenza Append-Only File (AOF). Questa combinazione offre la protezione più efficace contro la perdita di dati. Per saperne di più, consulta la Panoramica della persistenza nella documentazione di Memorystore for Valkey.
Best practice per la pianificazione della capacità
Per assicurarti di poter eseguire correttamente il provisioning delle risorse e creare architetture resilienti, ti consigliamo di seguire queste best practice per la pianificazione della capacità:
- Esegui il deployment in più località: se non riesci a creare un'istanza nella tua zona preferita a causa di vincoli temporanei delle risorse, prova a crearla in un'altra zona all'interno della stessa regione o in un'altra regione.
- Utilizza l'accesso tra regioni: configura i client in modo che accedano alle istanze che si trovano in regioni diverse. Se devi eseguire il provisioning di un'istanza che si trova in una regione diversa a causa di vincoli delle risorse locali, i client possono connettersi all'istanza.
- Scegli un livello di capacità diverso: se riscontri vincoli di risorse a causa delle dimensioni di un'istanza, seleziona un livello di capacità diverso o ridimensiona l'istanza. Per saperne di più, consulta Prestazioni del livello di capacità.
Esportazione RDB
Quando esporti un backup RDB, segui queste indicazioni:
- Esegui l'esportazione durante un periodo di bassa frequenza di scrittura.
- Se l'esportazione avviene durante un periodo di frequenza di scrittura elevata, riduci temporaneamente la configurazione di
maxmemoryal 50% della capacità dell'istanza per fornire un overhead sufficiente per un'operazione riuscita.
Operazioni ad alta intensità di risorse
Per le istanze Redis di livello Standard, le seguenti operazioni utilizzano memoria aggiuntiva per la durata dell'operazione:
L'upgrade della versione, la scalabilità e il failover manuale utilizzano memoria aggiuntiva (per le istanze di livello Standard) a causa della replica. Queste operazioni seguono il processo di replica descritto in Comportamento dell'upgrade delle istanze di livello Standard.
Le operazioni di importazione ed esportazione richiedono memoria aggiuntiva a causa del processo Redis con fork e della gestione dei dati copy-on-write associata a queste operazioni.
Per mitigare gli svantaggi delle operazioni ad alta intensità di risorse, devi:
- Riduci la configurazione maxmemory all'80% della capacità dell'istanza per la durata dell'operazione. In questo modo, l'overhead è sufficiente per un'operazione riuscita.
- Monitora la metrica relativa al rapporto di utilizzo della memoria utilizzata di sistema e assicurati che sia inferiore all'80% prima di eseguire una di queste operazioni.
- Esegui queste operazioni durante i periodi di traffico ridotto delle istanze (ad esempio di notte o nel fine settimana).
- Implementa una logica di ripetizione con backoff esponenziale prima di eseguire queste operazioni.
Operazioni e scenari che richiedono un nuovo tentativo di connessione
Le seguenti operazioni e scenari interrompono la connessione di rete tra la tua rete e l'istanza Redis:
- Upgrade della versione
- Scale up/down
- Importazione
- Failover manuale
- Manutenzione del sistema
- Rotazione delle autorità di certificazione per le istanze Redis con crittografia in transito abilitata
- Failover di emergenza
Queste operazioni modificano l'istanza, richiedendo un'interruzione temporanea della connessione. Prima di eseguire queste operazioni, devi disporre di una logica di ripetizione con backoff esponenziale, in modo che l'applicazione si riconnetta automaticamente e continui a funzionare normalmente.
Manutenzione di routine
Le istanze Memorystore for Redis vengono sottoposte periodicamente a manutenzione. Per maggiori dettagli, consulta la policy di manutenzione di Memorystore for Redis.
Implementa le seguenti best practice per prepararti alla manutenzione di routine:
- Imposta un periodo di manutenzione durante il quale possono essere eseguiti gli aggiornamenti di manutenzione.
- Pianifica i periodi di manutenzione in momenti di traffico ridotto dell'istanza e di overhead di memoria sufficiente. Per saperne di più, consulta Impatto degli aggiornamenti di manutenzione.
- Attiva le notifiche relative ai periodi di manutenzione per ricevere avvisi sulla manutenzione imminente.
- Implementa una logica di ripetizione con backoff esponenziale.
- Per le istanze di livello Standard, puoi simulare un evento di manutenzione utilizzando il failover manuale per vedere in che modo il failover causato dalla manutenzione influisce sulla tua applicazione.
- Per le istanze di livello Base, puoi simulare l'impatto di un aggiornamento di manutenzione scalando temporaneamente l'istanza a una dimensione maggiore. Dopo aver osservato l'impatto, puoi tornare alle dimensioni originali.
Gestione della memoria
La gestione della memoria può essere una sfida a causa della nota frammentazione della memoria che si verifica con Redis open source. Ti consigliamo di ridurre la configurazione di maxmemory per la tua istanza in modo da avere un overhead in caso di pressione elevata sulla memoria.
Il modo migliore per monitorare la pressione sulla memoria della tua istanza Memorystore è utilizzare la metrica Rapporto di utilizzo della memoria di sistema. Per una guida più dettagliata su come gestire la memoria per Memorystore for Redis, consulta Best practice di gestione della memoria.
Gestione delle connessioni inattive
Nel tempo, potresti notare un aumento del numero di connessioni alla tua istanza Memorystore se le connessioni non vengono terminate correttamente. Ciò può avere implicazioni negative sulle prestazioni, soprattutto se utilizzi la crittografia dei dati in transito, che impone limiti massimi di connessioni in base al livello di capacità. Per mitigare questo problema, ti consigliamo di utilizzare il parametro di configurazione Redis timeout, che ti consente di impostare il numero di secondi prima che le connessioni client inattive vengano terminate automaticamente.
Nomi delle risorse di Access Transparency
I dati sensibili non devono essere archiviati nei nomi delle risorse Memorystore for Redis. Per nomi delle risorse intendiamo i nomi delle istanze Memorystore for Redis e i metadati delle istanze, come i tag. Non è garantito che i dati archiviati nei nomi delle risorse siano protetti da Google Cloud Access Transparency e potrebbero essere in conflitto con i requisiti di conformità di Access Transparency della tua organizzazione.
Connettore di accesso VPC serverless richiesto per alcuni ambienti serverless
Alcuni ambienti serverless richiedono un connettore di accesso VPC serverless per connettersi a Memorystore for Redis. Se vuoi connetterti utilizzando uno di questi ambienti, configura il connettore di accesso VPC serverless per il tuo progetto.
Networking
Ti consigliamo di utilizzare la modalità di connessione con accesso privato ai servizi. Memorystore for Redis utilizza due modalità di connessione: accesso privato ai servizi e peering diretto. La modalità di connessione di accesso privato ai servizi semplifica la gestione degli intervalli IP e ti consente di utilizzare il VPC condiviso, se vuoi.
Una volta creata un'istanza, la modalità di connessione non può essere modificata.
Per maggiori dettagli, consulta Networking.
Monitoraggio e avvisi
Ti consigliamo di utilizzare il monitoraggio e gli avvisi perché ti forniscono indicatori chiave sulla memoria utilizzata dalla tua istanza Redis. Inoltre, forniscono insight sull'efficienza con cui l'istanza Redis risponde alle richieste di cache in entrata.
Ti consigliamo di configurare i seguenti avvisi predefiniti:
- Impostazione di un avviso di Cloud Monitoring per la memoria utilizzata
- Impostazione di un avviso di Cloud Monitoring per la percentuale di memoria utilizzata dal sistema
Best practice per l'utilizzo della CPU
L'utilizzo improprio di comandi Redis costosi comporta latenza elevata, mancata risposta o problemi di connettività. Le istanze di livello Standard forniscono l'alta affidabilità durante ripristino di emergenza e si basano sulla replica asincrona tra i nodi primari e di replica. Se uno dei nodi ha un'elaborazione di comandi costosa che blocca il thread principale di Redis, la replica potrebbe essere interessata. Se il problema persiste e si verifica un'interruzione della località, i dati più recenti scritti nella località dell'interruzione potrebbero non essere disponibili nell'altra località.
Ti consigliamo di utilizzare Cloud Monitoring per impostare avvisi per la metrica Secondi di CPU del thread principale (redis.googleapis.com/stats/cpu_utilization_main_thread) per assicurarti che l'utilizzo della CPU non superi 0,8 secondi per il nodo principale o 0,5 secondi per ogni nodo di replica, quando la replica è designata come replica di lettura.
Se l'istanza Redis supera i valori consigliati, ti consigliamo di scalare l'istanza a un livello di capacità superiore o di seguire le istruzioni per la risoluzione dei problemi per evitare operazioni che richiedono un utilizzo intensivo della CPU.
Se l'istanza registra un utilizzo elevato della CPU o se le risorse dell'istanza si esauriscono (ad esempio, se sono presenti troppe connessioni), l'istanza potrebbe non funzionare correttamente e le metriche esterne potrebbero non essere presenti.
Comandi ad alta intensità di risorse
Ti consigliamo vivamente di evitare di utilizzare comandi Redis che richiedono un uso intensivo delle risorse. L'utilizzo di questi comandi potrebbe causare i seguenti problemi di prestazioni:
- Latenza elevata e timeout del client
- Pressione della memoria causata da comandi che aumentano la memoria utilizzata
- Perdita di dati durante la replica e la sincronizzazione dei nodi perché il thread principale di Redis è bloccato
- Controlli di integrità, osservabilità e replica con risorse insufficienti
La tabella seguente elenca esempi di comandi Redis che richiedono un utilizzo intensivo delle risorse e fornisce alternative efficienti in termini di risorse.
| Category | Comando che richiede un utilizzo intensivo delle risorse | Alternativa efficiente in termini di risorse |
|---|---|---|
| Esegui per l'intero keyspace | KEYS |
SCAN |
| Esegui per un set di chiavi di lunghezza variabile | LRANGE |
Limita le dimensioni dell'intervallo che utilizzi per una query. |
ZRANGE |
Limita le dimensioni dell'intervallo che utilizzi per una query. | |
HGETALL |
HSCAN |
|
SMEMBERS |
SSCAN |
|
| Blocca l'esecuzione di uno script | EVAL |
Assicurati che lo script non venga eseguito a tempo indeterminato. |
EVALSHA |
Assicurati che lo script non venga eseguito a tempo indeterminato. | |
| Rimuovi file e link | DEL |
UNLINK |
| Pubblica e sottoscrivi | PUBLISH |
SPUBLISH |
SUBSCRIBE |
SSUBSCRIBE |
Best practice per i client Redis
Questa sezione fornisce indicazioni sull'utilizzo ottimale del client Redis.
Rileva e gestisci le connessioni che non rispondono
Ti consigliamo vivamente di configurare l'applicazione client in modo che rilevi le connessioni non reattive a Memorystore for Redis. Quando viene rilevata una connessione che non risponde, il client deve reimpostarla. Per creare un'applicazione resiliente, ti consigliamo le seguenti configurazioni client:
- Configura i parametri TCP keep-alive: imposta i parametri
TCP keepalive time,TCP keepalive intervaleTCP keepalive probesin modo che i client rilevino e interrompano in modo proattivo le connessioni che non rispondono, anche quando sono inattive. Ad esempio, se imposti il parametroTCP keepalive timesu 30 secondi,TCP keepalive intervalsu 10 secondi eTCP keepalive probessu 3, i client reimpostano le connessioni inattive che non rispondono entro un minuto. - Configura i timeout utente TCP: imposta questo timeout nei client per reimpostare le connessioni con richieste in sospeso e interrompere la risposta. Ad esempio, se imposti il timeout su 15 secondi, i client reimpostano le connessioni che non rispondono e che hanno richieste in sospeso dopo 15 secondi.
Best practice specifiche per i clienti
Se fai lo scale out delle tue applicazioni, potresti riscontrare errori READONLY sui comandi di scrittura. Memorystore for Redis utilizza un deployment non Sentinel con endpoint statici e i client non ricevono in anticipo informazioni dinamiche sui ruoli.
Se utilizzi una singola connessione client sia per l'endpoint primario che per quello della replica, il client potrebbe inviare accidentalmente comandi di scrittura alla replica di sola lettura. La replica restituisce un errore READONLY perché non può elaborare i comandi di scrittura.
Per evitare un routing errato delle scritture, non utilizzare una singola connessione sia per le letture che per le scritture. Suddividi invece le operazioni creando le seguenti istanze client separate:
- Client principale: si connette solo all'endpoint principale
- Client di replica: si connette solo all'endpoint di replica
Le seguenti schede mostrano come configurare i modelli separati in Go, Java, Node.js e Python.
Vai
package main import ( "context" "fmt" "github.com/redis/go-redis/v9" ) func main() { ctx := context.Background() // Initialize the primary client connecting only to the primary endpoint primaryClient := redis.NewClient(&redis.Options{ Addr: "PRIMARY_HOST:6379", Password: "YOUR_PASSWORD", DB: 0, }) defer primaryClient.Close() // Initialize the replica client connecting only to the replica endpoint replicaClient := redis.NewClient(&redis.Options{ Addr: "REPLICA_HOST:6379", Password: "YOUR_PASSWORD", DB: 0, }) defer replicaClient.Close() // Use the primary client for all mutating commands err := primaryClient.Set(ctx, "example_key", "example_value", 0).Err() if err != nil { fmt.Printf("Failed to write to primary: %v\n", err) } // Use the replica client for all read-only commands val, err := replicaClient.Get(ctx, "example_key").Result() if err != nil { fmt.Printf("Failed to read from replica: %v\n", err) } else { fmt.Printf("Successfully read value: %s\n", val) } }
Java
@Bean public RedisConnectionFactory primaryConnectionFactory() { RedisStandaloneConfiguration config = new RedisStandaloneConfiguration("PRIMARY_HOST", 6379); config.setPassword(RedisPassword.of("YOUR_PASSWORD")); return new LettuceConnectionFactory(config); } @Bean public RedisConnectionFactory replicaConnectionFactory() { RedisStaticMasterReplicaConfiguration config = new RedisStaticMasterReplicaConfiguration("PRIMARY_HOST", 6379); config.addNode("REPLICA_HOST", 6379); config.setPassword(RedisPassword.of("YOUR_PASSWORD")); LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder() .readFrom(ReadFrom.REPLICA_PREFERRED) .build(); return new LettuceConnectionFactory(config, clientConfig); } @Bean public RedisTemplate<String, Object> primaryRedisTemplate( @Qualifier("primaryConnectionFactory") RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(factory); return template; } @Bean public RedisTemplate<String, Object> replicaRedisTemplate( @Qualifier("replicaConnectionFactory") RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(factory); return template; }
Node.js
import { createClient } from 'redis'; async function main() { // Initialize the primary client connecting only to the primary endpoint const primaryClient = createClient({ url: 'redis://PRIMARY_HOST:6379', password: 'YOUR_PASSWORD' }); // Initialize the replica client connecting only to the replica endpoint const replicaClient = createClient({ url: 'redis://REPLICA_HOST:6379', password: 'YOUR_PASSWORD' }); primaryClient.on('error', (err) => console.error('Primary Client Error', err)); replicaClient.on('error', (err) => console.error('Replica Client Error', err)); await primaryClient.connect(); await replicaClient.connect(); // Use the primary client for all mutating commands try { await primaryClient.set('example_key', 'example_value'); console.log('Successfully wrote to primary'); } catch (err) { console.error('Failed to write to primary:', err); } // Use the replica client for all read-only commands try { const val = await replicaClient.get('example_key'); console.log(`Successfully read value: ${val}`); } catch (err) { console.error('Failed to read from replica:', err); } await primaryClient.disconnect(); await replicaClient.disconnect(); } main();
Python
import redis def main(): # Initialize the primary client connecting only to the primary endpoint primary_client = redis.Redis( host='PRIMARY_HOST', port=6379, password='YOUR_PASSWORD', decode_responses=True ) # Initialize the replica client connecting only to the replica endpoint replica_client = redis.Redis( host='REPLICA_HOST', port=6379, password='YOUR_PASSWORD', decode_responses=True ) # Use the primary client for all mutating commands try: primary_client.set('example_key', 'example_value') print('Successfully wrote to primary') except redis.RedisError as e: print(f'Failed to write to primary: {e}') # Use the replica client for all read-only commands try: val = replica_client.get('example_key') print(f'Successfully read value: {val}') except redis.RedisError as e: print(f'Failed to read from replica: {e}') if __name__ == '__main__': main()