Auf dieser Seite finden Sie eine Anleitung zur optimalen Verwendung von Memorystore for Redis. Diese Seite weist auch auf mögliche Probleme hin.
Eine Liste mit Szenarien zur Fehlerbehebung finden Sie unter Fehlerbehebung.
RDB-Export
Beachten Sie beim Exportieren einer RDB-Sicherung die folgende Anleitung:
- Während eines niedrigen Schreibsatzes exportieren.
- Wenn Sie während einer Periode mit hoher Schreibrate exportieren, senken Sie die
maxmemory-Konfiguration vorübergehend auf 50 % der Instanzkapazität, um genügend Overhead für eine erfolgreiche Operation bereitzustellen.
Ressourcenintensive Vorgänge
Bei Redis-Instanzen der Standardstufe wird für die folgenden Vorgänge während der Ausführung zusätzlicher Arbeitsspeicher verwendet:
Für Versionsupgrades, Skalierung und manuelles Failover wird aufgrund der Replikation zusätzlicher Arbeitsspeicher benötigt (für Instanzen der Standard-Tier). Diese Vorgänge folgen dem Replikationsprozess, wie unter Standardverhalten der Instanz-Upgrade beschrieben.
Import- und Exportvorgänge erfordern zusätzlichen Arbeitsspeicher, da der Redis-Prozess verzweigt wird und die Datenverwaltung bei diesen Vorgängen nach dem Copy-on-Write-Prinzip erfolgt.
Zur Verringerung der Nachteile ressourcenintensiver Vorgänge sollten Sie Folgendes tun:
- Verringern Sie die maxmemory-Konfiguration auf 80 % der Instanzkapazität für die Dauer des Vorgangs. Dies ist ein ausreichender Overhead für einen erfolgreichen Vorgang.
- Behalten Sie den Messwert für das Verhältnis der Systemspeichernutzung im Blick und achten Sie darauf, dass er vor dem Ausführen eines dieser Vorgänge unter 80% liegt.
- Führen Sie diese Vorgänge in Zeiten mit niedrigem Instanztraffic aus, z. B. über Nacht oder am Wochenende.
- Richten Sie eine Wiederholungslogik mit exponentiellem Backoff ein, bevor Sie diese Vorgänge ausführen.
Vorgänge und Szenarien, für die eine Verbindungswiederholung erforderlich ist
Folgende Vorgänge und Szenarien unterbrechen die Netzwerkverbindung zwischen Ihrem Netzwerk und der Redis-Instanz:
- Versionsupgrade
- Hoch-/Herunterskalieren
- Wird importiert...
- Manueller Failover
- Systemwartung
- Rotation von Zertifizierungsstellen für Redis-Instanzen mit aktivierter Verschlüsselung während der Übertragung
- Notfall-Failover
Durch diese Vorgänge wird Ihre Instanz geändert, sodass eine vorübergehende Verbindungsunterbrechung notwendig ist. Sie müssen eine Wiederholungslogik mit exponentiellem Backoff eingerichtet haben, bevor diese Vorgänge ausgeführt werden, damit Ihre Anwendung automatisch wieder eine Verbindung herstellt und weiterhin normal funktioniert.
Routinewartung
Memorystore for Redis-Instanzen werden regelmäßig gewartet. Weitere Informationen finden Sie in der Wartungsrichtlinie für Memorystore for Redis.
Setzen Sie folgende Best Practices ein, um auf routinemäßige Wartungen vorbereitet zu sein:
- Legen Sie ein Wartungsfenster fest, in dem Wartungsupdates stattfinden können.
- Planen Sie Wartungsfenster für Zeiten mit geringem Instanz-Traffic und ausreichendem Speicher-Overhead. Weitere Informationen finden Sie unter Auswirkungen von Wartungsupdates.
- Aktivieren Sie Benachrichtigungen zu Wartungsfenstern, um über bevorstehende Wartungen informiert zu werden.
- Es ist eine Wiederholungslogik mit exponentiellem Backoff erforderlich.
- Bei Instanzen der Standard-Stufe können Sie ein Wartungsereignis simulieren, indem Sie manuelles Failover verwenden, um zu sehen, wie sich das durch die Wartung verursachte Failover auf Ihre Anwendung auswirkt.
- Bei Instanzen des Basic Tier können Sie die Auswirkungen eines Wartungsupdates simulieren, indem Sie die Instanz vorübergehend skalieren. Nachdem Sie die Auswirkungen beobachtet haben, können Sie die Größe wieder auf die ursprüngliche Größe reduzieren.
Speicherverwaltung
Die Speicherverwaltung kann aufgrund der bekannten Speicherfragmentierung, die bei Open-Source-Redis auftritt, eine Herausforderung sein. Wir empfehlen Ihnen, die Konfiguration von maxmemory für Ihre Instanz zu senken, um sich im Falle eines hohen Arbeitsspeichers durch Overhead zu kümmern.
Am besten lässt sich die Arbeitsspeichersituation Ihrer Memorystore-Instanz mit dem Messwert „Verhältnis der Arbeitsspeichernutzung des Systems“ überwachen. Einen detaillierten Leitfaden zur Verwaltung des Arbeitsspeichers für Memorystore for Redis finden Sie unter Best Practices für die Arbeitsspeicherverwaltung.
Inaktive Verbindungen verwalten
Im Laufe der Zeit kann die Anzahl der Verbindungen zu Ihrer Memorystore-Instanz zunehmen, wenn Verbindungen nicht ordnungsgemäß beendet werden. Dies kann sich negativ auf die Leistung auswirken, insbesondere wenn Sie die Verschlüsselung während der Übertragung verwenden. Hierbei gelten maximale Verbindungslimits entsprechend Ihrer Kapazitätsstufe. Um dies zu vermeiden, empfehlen wir die Verwendung des Redis-Konfigurationsparameters timeout, mit dem Sie die Anzahl der Sekunden festlegen können, bevor inaktive Clientverbindungen automatisch beendet werden.
Access Transparency-Ressourcennamen
Vertrauliche Daten sollten nicht in Memorystore for Redis-Ressourcennamen gespeichert werden. Mit Ressourcennamen sind Memorystore for Redis-Instanznamen und Instanzmetadaten wie Tags gemeint. Es wird nicht garantiert, dass Daten, die in Ressourcennamen gespeichert sind, durch Google Cloud Access Transparency geschützt sind. Sie können mit den Access Transparency-Compliance-Anforderungen Ihrer Organisation in Konflikt geraten.
Connector für serverlosen VPC-Zugriff für einige serverlose Umgebungen erforderlich
In einigen serverlosen Umgebungen ist ein Connector für serverlosen VPC-Zugriff erforderlich, um eine Verbindung zu Memorystore for Redis herzustellen. Richten Sie den Connector für serverlosen VPC-Zugriff für Ihr Projekt ein, wenn Sie eine Verbindung über eine dieser Umgebungen herstellen möchten.
Netzwerk
Wir empfehlen die Verwendung des Verbindungsmodus Zugriff auf private Dienste. Memorystore for Redis verwendet zwei Verbindungsmodi: Zugriff auf private Dienste und Direct Peering. Mit dem Verbindungsmodus für den Zugriff auf private Dienste wird die Verwaltung von IP-Bereichen vereinfacht und Sie können bei Bedarf eine freigegebene VPC verwenden.
Der Verbindungsmodus kann nach dem Erstellen einer Instanz nicht mehr geändert werden.
Weitere Informationen finden Sie unter Netzwerk.
Monitoring und Warnungen
Wir empfehlen die Verwendung von Monitoring und Benachrichtigungen, da sie wichtige Signale zur Arbeitsspeichernutzung Ihrer Redis-Instanz liefern. Sie geben außerdem Aufschluss darüber, wie effizient Ihre Redis-Instanz auf eingehende Cache-Anfragen reagiert.
Sie sollten folgende Standardwarnungen einrichten:
- Cloud Monitoring-Benachrichtigung für die Arbeitsspeichernutzung festlegen
- Cloud Monitoring-Benachrichtigung für Systemspeicherauslastung einstellen
Best Practices für die CPU-Nutzung
Die unsachgemäße Verwendung von ressourcenintensiven Redis-Befehlen führt zu hoher Latenz, mangelnder Reaktionsfähigkeit oder Verbindungsproblemen. Instanzen der Standard-Stufe bieten Hochverfügbarkeit bei der Notfallwiederherstellung und basieren auf asynchroner Replikation zwischen primären und Replikatknoten. Wenn auf einem der Knoten eine aufwendige Befehlsverarbeitung stattfindet, die den Redis-Hauptthread blockiert, kann sich das auf die Replikation auswirken. Wenn das Problem weiterhin besteht und ein Standortausfall auftritt, sind die zuletzt am Standort des Ausfalls geschriebenen Daten möglicherweise nicht am anderen Standort verfügbar.
Wir empfehlen, Cloud Monitoring zu verwenden, um Benachrichtigungen für den Messwert CPU-Sekunden des Hauptthreads (redis.googleapis.com/stats/cpu_utilization_main_thread) festzulegen. So können Sie dafür sorgen, dass die CPU-Auslastung für den primären Knoten nicht mehr als 0,8 Sekunden und für jeden Replikatknoten nicht mehr als 0,5 Sekunden beträgt, wenn das Replikat als Lesereplikat festgelegt ist.
Wenn Ihre Redis-Instanz die empfohlenen Werte überschreitet, empfehlen wir, die Instanz auf eine höhere Kapazitätsstufe zu skalieren oder die Anleitung zur Fehlerbehebung zu befolgen, um CPU-intensive Vorgänge zu vermeiden.
Wenn die CPU-Auslastung Ihrer Instanz hoch ist oder die Ressourcen der Instanz erschöpft sind (z. B. durch zu viele Verbindungen), kann es sein, dass sich die Instanz nicht richtig verhält und externe Messwerte fehlen.
Ressourcenintensive Befehle
Wir empfehlen dringend, ressourcenintensive Redis-Befehle zu vermeiden. Die Verwendung dieser Befehle kann zu den folgenden Leistungsproblemen führen:
- Hohe Latenz und Client-Zeitüberschreitungen
- Arbeitsspeichermangel durch Befehle, die die Arbeitsspeichernutzung erhöhen
- Datenverlust während der Knotenreplikation und ‑synchronisierung, da der Redis-Hauptthread blockiert ist
- Systemdiagnosen, die nicht ausgeführt werden, Beobachtbarkeit und Replikation
In der folgenden Tabelle finden Sie Beispiele für ressourcenintensive Redis-Befehle und ressourcenschonende Alternativen.
| Kategorie | Ressourcenintensiver Befehl | Ressourcenschonende Alternative |
|---|---|---|
| Für den gesamten Schlüsselbereich ausführen | KEYS |
SCAN |
| Für einen Schlüsselsatz mit variabler Länge ausführen | LRANGE |
Begrenzen Sie die Größe des Bereichs, den Sie für eine Abfrage verwenden. |
ZRANGE |
Begrenzen Sie die Größe des Bereichs, den Sie für eine Abfrage verwenden. | |
HGETALL |
HSCAN |
|
SMEMBERS |
SSCAN |
|
| Ausführung eines Skripts blockieren | EVAL |
Achten Sie darauf, dass Ihr Script nicht unbegrenzt ausgeführt wird. |
EVALSHA |
Achten Sie darauf, dass Ihr Script nicht unbegrenzt ausgeführt wird. | |
| Dateien und Links entfernen | DEL |
UNLINK |
| Veröffentlichen und abonnieren | PUBLISH |
SPUBLISH |
SUBSCRIBE |
SSUBSCRIBE |
Best Practices für Redis-Clients
In diesem Abschnitt finden Sie Informationen zur optimalen Verwendung Ihres Redis-Clients.
Nicht reagierende Verbindungen erkennen und verarbeiten
Wir empfehlen dringend, Ihre Clientanwendung so zu konfigurieren, dass nicht reagierende Verbindungen zu Memorystore for Redis erkannt werden. Wenn eine nicht reagierende Verbindung erkannt wird, muss der Client sie zurücksetzen. Um eine robuste Anwendung zu erstellen, empfehlen wir die folgenden Clientkonfigurationen:
- TCP-Keep-Alive-Parameter konfigurieren: Legen Sie die Parameter
TCP keepalive time,TCP keepalive intervalundTCP keepalive probesso fest, dass Clients nicht reagierende Verbindungen proaktiv erkennen und trennen, auch wenn die Verbindungen inaktiv sind. Wenn Sie beispielsweise den ParameterTCP keepalive timeauf 30 Sekunden,TCP keepalive intervalauf 10 Sekunden undTCP keepalive probesauf 3 festlegen, werden inaktive Verbindungen, die nicht reagieren, innerhalb einer Minute zurückgesetzt. - TCP-Nutzer-Timeouts konfigurieren: Legen Sie dieses Timeout in Ihren Clients fest, um Verbindungen zurückzusetzen, für die ausstehende Anfragen vorhanden sind und die nicht mehr reagieren. Wenn Sie das Zeitlimit beispielsweise auf 15 Sekunden festlegen, werden nicht reagierende Verbindungen mit ausstehenden Anfragen nach 15 Sekunden zurückgesetzt.
Best Practices für Kunden
Wenn Sie Ihre Anwendungen horizontal skalieren, können bei Schreibbefehlen READONLY-Fehler auftreten. Memorystore for Redis verwendet eine Bereitstellung ohne Sentinel mit statischen Endpunkten und Clients erhalten keine dynamischen Rolleninformationen im Voraus.
Wenn Sie eine einzelne Clientverbindung für Ihre primären und Replikatendpunkte verwenden, kann es passieren, dass Ihr Client versehentlich Schreibbefehle an das schreibgeschützte Replikat sendet. Das Replikat gibt einen READONLY-Fehler zurück, weil es keine Schreibbefehle verarbeiten kann.
Verwenden Sie nicht eine einzelne Verbindung für Lese- und Schreibvorgänge, um Fehlleitungen von Schreibvorgängen zu vermeiden. Trennen Sie Ihre Vorgänge stattdessen, indem Sie die folgenden separaten Clientinstanzen erstellen:
- Primärer Client: Nur mit dem primären Endpunkt verbinden
- Replikatclient: Nur Verbindung zum Replikatendpunkt herstellen
Auf den folgenden Tabs sehen Sie, wie Sie die einzelnen Vorlagen in Go, Java, Node.js und Python konfigurieren.
Go
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()