Best practices for Memorystore for Redis

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.

Best Practices für Hochverfügbarkeit und Datenbeständigkeit

Wir empfehlen, die Standard-Stufe als primären Mechanismus für Hochverfügbarkeit (HA) zu verwenden. Die Standard-Stufe bietet eine hochverfügbare Instanz mit mehreren Replikaten und ermöglicht eine schnelle Wiederherstellung durch automatisches Failover, wenn die primäre Instanz ausfällt. Darüber hinaus bietet die Aktivierung von RDB-Snapshots auf Instanzen der Standard-Stufe zusätzlichen Schutz vor Knotenausfällen.

In einigen Szenarien möchten Sie möglicherweise auch sicherstellen, dass Sie Daten aus Snapshot-Sicherungen wiederherstellen können. In diesen Szenarien können Sicherungen und die Möglichkeit, Daten aus RDB-Snapshots wiederherzustellen, zusätzlichen Schutz vor Datenverlust bieten.

Wenn Sie RDB-Snapshots aktivieren und Ihre Daten wiederherstellen müssen, kann Memorystore for Redis dies aus dem neuesten Snapshot tun. Diese Snapshots sind nur für die interne Systemwiederherstellung bestimmt und Sie können nicht darauf zugreifen.

Einschränkungen der Haltbarkeit und Best Practices

Obwohl die Standard-Stufe Hochverfügbarkeit durch Replikation und automatisches Failover bietet, garantiert Hochverfügbarkeit keine vollständige Datendauerhaftigkeit. Memorystore for Redis kann auch bei aktivierter Hochverfügbarkeit keine vollständige Datendauerhaftigkeit bei bestimmten katastrophalen Ereignissen wie vorübergehenden regionalen Ausfällen bieten.

Zum Schutz Ihrer Daten und für ein grundlegendes Maß an Persistenz sind RDB-Snapshots standardmäßig aktiviert, wenn Sie eine Memorystore for Redis-Instanz über die Google Cloud Console erstellen.

Für Produktionsarbeitslasten sollten Sie die folgenden Best Practices beachten, um die Datenstabilität weiter zu verbessern:

  • Notfallwiederherstellung: Memorystore for Redis unterstützt keine regionenübergreifende Replikation. Wenn Ihre Notfallwiederherstellungsstrategie eine regionenübergreifende Replikation für echte regionale Ausfallsicherheit erfordert, empfehlen wir die Verwendung einer Memorystore for Valkey-Instanz. Weitere Informationen zum Konfigurieren und Verwalten von sekundären Instanzen in verschiedenen Regionen finden Sie in der Dokumentation zu Memorystore for Valkey unter Mit regionenübergreifender Replikation arbeiten.
  • Maximale Beständigkeit: Wenn Ihre Anwendung die höchstmögliche Datenbeständigkeit erfordert, empfehlen wir die Verwendung einer Memorystore for Valkey-Instanz, die mit regionenübergreifender Replikation, automatischen täglichen Sicherungen und AOF-Persistenz (Append-Only File) konfiguriert ist. Diese Kombination bietet den zuverlässigsten Schutz vor Datenverlust. Weitere Informationen finden Sie in der Dokumentation zu Memorystore for Valkey unter Persistenz – Übersicht.

Best Practices für die Kapazitätsplanung

Damit Sie Ressourcen erfolgreich bereitstellen und robuste Architekturen erstellen können, empfehlen wir die folgenden Best Practices für die Kapazitätsplanung:

  • An mehreren Standorten bereitstellen: Wenn Sie aufgrund vorübergehender Ressourceneinschränkungen keine Instanz in Ihrer bevorzugten Zone erstellen können, versuchen Sie, die Instanz entweder in einer anderen Zone innerhalb derselben Region oder in einer anderen Region zu erstellen.
  • Regionsübergreifenden Zugriff verwenden: Konfigurieren Sie Ihre Clients so, dass sie auf Ihre Instanzen in verschiedenen Regionen zugreifen können. Wenn Sie aufgrund lokaler Ressourcenbeschränkungen eine Instanz in einer anderen Region bereitstellen müssen, können Ihre Clients eine Verbindung zur Instanz herstellen.
  • Andere Kapazitätsstufe auswählen: Wenn aufgrund der Größe einer Instanz Ressourcenbeschränkungen auftreten, wählen Sie entweder eine andere Kapazitätsstufe aus oder ändern Sie die Größe der Instanz. Weitere Informationen finden Sie unter Leistung der Kapazitätsstufe.

RDB-Export

Beachten Sie beim Exportieren einer RDB-Sicherung die folgende Anleitung:

Ressourcenintensive Vorgänge

Bei Redis-Instanzen der Standardstufe verwenden die folgenden Vorgänge zusätzlichen Speicher für die Dauer des Vorgangs:

Durch ein Upgrade der Version, des Autoscaling und des manuellen Failovers wird aufgrund der Replikation zusätzlicher Speicher (für Instanzen der Standardstufe) verbraucht. Diese Vorgänge folgen dem Replikationsprozess, wie unter Standardverhalten der Instanz-Upgrade beschrieben.

Import- und Exportvorgänge erfordern zusätzlichen Arbeitsspeicher, da diese Vorgänge mit einem verzweigten Redis-Prozess und Copy-on-Write-Datenmanagement verbunden sind.

Zur Verringerung der Nachteile ressourcenintensiver Vorgänge sollten Sie Folgendes tun:

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:

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:

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.

Die beste Möglichkeit, die Arbeitsspeicherauslastung Ihrer Memorystore-Instanz zu überwachen, ist die Verwendung des Messwerts „Verhältnis der Arbeitsspeichernutzung des Systems“. Eine ausführliche Anleitung zur Speicherverwaltung für Memorystore for Redis finden Sie unter Best Practices für die Speicherverwaltung.

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

Sensible Daten sollten nicht in Memorystore for Redis-Ressourcennamen gespeichert werden. Mit Ressourcennamen meinen wir Memorystore for Redis-Instanznamen und Instanzmetadaten wie Tags. In Ressourcennamen gespeicherte Daten sind nicht unbedingt durch Google Cloud Access Transparency geschützt und können gegen die Access Transparency-Compliance-Anforderungen Ihrer Organisation verstoßen.

Connector für serverlosen VPC-Zugriff für einige serverlose Umgebungen erforderlich

Einige serverlose Umgebungen erfordern einen Connector für serverlosen VPC-Zugriff, 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, den Verbindungsmodus für private Dienste den Verbindungsmodus zu verwenden. 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 so wichtige Signale zur Arbeitsspeichernutzung Ihrer Redis-Instanz erhalten. Sie geben außerdem Aufschluss darüber, wie effizient Ihre Redis-Instanz auf eingehende Cache-Anfragen reagiert.

Sie sollten folgende Standardwarnungen einrichten:

Best Practices für die CPU-Nutzung

Die unsachgemäße Verwendung teurer Redis-Befehle führt zu hoher Latenz, mangelnder Reaktionsfähigkeit oder Verbindungsproblemen. Instanzen der Standard-Stufe bieten Hochverfügbarkeit während der Notfallwiederherstellung und basieren auf asynchroner Replikation zwischen primären und Replikatknoten. Wenn einer der Knoten einen rechenintensiven Befehl verarbeitet, der 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 sicherstellen, dass die CPU-Auslastung 0,8 Sekunden für den primären Knoten oder 0,5 Sekunden für jeden Replikatknoten nicht überschreitet, wenn das Replikat als Lesereplikat festgelegt ist.

Wenn Ihre Redis-Instanz die empfohlenen Werte überschreitet, sollten Sie die Instanz auf eine höhere Kapazitätsstufe skalieren oder der Anleitung zur Fehlerbehebung folgen, um CPU-intensive Vorgänge zu vermeiden.

Wenn Ihre Instanz eine hohe CPU-Auslastung aufweist oder die Ressourcen der Instanz erschöpft sind (z. B. durch zu viele Verbindungen), kann es zu Fehlern bei der Instanz kommen und externe Messwerte fehlen.

Ressourcenintensive Befehle

Wir empfehlen dringend, keine ressourcenintensiven Redis-Befehle zu verwenden. Die Verwendung dieser Befehle kann zu folgenden Leistungsproblemen führen:

  • Hohe Latenz und Client-Zeitüberschreitungen
  • Arbeitsspeichermangel, der durch Befehle verursacht wird, die die Arbeitsspeichernutzung erhöhen
  • Datenverlust während der Knotenreplikation und ‑synchronisierung, weil der Redis-Hauptthread blockiert ist
  • Nicht ausgeführte Systemdiagnosen, Beobachtbarkeit und Replikation

In der folgenden Tabelle sind Beispiele für ressourcenintensive Redis-Befehle aufgeführt und es werden ressourceneffiziente Alternativen vorgeschlagen.

Kategorie Ressourcenintensiver Befehl Ressourceneffiziente 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 Scripts blockieren EVAL Achten Sie darauf, dass Ihr Script nicht unendlich lange ausgeführt wird.
EVALSHA Achten Sie darauf, dass Ihr Script nicht unendlich lange 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 eine Anleitung 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. Zum Erstellen einer ausfallsicheren Anwendung empfehlen wir die folgenden Clientkonfigurationen:

  • TCP-Keep-Alive-Parameter konfigurieren: Legen Sie die Parameter TCP keepalive time, TCP keepalive interval und TCP keepalive probes so fest, dass Clients nicht reagierende Verbindungen proaktiv erkennen und trennen, auch wenn die Verbindungen inaktiv sind. Wenn Sie beispielsweise den Parameter TCP keepalive time auf 30 Sekunden, TCP keepalive interval auf 10 Sekunden und TCP keepalive probes auf 3 festlegen, setzen Clients nicht reagierende inaktive Verbindungen innerhalb einer Minute zurück.
  • TCP-Nutzerzeitlimits konfigurieren: Legen Sie dieses Zeitlimit in Ihren Clients fest, um Verbindungen mit ausstehenden Anfragen zurückzusetzen, die nicht mehr reagieren. Wenn Sie das Zeitlimit beispielsweise auf 15 Sekunden festlegen, setzen Clients nicht reagierende Verbindungen mit ausstehenden Anfragen nach 15 Sekunden zurück.

Clientspezifische Best Practices

Wenn Sie Ihre Anwendungen horizontal skalieren, können bei Schreibbefehlen READONLY-Fehler auftreten. Memorystore for Redis verwendet eine Nicht-Sentinel-Bereitstellung mit statischen Endpunkten. Clients erhalten keine dynamischen Rolleninformationen im Voraus. Wenn Sie eine einzelne Clientverbindung sowohl für den primären als auch für den Replikatendpunkt verwenden, sendet Ihr Client möglicherweise versehentlich Schreibbefehle an das Replikat mit Lesezugriff. Das Replikat gibt den Fehler READONLY zurück, da es keine Schreibbefehle verarbeiten kann.

Verwenden Sie nicht dieselbe Verbindung für Lese- und Schreibvorgänge, um eine fehlerhafte Weiterleitung von Schreibvorgängen zu vermeiden. Teilen Sie stattdessen Ihre Vorgänge auf, indem Sie die folgenden separaten Clientinstanzen erstellen:

  • Primärer Client: Nur mit dem primären Endpunkt verbinden
  • Replikatclient: Nur mit dem Replikatendpunkt verbinden

Auf den folgenden Tabs wird gezeigt, wie Sie die separaten 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()