Prácticas recomendadas para utilizar réplicas de lectura
Muchas aplicaciones, como los almacenes de sesiones, las tablas de clasificación y los motores de recomendaciones, requieren una alta disponibilidad y gestionan muchas más operaciones de lectura que de escritura. A menudo, estas aplicaciones toleran datos ligeramente obsoletos (coherencia final), lo que significa que no ocurre nada si distintos usuarios ven momentáneamente versiones ligeramente diferentes de los mismos datos. Por ejemplo:
Los resultados de las consultas en caché suelen tolerar datos ligeramente obsoletos, especialmente en el caso de los patrones de reserva de caché, en los que el origen de la verdad es externo.
En una tabla de clasificación de videojuegos, un retraso de unos segundos en la actualización de las puntuaciones no suele afectar de forma significativa a la experiencia del usuario.
En el caso de los almacenes de sesiones, algunos retrasos leves en la propagación de los datos de sesión entre las réplicas rara vez afectan a la funcionalidad de la aplicación.
Los motores de recomendaciones suelen utilizar el análisis de datos históricos, por lo que la coherencia en tiempo real es menos importante.
Coherencia final significa que todos los nodos de réplica devolverán los mismos datos una vez que se complete el proceso de replicación, normalmente en cuestión de milisegundos. En estos casos de uso, la implementación de réplicas de lectura es una estrategia eficaz para reducir la latencia al leer desde la instancia de ElastiCache.
El uso de réplicas de lectura en Amazon ElastiCache puede proporcionar importantes mejoras del rendimiento gracias a:
Mejora de la escalabilidad de lectura
Distribuye las operaciones de lectura entre varios nodos de réplica.
Las descargas leen el tráfico de lectura del nodo principal.
Se reduce la latencia de lectura al atender las solicitudes de réplicas más cercanas desde el punto de vista geográfico.
Rendimiento optimizado del nodo principal
Asigna los recursos del nodo principal a las operaciones de escritura.
Reduce la sobrecarga de la conexión en el nodo principal.
Mejora el rendimiento de escritura y mantiene mejores tiempos de respuesta durante los períodos de más tráfico.
Uso de la lectura desde la réplica en ElastiCache sin servidor
ElastiCache sin servidor proporciona dos puntos de conexión diferentes para distintos requisitos de coherencia. Los dos puntos de conexión utilizan el mismo nombre de DNS pero puertos diferentes. Para utilizar el puerto de lectura desde la réplica, debe autorizar el acceso a ambos puertos desde la aplicación cliente mediante la configuración de los grupos de seguridad y las listas de control de acceso a la red de su VPC.
Punto de conexión principal (puerto 6379)
Se utiliza para operaciones que requieren coherencia inmediata.
Garantiza que se lean los datos más actualizados.
Es ideal para transacciones y operaciones de escritura críticas.
Es necesario para las operaciones de escritura.
Ejemplo:
test-12345.serverless.use1.cache.amazonaws.com:6379
Punto de conexión con latencia optimizada (puerto 6380)
Optimizado para operaciones de lectura que pueden tolerar una coherencia final.
Si se puede, ElastiCache sin servidor enruta automáticamente las solicitudes de lectura al nodo de réplica en la zona de disponibilidad local del cliente. Esta optimización proporciona una latencia más baja al evitar la latencia de red adicional que se produce al recuperar datos de un nodo en una zona de disponibilidad diferente.
ElastiCache sin servidor selecciona automáticamente los nodos disponibles en otras zonas si un nodo local no está disponible.
Ejemplo:
test-12345.serverless.use1.cache.amazonaws.com:6380Los clientes como Glide y Lettuce detectarán automáticamente las lecturas y las enrutarán hacia el punto de conexión con latencia optimizada si proporciona la configuración de lectura desde la réplica. Si su cliente no admite la configuración de enrutamiento (por ejemplo, valkey-java y versiones anteriores de jedis), debe definir la configuración de puerto y cliente correcta para leer las réplicas.
Conexión a réplicas de lectura en ElastiCache sin servidor: Valkey y Glide
El siguiente fragmento de código muestra cómo se puede configurar la lectura desde la réplica para ElastiCache sin servidor en la biblioteca Valkey Glide. No necesita especificar el puerto para la lectura de las réplicas, pero sí configurar el enrutamiento ReadFrom.PREFER_REPLICA.
package glide.examples; import glide.api.GlideClusterClient; import glide.api.logging.Logger; import glide.api.models.configuration.GlideClusterClientConfiguration; import glide.api.models.configuration.NodeAddress; import glide.api.models.exceptions.ClosingException; import glide.api.models.exceptions.ConnectionException; import glide.api.models.exceptions.TimeoutException; import glide.api.models.configuration.ReadFrom; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; public class ClusterExample { public static void main(String[] args) { // Set logger configuration Logger.setLoggerConfig(Logger.Level.INFO); GlideClusterClient client = null; try { System.out.println("Connecting to Valkey Glide..."); // Configure the Glide Client GlideClusterClientConfiguration config = GlideClusterClientConfiguration.builder() .address(NodeAddress.builder() .host("your-endpoint") .port(6379) .build()) .useTLS(true) .readFrom(ReadFrom.PREFER_REPLICA) .build(); // Create the GlideClusterClient client = GlideClusterClient.createClient(config).get(); System.out.println("Connected successfully."); // Perform SET operation CompletableFuture<String> setResponse = client.set("key", "value"); System.out.println("Set key 'key' to 'value': " + setResponse.get()); // Perform GET operation CompletableFuture<String> getResponse = client.get("key"); System.out.println("Get response for 'key': " + getResponse.get()); // Perform PING operation CompletableFuture<String> pingResponse = client.ping(); System.out.println("PING response: " + pingResponse.get()); } catch (ClosingException | ConnectionException | TimeoutException | ExecutionException e) { System.err.println("An exception occurred: "); e.printStackTrace(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { // Close the client connection if (client != null) { try { client.close(); System.out.println("Client connection closed."); } catch (ClosingException | ExecutionException e) { System.err.println("Error closing client: " + e.getMessage()); } } } } }