Caché en Rust: Redis y otras soluciones eficientes
En el desarrollo moderno de alto rendimiento con Rust, el caché juega un papel clave. Permite reducir la carga en las bases de datos, acelerar las respuestas de API y optimizar el trabajo con cálculos costosos. En este artículo, revisaremos las principales bibliotecas para caché en el ecosistema de Rust: desde el potente Redis hasta soluciones ligeras en memoria.
1. Redis a través del crate redis-rs
redis-rs es la biblioteca principal y más madura para trabajar con Redis en Rust. Soporta operaciones asíncronas (a través de tokio o async-std), clustering, pub/sub y todos los tipos de datos populares de Redis.
Instalación
[dependencies]redis = { version = "0.25", features = ["tokio-comp"] }tokio = { version = "1", features = ["full"] }Ejemplo básico: caché de cadenas
use redis::AsyncCommands;
#[tokio::main]async fn main() -> redis::RedisResult<()> { let client = redis::Client::open("redis://127.0.0.1:6379/")?; let mut con = client.get_multiplexed_async_connection().await?;
// Establecemos caché con TTL de 60 segundos let _: () = con.set_ex("user:123", "{\\"name\\":\\"Alice\\"}", 60).await?;
// Obtenemos el valor let cached: String = con.get("user:123").await?; println!("Datos en caché: {}", cached);
// Verificamos la existencia de la clave let exists: bool = con.exists("user:123").await?; println!("Clave existe: {}", exists);
Ok(())}Serialización de estructuras complejas
Para almacenar en caché estructuras de datos, use serde junto con redis:
use serde::{Serialize, Deserialize};use redis::AsyncCommands;
#[derive(Debug, Serialize, Deserialize)]struct User { id: u32, name: String, email: String,}
async fn cache_user(con: &mut redis::aio::MultiplexedConnection, user: &User) { let json = serde_json::to_string(user).unwrap(); let _: () = con.set_ex(format!("user:{}", user.id), json, 300).await.unwrap();}
async fn get_cached_user(con: &mut redis::aio::MultiplexedConnection, id: u32) -> Option<User> { let json: Option<String> = con.get(format!("user:{}", id)).await.unwrap(); json.and_then(|data| serde_json::from_str(&data).ok())}2. Caché en memoria: crate moka
Moka es una biblioteca de alto rendimiento para caché en memoria, inspirada en Caffeine (Java). Es ideal para escenarios donde no se requiere un servidor externo y se necesita la máxima velocidad.
Características de moka:
- Evicción automática por tiempo (TTL, TTI) y por tamaño
- Sincronización asíncrona (background refresh)
- Seguridad para uso multihilo (Arc + RwLock)
- Soporte para políticas de peso (weighted cache)
Ejemplo: caché con TTL y límite de tamaño
use moka::sync::Cache;use std::time::Duration;
fn main() { // Creamos un caché de 1000 elementos con TTL de 10 minutos let cache: Cache<String, String> = Cache::builder() .max_capacity(1000) .time_to_live(Duration::from_secs(600)) .build();
// Inserción y obtención cache.insert("key1".to_string(), "value1".to_string()); if let Some(v) = cache.get("key1") { println!("Valor: {}", v); }}Variante asíncrona (moka::future::Cache)
use moka::future::Cache;
#[tokio::main]async fn main() { let cache: Cache<u64, String> = Cache::new(10_000);
// Inserción asíncrona cache.insert(42, "Hello async".to_string()).await;
// Obtención asíncrona if let Some(val) = cache.get(&42).await { println!("{}", val); }}3. Caché declarativo: crate <
También en la biblioteca
Análisis de HTML en C++: bibliotecas y ejemplos para trabajar con DOM y XPath
Envío de Email en C# (.NET): biblioteca System.Net.Mail
Biblioteca cpp-httplib: Cliente OAuth 2.0 en C++ para aplicaciones web