Codebeispiele für Clientbibliotheken

Auf dieser Seite finden Sie Codebeispiele für Memorystore for Valkey-Instanzen, die sowohl den Clustermodus aktiviert als auch den Clustermodus deaktiviert haben.

Codebeispiele für den aktivierten Clustermodus

Memorystore for Valkey ist mit allen Clientcodebeispielen für Memorystore for Redis Cluster kompatibel:

  • Codebeispiele für die Clientbibliothek von Memorystore for Redis Cluster
  • Codebeispiele für die Verbindung zur Clientbibliothek von Memorystore for Redis Cluster

Valkey GLIDE

Valkey General Language Independent Driver for the Enterprise (GLIDE) ist eine Open-Source-Clientbibliothek, die alle Valkey-Befehle unterstützt.

Mit Valkey GLIDE können Sie Ihre Anwendungen mit Memorystore for Valkey-Instanzen verbinden. Valkey GLIDE wurde für Zuverlässigkeit, optimierte Leistung und hohe Verfügbarkeit entwickelt.

Um die Konsistenz bei der Anwendungsentwicklung und beim Betrieb zu gewährleisten, wird Valkey GLIDE mit einem in Rust geschriebenen Core-Treiber-Framework mit sprachspezifischen Erweiterungen implementiert. Dieses Design sorgt für Konsistenz bei den Funktionen über verschiedene Sprachen hinweg und reduziert die Komplexität.

Valkey GLIDE unterstützt die Valkey-Versionen 7.2, 8.0 und 9.0. Es ist für die folgenden Sprachen verfügbar:

Andere Valkey OSS-Clientbibliotheken

Neben Valkey GLIDE ist Memorystore for Valkey mit den folgenden Valkey OSS-Clientbibliotheken kompatibel:

Systeme und Dienste

Mit Spring Boot, PostgreSQL und Memorystore for Valkey können Sie die folgenden Systeme und Dienste erstellen:

  • Sitzungsverwaltungssystem: Die Sitzungsverwaltung ist ein wichtiger Bestandteil moderner Webanwendungen, da sie dafür sorgt, dass Nutzerinteraktionen über mehrere Anfragen hinweg konsistent und sicher bleiben. Mit einer Caching-Ebene kann Ihre Anwendung Nutzersitzungen effizient verwalten und gleichzeitig die Last auf Ihrer Datenbank reduzieren und die Skalierbarkeit gewährleisten.
  • Skalierbares Bestenlistensystem: Bestenlisten sind eine nützliche Möglichkeit, Rankingdaten in Anwendungen anzuzeigen. Mit einer Caching-Ebene können Sie Bestenlisten-Rankings in Echtzeit bereitstellen und gleichzeitig die Datenbanklast reduzieren.
  • Leistungsstarker Caching-Dienst: Moderne Anwendungen müssen schnelle, reaktionsschnelle Nutzererlebnisse im großen Maßstab bieten. Durch die Entwicklung dieses Caching-Dienstes können Sie sowohl die Latenz als auch die Datenbanklast reduzieren.

Codebeispiele für den deaktivierten Clustermodus

Memorystore for Valkey mit deaktiviertem Clustermodus ist mit allen Redis- und Valkey OSS-Clientbibliotheken kompatibel, die unter Codebeispiele für den aktivierten Clustermodus aufgeführt sind.

Wenn Sie eine Instanz mit deaktiviertem Clustermodus in Memorystore for Valkey verwenden, führen Sie die folgenden Schritte aus:

  • Verwenden Sie anstelle des RedisCluster- oder ValkeyCluster-Clientobjekts, das die Bibliothek bereitstellt, das Redis- oder Valkey-Clientobjekt.
  • Erstellen Sie einen Writer-Client mit der IP-Adresse des primären Endpunkts.
  • Erstellen Sie einen Reader-Client mit der IP-Adresse des Reader-Endpunkts.

redis-py

Wir empfehlen die Verwendung von redis-py, Version 5.1 und höher.

import redis
primaryEndpoint = PRIMARY_ENDPOINT_IP
readerEndpoint = READER_ENDPOINT_IP

primary_client = redis.Redis(host=primaryEndpoint, port=6379, db=0, decode_responses=True)
reader_client = redis.Redis(host=readerEndpoint, port=6379, db=0, decode_responses=True)

primary_client.set("key","value")
print(reader_client.get("key"))

go-redis

Wir empfehlen die Verwendung von go-redis, Versionen 9.11.0 und höher.

package main

import (
"context"
"fmt"
"github.com/redis/go-redis/v9"
)

func main() {
primary_endpoint := PRIMARY_ENDPOINT_IP
reader_endpoint := READER_ENDPOINT_IP

primary_client := redis.NewClient(&redis.Options{
  Addr:     primary_endpoint,
  Password: "", // no password set
  DB:       0,  // use default DB
})

reader_client := redis.NewClient(&redis.Options{
  Addr:     reader_endpoint,
  Password: "", // no password set
  DB:       0,  // use default DB
})

ctx := context.Background()

err := primary_client.Set(ctx, "foo", "bar", 0).Err()
if err != nil {
  panic(err)
}

val, err := reader_client.Get(ctx, "foo").Result()
if err != nil {
  panic(err)
}
fmt.Println("foo", val)
}

Jedis

Wir empfehlen die Verwendung von Jedis, Version 4.4.0 und höher.


package org.example;

import java.io.*;
import java.time.LocalDateTime;
import java.lang.Thread;
import java.util.HashMap;
import java.util.Map;

import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

public class Main
{
public static void main( String[] args )
{
  primaryEndpoint = PRIMARY_ENDPOINT_IP

  JedisPool pool = new JedisPool(primaryEndpoint, 6379);

  try (Jedis jedis = pool.getResource()) {
    jedis.set("foo", "bar");
    System.out.println(jedis.get("foo")); // prints bar

    Map hash = new HashMap<>();;
    hash.put("name", "John");
    hash.put("surname", "Smith");
    hash.put("company", "Redis");
    hash.put("age", "29");
    jedis.hset("user-session:123", hash);
    System.out.println(jedis.hgetAll("user-session:123"));
    // Prints: {name=John, surname=Smith, company=Redis, age=29}
  } catch (Exception e) {
    System.out.println("Error setting or getting  key: " + e.getMessage());
  }
}
}

Node.js

Wir empfehlen die Verwendung von Node.js, Versionen 24.4.1 und höher.

import { createClient } from 'redis';
import * as fs from 'fs';

const primaryEndpoint = PRIMARY_ENDPOINT_IP

const primary_endpoint_url ='redis://primaryEndpoint:6379'

const client = createClient({
url: primary_endpoint_url
});

await client.connect();
await client.set(key, value);
const retval = await client.get(key);
console.log(retval)

Codebeispiel für IAM-Authentifizierung und Verschlüsselung bei der Übertragung

In diesem Abschnitt wird ein Beispiel dafür gegeben, wie Sie sich mit verschiedenen Clientbibliotheken bei einer Memorystore for Valkey-Instanz authentifizieren und eine Verbindung zu ihr herstellen können, indem Sie sowohl die IAM-Authentifizierung als auch die Verschlüsselung bei der Übertragung verwenden.

redis-py

Wir empfehlen die Verwendung von redis-py, Version 5.1 und höher.

from google.cloud import iam_credentials_v1
from redis.backoff import ConstantBackoff
from redis.retry import Retry
from redis.exceptions import (
ConnectionError,
AuthenticationWrongNumberOfArgsError,
AuthenticationError
)
from redis.utils import (str_if_bytes)

import redis

service_account="projects/-/serviceAccounts/<TO-DO-1: your service account that used to authenticate to Valkey>""

host=<TO-DO-2: your Redis Cluster discovery endpoint ip>
ssl_ca_certs=<TO-DO-3, your trusted server ca file name>

def generate_access_token():
  # Create a client
  client = iam_credentials_v1.IAMCredentialsClient()

  # Initialize request argument(s)
  request = iam_credentials_v1.GenerateAccessTokenRequest(
      name=service_account,
      scope=['https://www.googleapis.com/auth/cloud-platform'],
  )

  # Make the request
  response = client.generate_access_token(request=request)
  print(str(response.access_token))

  # Handle the response
  return str(response.access_token)

class ValkeyTokenProvider(redis.CredentialProvider):

    # Generated IAM tokens are valid for 15 minutes
    def get_credentials(self):
        token= generate_access_token()
        return "default",token

creds_provider = ValkeyTokenProvider()
client = redis.Redis(host=host, port=6379, credential_provider=creds_provider, ssl=True, ssl_ca_certs=caFilePath)
client.set('foo',"bar")
print(client.get('foo'))

Go

Wir empfehlen die Verwendung von Go, Version 1.24.5 und höher.

package main

import (
  "context"
  "crypto/tls"
  "crypto/x509"
  "flag"
  "fmt"
  "io/ioutil"
  "log"
  "sync"
  "time"

  credentials "google.golang.org/genproto/googleapis/iam/credentials/v1"

  "github.com/golang/protobuf/ptypes"
  "github.com/redis/go-redis/v9"
  "google.golang.org/api/option"
  gtransport "google.golang.org/api/transport/grpc"
)

var (
  svcAccount               = flag.String("a", "projects/-/serviceAccounts/example-service-account@example-project.iam.gserviceaccount.com", "service account email")
  lifetime                 = flag.Duration("d", time.Hour, "lifetime of token")
  refreshDuration          = flag.Duration("r", 5*time.Minute, "token refresh duration")
  checkTokenExpiryInterval = flag.Duration("e", 10*time.Second, "check token expiry interval")
  lastRefreshInstant       = time.Time{}
  errLastSeen              = error(nil)
  token                    = ""
  mu                       = sync.RWMutex{}
  err                      = error(nil)
)

func retrieveToken() (string, error) {
  ctx := context.Background()
  conn, err := gtransport.Dial(ctx,
    option.WithEndpoint("iamcredentials.googleapis.com:443"),
    option.WithScopes("https://www.googleapis.com/auth/cloud-platform"))

  if err != nil {
    log.Printf("Failed to dial API, error: %v", err)
    return token, err
  }
  client := credentials.NewIAMCredentialsClient(conn)
  req := credentials.GenerateAccessTokenRequest{
    Name:     *svcAccount,
    Scope:    []string{"https://www.googleapis.com/auth/cloud-platform"},
    Lifetime: ptypes.DurationProto(*lifetime),
  }
  rsp, err := client.GenerateAccessToken(ctx, &req)
  if err != nil {
    log.Printf("Failed to call GenerateAccessToken with request: %v, error: %v", req, err)
    return token, err
  }
  return rsp.AccessToken, nil
}

func refreshTokenLoop() {
  if *refreshDuration > *lifetime {
    log.Fatal("Refresh should not happen after token is already expired.")
  }
  for {
    mu.RLock()
    lastRefreshTime := lastRefreshInstant
    mu.RUnlock()
    if time.Now().After(lastRefreshTime.Add(*refreshDuration)) {
      var err error
      retrievedToken, err := retrieveToken()
      mu.Lock()
      token = retrievedToken
      if err != nil {
        errLastSeen = err
      } else {
        lastRefreshInstant = time.Now()
      }
      mu.Unlock()
    }
    time.Sleep(*checkTokenExpiryInterval)
  }
}

func retrieveTokenFunc() (string, string) {
  mu.RLock()
  defer mu.RUnlock()
  if time.Now().After(lastRefreshInstant.Add(*refreshDuration)) {
    log.Printf("Token is expired. last refresh instant: %v, refresh duration: %v, error that was last seen: %v", lastRefreshInstant, *refreshDuration, errLastSeen)
    return "", ""
  }
  username := "default"
  password := token
  return username, password
}

func main() {
  caFilePath := CA_FILE_PATH
  clusterDicEpAddr := PRIMARY_ENDPOINT_IP_ADDRESS_AND_PORT
  caCert, err := ioutil.ReadFile(caFilePath)
  if err != nil {
    log.Fatal(err)
  }
  caCertPool := x509.NewCertPool()
  caCertPool.AppendCertsFromPEM(caCert)
  token, err = retrieveToken()
  if err != nil {
    log.Fatal("Cannot retrieve IAM token to authenticate to the cluster, error: %v", err)
  }
  token, err = retrieveToken()
  fmt.Printf("token : %v", token)
  if err != nil {
    log.Fatal("Cannot retrieve IAM token to authenticate to the cluster, error: %v", err)
  }
  lastRefreshInstant = time.Now()
  go refreshTokenLoop()

  client := redis.NewClient(&redis.Options{
    Addr:                clusterDicEpAddr,
    CredentialsProvider: retrieveTokenFunc,
    TLSConfig: &tls.Config{
      RootCAs: caCertPool,
    },
  })

  ctx := context.Background()
  err = client.Set(ctx, "foo", "bar", 0).Err()
  if err != nil {
    log.Fatal(err)
  }
  val, err := client.Get(ctx, "foo").Result()
  if err != nil {
    log.Fatal(err)
  }
  fmt.Printf("\nGot the value for key: key, which is %s \n", val)
}