Exemplos de código da biblioteca de cliente

Esta página fornece exemplos de código para instâncias do Memorystore for Valkey que têm os modos Cluster Mode Enabled e Cluster Mode Disabled.

Exemplos de código para o modo de cluster ativado

O Memorystore for Valkey é compatível com todos os exemplos de código do cliente do Memorystore for Redis Cluster:

Acerca do Valkey GLIDE

O Valkey General Language Independent Driver for the Enterprise (GLIDE) é uma biblioteca cliente de código aberto e suporta todos os comandos do Valkey.

Pode usar o Valkey GLIDE para ligar as suas aplicações a instâncias do Memorystore for Valkey. O Valkey GLIDE foi concebido para oferecer fiabilidade, desempenho otimizado e elevada disponibilidade.

Para ajudar a garantir a consistência no desenvolvimento e nas operações de aplicações, o Valkey GLIDE é implementado através de uma estrutura de controlador principal, escrito em Rust, com extensões específicas do idioma. Este design garante a consistência das funcionalidades em todos os idiomas e reduz a complexidade.

O Valkey GLIDE suporta as versões 7.2 e 8.0 do Valkey. Está disponível para os seguintes idiomas:

Outras bibliotecas cliente de OSS do Valkey

Além do Valkey GLIDE, o Memorystore for Valkey é compatível com as seguintes bibliotecas cliente do Valkey OSS:

Sistemas e serviços

Pode usar o Spring Boot, o PostgreSQL e o Memorystore para Valkey para criar os seguintes sistemas e serviços:

  • Sistema de gestão de sessões: a gestão de sessões é uma parte crucial das aplicações Web modernas, que garante que as interações dos utilizadores permanecem consistentes e seguras em vários pedidos. Ao usar uma camada de colocação em cache, a sua aplicação pode gerir as sessões dos utilizadores de forma eficiente, ao mesmo tempo que reduz a carga na sua base de dados e garante a escalabilidade.
  • Sistema de tabelas de classificação escalável: as tabelas de classificação são uma forma útil de apresentar dados de classificação nas aplicações. Ao usar uma camada de colocação em cache, pode fornecer classificações em tabelas de classificação em tempo real e reduzir a carga da base de dados.
  • Serviço de colocação em cache de alto desempenho: as aplicações modernas têm de oferecer experiências do utilizador rápidas e dinâmicas em grande escala. Ao criar este serviço de colocação em cache, pode reduzir a latência e a carga da base de dados.

Exemplos de código para o modo de cluster desativado

O Memorystore for Valkey Cluster Mode Disabled é compatível com todas as bibliotecas cliente Redis e Valkey OSS indicadas em Exemplos de código para o modo de cluster ativado.

Quando usa uma instância com o modo de cluster desativado no Memorystore for Valkey, conclua as seguintes ações:

  • Em vez do objeto cliente RedisCluster ou ValkeyCluster fornecido pela biblioteca, use o objeto cliente Redis ou Valkey.
  • Crie um cliente de gravação através do endereço IP do ponto final principal.
  • Crie um cliente de leitura através do endereço IP do ponto final de leitura.

redis-py

Recomendamos que use o redis-py, versões 5.1 e posteriores.

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

Recomendamos que use o go-redis, versões 9.11.0 e posteriores.

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

Recomendamos a utilização do Jedis, versões 4.4.0 e posteriores.


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

Recomendamos que use o Node.js, versões 24.4.1 e posteriores.

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)

Exemplo de código para autenticação IAM e encriptação em trânsito

Esta secção dá um exemplo de como autenticar e estabelecer ligação a uma instância do Memorystore for Valkey usando a autenticação IAM e a encriptação em trânsito com várias bibliotecas cliente.

redis-py

Recomendamos que use o redis-py, versões 5.1 e posteriores.

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

Ir

Recomendamos que use o Go, versões 1.24.5 e posteriores.

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