Exemples de code de bibliothèque cliente

Cette page fournit des exemples de code pour les instances Memorystore pour Valkey qui sont à la fois en mode cluster activé et en mode cluster désactivé.

Exemples de code pour le mode cluster activé

Memorystore pour Valkey est compatible avec tous les exemples de code client Memorystore pour Redis Cluster :

À propos de Valkey GLIDE

Valkey General Language Independent Driver for the Enterprise (GLIDE) est une bibliothèque cliente Open Source qui prend en charge toutes les commandes Valkey.

Vous pouvez utiliser Valkey GLIDE pour connecter vos applications à des instances Memorystore pour Valkey. Valkey GLIDE est conçu pour la fiabilité, les performances optimisées et la haute disponibilité.

Pour garantir la cohérence du développement et des opérations des applications, Valkey GLIDE est implémenté à l'aide d'un framework de pilote principal, écrit en Rust, avec des extensions spécifiques à chaque langage. Cette conception assure la cohérence des fonctionnalités dans toutes les langues et réduit la complexité.

Valkey GLIDE est compatible avec les versions 7.2 et 8.0 de Valkey. Il est disponible dans les langues suivantes :

Autres bibliothèques clientes Valkey OSS

En plus de Valkey GLIDE, Memorystore pour Valkey est compatible avec les bibliothèques clientes Valkey OSS suivantes :

Systèmes et services

Vous pouvez utiliser Spring Boot, PostgreSQL et Memorystore pour Valkey afin de créer les systèmes et services suivants :

  • Système de gestion des sessions : la gestion des sessions est un élément essentiel des applications Web modernes. Elle permet de garantir que les interactions des utilisateurs restent cohérentes et sécurisées pour plusieurs requêtes. En utilisant une couche de mise en cache, votre application peut gérer efficacement les sessions utilisateur tout en réduisant la charge sur votre base de données et en assurant l'évolutivité.
  • Système de classement évolutif : les classements sont un moyen utile d'afficher les données de classement dans les applications. En utilisant une couche de mise en cache, vous pouvez fournir des classements en temps réel tout en réduisant la charge de votre base de données.
  • Service de mise en cache hautes performances : les applications modernes doivent offrir des expériences utilisateur rapides et réactives à grande échelle. En créant ce service de mise en cache, vous pouvez réduire à la fois la latence et la charge de votre base de données.

Exemples de code pour le mode cluster désactivé

Memorystore pour Valkey en mode cluster désactivé est compatible avec toutes les bibliothèques clientes Redis et Valkey OSS listées dans Exemples de code pour le mode cluster activé.

Lorsque vous utilisez une instance en mode cluster désactivé dans Memorystore pour Valkey, effectuez les actions suivantes :

  • Au lieu de l'objet client RedisCluster ou ValkeyCluster fourni par la bibliothèque, utilisez l'objet client Redis ou Valkey.
  • Créez un client d'écriture à l'aide de l'adresse IP du point de terminaison principal.
  • Créez un client lecteur à l'aide de l'adresse IP du point de terminaison du lecteur.

redis-py

Nous vous recommandons d'utiliser redis-py, versions 5.1 et ultérieures.

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

Nous vous recommandons d'utiliser go-redis, versions 9.11.0 et ultérieures.

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)
}

Jedi

Nous vous recommandons d'utiliser Jedis, version 4.4.0 ou ultérieure.


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

Nous vous recommandons d'utiliser Node.js, versions 24.4.1 et ultérieures.

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)

Exemple de code pour l'authentification IAM et le chiffrement en transit

Cette section fournit un exemple d'authentification et de connexion à une instance Memorystore pour Valkey à l'aide de l'authentification IAM et du chiffrement en transit avec différentes bibliothèques clientes.

redis-py

Nous vous recommandons d'utiliser redis-py, versions 5.1 et ultérieures.

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

Nous vous recommandons d'utiliser Go, version 1.24.5 ou ultérieure.

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)
}