Exemplos de código da biblioteca de cliente

Esta página fornece exemplos de código para instâncias do Memorystore para Valkey que têm tanto os modos de cluster ativado quanto desativado.

Exemplos de código para o modo de cluster ativado

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

Sobre o GLIDE do Valkey

O driver independente de linguagem geral do Valkey para empresas (GLIDE, na sigla em inglês) é uma biblioteca de cliente de código aberto e oferece suporte a todos os comandos do Valkey.

É possível usar o GLIDE do Valkey para conectar seus aplicativos a instâncias do Memorystore para Valkey. O GLIDE do Valkey foi projetado para confiabilidade, desempenho otimizado e alta disponibilidade.

Para garantir a consistência no desenvolvimento e nas operações de aplicativos, o GLIDE do Valkey é implementado usando uma estrutura de driver principal, escrita em Rust, com extensões específicas da linguagem. Esse design garante a consistência dos recursos em todas as linguagens e reduz a complexidade.

O GLIDE do Valkey oferece suporte às versões 7.2, 8.0 e 9.0 do Valkey. Ele está disponível para as seguintes linguagens:

Outras bibliotecas de cliente do Valkey OSS

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

Sistemas e serviços

É possível usar o Spring Boot, o PostgreSQL e o Memorystore para Valkey para criar os seguintes sistemas e serviços:

  • Sistema de gerenciamento de sessões: o gerenciamento de sessões é uma parte crucial dos aplicativos da Web modernos, garantindo que as interações do usuário permaneçam consistentes e seguras em várias solicitações. Ao usar uma camada de armazenamento em cache, o aplicativo pode gerenciar as sessões do usuário com eficiência, reduzindo a carga no banco de dados e garantindo a escalonabilidade.
  • Sistema de placar escalonável: os placares são uma maneira útil de mostrar dados de classificação em aplicativos. Ao usar uma camada de armazenamento em cache, é possível fornecer classificações de placar em tempo real, reduzindo a carga do banco de dados.
  • Serviço de armazenamento em cache de alta performance: os aplicativos modernos precisam oferecer experiências de usuário rápidas e responsivas em escala. Ao criar esse serviço de armazenamento em cache, é possível reduzir a latência e a carga do banco de dados.

Exemplos de código para o modo de cluster desativado

O Memorystore para Valkey com modo de cluster desativado é compatível com todas as bibliotecas de cliente do Redis e do Valkey OSS listadas em Exemplos de código para o modo de cluster ativado.

Ao usar uma instância com o modo de cluster desativado no Memorystore para Valkey, conclua as seguintes ações:

  • Em vez do objeto de cliente RedisCluster ou ValkeyCluster fornecido pela biblioteca, use o objeto de cliente do Redis ou do Valkey.
  • Crie um cliente gravador usando o endereço IP do endpoint principal.
  • Crie um cliente leitor usando o endereço IP do endpoint do leitor.

redis-py

Recomendamos o uso do redis-py, versões 5.1 e mais recentes.

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 o uso do go-redis, versões 9.11.0 e mais recentes.

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 o uso do Jedis, versões 4.4.0 e mais recentes.


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 o uso do Node.js, versões 24.4.1 e mais recentes.

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 do IAM e criptografia em trânsito

Esta seção mostra um exemplo de como autenticar e se conectar a uma instância do Memorystore para Valkey usando a autenticação do IAM e a criptografia em trânsito com várias bibliotecas de cliente.

redis-py

Recomendamos o uso do redis-py, versões 5.1 e mais recentes.

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

Recomendamos o uso do Go, versões 1.24.5 e mais recentes.

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