Cache em Rust: Redis, Memcached e soluções embutidas

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Cache em Rust: Redis e outras soluções eficientes



No desenvolvimento moderno de alta carga em Rust, o cache desempenha um papel fundamental. Ele permite reduzir a carga em bancos de dados, acelerar respostas de API e otimizar o trabalho com cálculos custosos. Neste artigo, abordaremos as principais bibliotecas para cache no ecossistema Rust: desde o poderoso Redis até soluções leves in-memory.



1. Redis através do crate redis-rs



redis-rs é a biblioteca principal e mais madura para trabalhar com Redis em Rust. Ela suporta operações assíncronas (via tokio ou async-std), clusterização, pub/sub e todos os tipos populares de dados do Redis.



Instalação

[dependencies]redis = { version = "0.25", features = ["tokio-comp"] }tokio = { version = "1", features = ["full"] }


Exemplo básico: cache de strings

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?;

// Define o cache com TTL de 60 segundos let _: () = con.set_ex("user:123", "{\\"name\\":\\"Alice\\"}", 60).await?;

// Obtém o valor let cached: String = con.get("user:123").await?; println!("Dados em cache: {}", cached);

// Verifica a existência da chave let exists: bool = con.exists("user:123").await?; println!("Chave existe: {}", exists);

Ok(())}


Serialização de estruturas complexas

Para armazenar estruturas de dados em cache, use serde em conjunto com 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. Cache in-memory: o crate moka



Moka é uma biblioteca de alto desempenho para cache em memória, inspirada no Caffeine (Java). Ela é ideal para cenários onde não é necessário um servidor externo, mas sim máxima velocidade.



Características do moka:

  • Evicção automática por tempo (TTL, TTI) e por tamanho
  • Sincronização assíncrona (background refresh)
  • Segurança para uso multi-thread (Arc + RwLock)
  • Suporte a políticas de peso (weighted cache)


Exemplo: cache com TTL e limite de tamanho

use moka::sync::Cache;use std::time::Duration;

fn main() { // Cria um cache de 1000 elementos com TTL de 10 minutos let cache: Cache<String, String> = Cache::builder() .max_capacity(1000) .time_to_live(Duration::from_secs(600)) .build();

// Inserção e obtenção cache.insert("key1".to_string(), "value1".to_string()); if let Some(v) = cache.get("key1") { println!("Valor: {}", v); }}


Variante assíncrona (moka::future::Cache)

use moka::future::Cache;

#[tokio::main]async fn main() { let cache: Cache<u64, String> = Cache::new(10_000);

// Inserção assíncrona cache.insert(42, "Hello async".to_string()).await;

// Obtenção assíncrona if let Some(val) = cache.get(&42).await { println!("{}", val); }}


3. Cache declarativo: o crate <

Recommendations