Caching en Rust: Redis, Memcached y soluciones integradas

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Almacenamiento en caché en Rust: Redis, Memcached y soluciones integradas



El almacenamiento en caché es uno de los mecanismos clave para optimizar el rendimiento de las aplicaciones modernas. En el ecosistema de Rust, conocido por su velocidad y seguridad de memoria, elegir la herramienta adecuada para el almacenamiento en caché puede afectar significativamente la eficiencia del programa. En este artículo, exploraremos tres enfoques principales: los sistemas externos Redis y Memcached, así como las soluciones integradas disponibles en la biblioteca estándar y crates populares.



¿Por qué almacenar en caché en Rust?

Rust ya es muy rápido por sí mismo, pero al trabajar con bases de datos, API externas o cálculos complejos, el almacenamiento en caché permite:

  • Reducir la latencia (latency) en solicitudes repetidas
  • Disminuir la carga en bases de datos y servicios externos
  • Ahorrar recursos computacionales y tiempo de CPU


1. Soluciones integradas: HashMap y caché LRU

La forma más simple de almacenamiento en caché en Rust es usar HashMap de la biblioteca estándar. Para aplicaciones multihilo, se necesita un envoltorio Mutex<HashMap> o RwLock<HashMap>. Sin embargo, este enfoque no tiene una política de desalojo (eviction policy), lo que puede provocar un crecimiento infinito de la memoria.



Ejemplo de un caché simple con HashMap

use std::collections::HashMap;use std::sync::Mutex;

struct SimpleCache { store: Mutex<HashMap<String, String>>,}

impl SimpleCache { fn new() -> Self { SimpleCache { store: Mutex::new(HashMap::new()), } }

fn get(&self, key: &str) -> Option<String> { self.store.lock().unwrap().get(key).cloned() }

fn set(&self, key: String, value: String) { self.store.lock().unwrap().insert(key, value); }}


Caché LRU mediante el crate lru

Para limitar el tamaño del caché y desalojar automáticamente las entradas antiguas, use el crate lru. Implementa el algoritmo Least Recently Used: elimina los elementos usados con menos frecuencia.



use lru::LruCache;use std::num::NonZeroUsize;

fn main() { let mut cache = LruCache::new(NonZeroUsize::new(3).unwrap()); cache.put("apple", 10); cache.put("banana", 20); cache.put("cherry", 30); cache.put("date", 40); // "apple" será desalojado

println!("{:?}", cache.get(&"apple")); // None println!("{:?}", cache.get(&"date")); // Some(40)}


Ventajas: latencia de red cero, simplicidad, control total. Desventajas: el caché solo vive dentro de un solo proceso, no hay persistencia.



2. Almacenamiento en caché con Redis mediante redis-rs

Redis es un almacén de tipo clave-valor en memoria que se utiliza a menudo como caché distribuido. En Rust, para trabajar con Redis se usa el crate redis (o redis-rs).



Conexión y operación básica

use redis::Commands;

fn main() -> redis::RedisResult<()> { let client = redis::Client::open("redis://127.0.0.1:6379/")?; let mut con = client.get_connection()?;

// Establecer valor con TTL (tiempo de vida) con.set_ex("user:42", "{\\"name\\": \\"Alice\\"}", 60)?;

// Lectura let value: String = con.get("user:42")?; println!("{}", value);

// Verificar existencia let exists: bool = con.exists("user:42")?; println!("Exists: {}", exists);

Ok(())}


Funcionalidades avanzadas de Redis

  • TTL (Time To Live): eliminación automática de entradas obsoletas
  • Estructuras de datos: listas, conjuntos, hashes — para escenarios complejos
  • Pub/Sub: notificaciones sobre cambios en el caché
  • Clustering: escalado horizontal


Ventajas: dis

Blogs

Book Recommendations