Memorizzazione nella cache dei dati con Memorystore

Le applicazioni web scalabili ad alte prestazioni utilizzano spesso una cache di dati in memoria distribuita davanti o al posto di un'archiviazione persistente solida per alcune attività. Ti consigliamo di utilizzare Memorystore for Redis come servizio di memorizzazione nella cache. Tieni presente che Memorystore for Redis non offre un livello gratuito. Per maggiori dettagli, vedi Prezzi di Memorystore.

Prima di iniziare, assicurati che l'app rimanga all'interno Quote di Memorystore for Redis

Quando utilizzare una cache in memoria

Dati di sessione, preferenze utente e altri dati restituiti dalle query per le pagine web sono buoni candidati per la memorizzazione nella cache. In generale, se una query eseguita di frequente restituisce un insieme di risultati che non devono necessariamente essere visualizzati nell'app, puoi memorizzare nella cache i risultati. Le richieste successive possono controllare la cache ed eseguire query sul database solo se i risultati non sono presenti o sono scaduti.

Se archivi un valore solo in Memorystore senza eseguirne il backup in di archiviazione permanente, assicurati che l'applicazione si comporti in modo accettabile se scade e viene rimosso dalla cache. Ad esempio, se l'assenza improvvisa degli dati di sessione di un utente causa il malfunzionamento della sessione, questi dati dovrebbero probabilmente essere archiviati nel database oltre che in Memorystore.

Informazioni sulle autorizzazioni di Memorystore

Ogni interazione con un servizio Google Cloud deve essere autorizzata. Per Ad esempio, per interagire con un database Redis ospitato da Memorystore, la tua app deve fornire le credenziali di un account autorizzato ad accedere Memorystore.

Per impostazione predefinita, l'app fornisce le credenziali dell'account di servizio predefinito di App Engine, che è autorizzato ad accedere ai database nello stesso progetto dell'app.

Se una delle seguenti condizioni è vera, devi utilizzare una tecnica di autenticazione alternativa che fornisca esplicitamente le credenziali:

  • La tua app e il database Memorystore si trovano in diversi progetti Google Cloud.

  • Hai modificato i ruoli assegnati all'account di servizio App Engine predefinito.

Per informazioni sulle tecniche di autenticazione alternative, vedi Impostazione dell'autenticazione per la produzione da server a server Applicazioni.

Panoramica dell'utilizzo di Memorystore

Per utilizzare Memorystore nella tua app:

  1. Configurare Memorystore for Redis per creare un'istanza Redis su Memorystore Accesso VPC serverless utilizzato dalla tua app per comunicare con Redis. L'ordine di creazione di queste due entità indipendenti non è e possono essere configurate in qualsiasi ordine. Le istruzioni di questa guida mostrano per prima cosa devi configurare l'accesso VPC serverless.

  2. Installa una libreria client per Redis e utilizza i comandi Redis per memorizzare nella cache i dati.

    Memorystore for Redis è compatibile con qualsiasi libreria client per Redis. Questa guida descrive l'utilizzo dei Giorgia libreria client per inviare comandi Redis dalla tua app. Per maggiori dettagli su gli Jedi, vedi Wiki Jedi.

  3. Testa gli aggiornamenti.

  4. Esegui il deployment dell'app in App Engine.

Configurazione di Memorystore for Redis

Per configurare Memorystore for Redis:

  1. Connetti App Engine a un VPC Google Cloud. L'app può comunicare con Memorystore solo tramite un connettore VPC.

    Assicurati di aggiungere le informazioni di connessione VPC al file app.yaml come descritto in Configurare l'utilizzo del connettore da parte dell'app.

  2. Prendi nota dell'indirizzo IP e del numero di porta dell'istanza Redis creata. Userai queste informazioni quando crei un client Redis nel codice.

  3. Crea un'istanza Redis in Memorystore.

    Quando ti viene richiesto di selezionare una regione per l'istanza Redis, seleziona stessa regione in cui si trova l'app di App Engine.

Installazione delle dipendenze

Per rendere disponibile la libreria client Jedis alla tua app quando viene eseguita in App Engine, aggiungila alle dipendenze dell'app. Ad esempio, se utilizzi Maven, aggiungi la seguente dipendenza al file pom.xml:
<dependency>
  <groupId>redis.clients</groupId>
  <artifactId>jedis</artifactId>
  <version>5.1.0</version>
</dependency>

Creazione di un client Redis

Per interagire con un database Redis, il codice deve creare un client Redis per gestire la connessione al database Redis. Le seguenti sezioni descrivono creando un client Redis utilizzando Jedi libreria client.

Specifica delle variabili di ambiente

La Jedi la libreria client utilizza due variabili di ambiente per assemblare l'URL per il tuo database Redis:

  • Una variabile per identificare l'indirizzo IP del database Redis creato in Memorystore.
  • Una variabile per identificare il numero di porta del database Redis che hai creato in Memorystore.

Ti consigliamo di definire queste variabili nel file app.yaml dell'app anziché nel file definendole direttamente nel tuo codice. In questo modo è più facile eseguire l'app in diversi ambienti, ad esempio in un ambiente locale e in App Engine.

Ad esempio, aggiungi le seguenti righe al file app.yaml:

 env_variables:
      redis.host: '10.112.12.112'
      redis.port: '6379'

In fase di importazione Jedi e la creazione del client

Quando utilizzi la libreria Jedis, ti consigliamo di creare un JedisPool e di utilizzare il pool per creare un client. Le seguenti righe di codice utilizzano le variabili di ambiente redis.host e redis.port che hai definito in precedenza per creare un pool:


package com.example.redis;

import java.io.IOException;
import java.util.Properties;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

@WebListener
public class AppServletContextListener implements ServletContextListener {

  private Properties config = new Properties();

  private JedisPool createJedisPool() throws IOException {
    String host;
    Integer port;
    config.load(
        Thread.currentThread()
            .getContextClassLoader()
            .getResourceAsStream("application.properties"));
    host = config.getProperty("redis.host");
    port = Integer.valueOf(config.getProperty("redis.port", "6379"));

    JedisPoolConfig poolConfig = new JedisPoolConfig();
    // Default : 8, consider how many concurrent connections into Redis you will need under load
    poolConfig.setMaxTotal(128);

    return new JedisPool(poolConfig, host, port);
  }

  @Override
  public void contextDestroyed(ServletContextEvent event) {
    JedisPool jedisPool = (JedisPool) event.getServletContext().getAttribute("jedisPool");
    if (jedisPool != null) {
      jedisPool.destroy();
      event.getServletContext().setAttribute("jedisPool", null);
    }
  }

  // Run this before web application is started
  @Override
  public void contextInitialized(ServletContextEvent event) {
    JedisPool jedisPool = (JedisPool) event.getServletContext().getAttribute("jedisPool");
    if (jedisPool == null) {
      try {
        jedisPool = createJedisPool();
        event.getServletContext().setAttribute("jedisPool", jedisPool);
      } catch (IOException e) {
        // handle exception
      }
    }
  }
}

Per creare un client dal pool, utilizza il metodo JedisPool.getResource(). Ad esempio:


package com.example.redis;

import java.io.IOException;
import java.net.SocketException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

@WebServlet(name = "Track visits", value = "")
public class VisitCounterServlet extends HttpServlet {

  @Override
  public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    try {
      JedisPool jedisPool = (JedisPool) req.getServletContext().getAttribute("jedisPool");

      if (jedisPool == null) {
        throw new SocketException("Error connecting to Jedis pool");
      }
      Long visits;

      try (Jedis jedis = jedisPool.getResource()) {
        visits = jedis.incr("visits");
      }

      resp.setStatus(HttpServletResponse.SC_OK);
      resp.getWriter().println("Visitor counter: " + String.valueOf(visits));
    } catch (Exception e) {
      resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
    }
  }
}

Utilizzo dei comandi Redis per archiviare e recuperare i dati nella cache

Sebbene il database Memorystore Redis supporti la maggior parte i comandi Redis, ti basta usare pochi comandi archiviare e recuperare i dati dalla cache. La tabella seguente suggerisce i comandi Redis che puoi utilizzare per memorizzare nella cache i dati. Per scoprire come chiamare questi comandi dal tuo visualizza la documentazione della libreria client.

Attività Comando Redis
Crea una voce nella cache dei dati e
imposta una scadenza per la voce
SETNX
MSETNX
Recuperare i dati dalla cache GET
MGET
Sostituire i valori della cache esistenti SET
MSET
Aumentare o diminuire i valori numerici della cache INCR
INCRBY
DECR
DECRBY
Eliminare le voci dalla cache DEL
SCOLLEGA
Supportare le interazioni simultanee con la cache Consulta i dettagli sulle transazioni Redis.

Test degli aggiornamenti in corso...

Quando testi la tua app in locale, valuta la possibilità di eseguire un'istanza locale di Redis per evitare di interagire con i dati di produzione (Memorystore non fornire un emulatore). Per installare ed eseguire Redis localmente, segui le istruzioni riportate nella documentazione di Redis. Tieni presente che al momento non è possibile eseguire Redis localmente su Windows.

Deployment dell'app

Una volta che l'app è in esecuzione nel server di sviluppo locale senza errori:

  1. Testa l'app su in App Engine.

  2. Se l'app viene eseguita senza errori, utilizza il traffico da dividere in lentamente aumentare il traffico per la tua app aggiornata. Monitora attentamente l'app per individuare prima di indirizzare una quantità maggiore di traffico all'app aggiornata.