Cache em Rust: Redis, Memcached e soluções embutidas
Cache é um dos mecanismos-chave para otimizar o desempenho de aplicações web e sistemas de alta carga. No ecossistema Rust, existem várias bibliotecas poderosas para organizar cache: desde soluções distribuídas (Redis, Memcached) até caches leves in-memory (moka, cached). Neste artigo, analisaremos detalhadamente cada uma delas, forneceremos exemplos de código e compararemos seu desempenho.
1. Redis através do crate redis-rs
redis-rs é o cliente principal e mais maduro para Redis em Rust. Ele suporta todos os recursos principais: strings, listas, hashes, pub/sub, transações e clusterização.
Instalação
[dependencies]redis = { version = "0.25", features = ["tokio-comp"] }tokio = { version = "1", features = ["full"] }Exemplo: cache básico com Redis
use redis::{AsyncCommands, Client};use std::time::Duration;
#[tokio::main]async fn main() -> redis::RedisResult<()> { let client = Client::open("redis://127.0.0.1:6379/")?; let mut con = client.get_multiplexed_async_connection().await?;
// Define uma chave com TTL de 60 segundos con.set_ex("user:1:profile", "{\\"name\\":\\"Alice\\"}", 60).await?;
// Lê o valor let data: Option<String> = con.get("user:1:profile").await?; println!("Obtido: {:?}", data);
// Incrementa contador let count: i64 = con.incr("page_views", 1).await?; println!("Visualizações da página: {}", count);
Ok(())}Características importantes:
- Assincronicidade: redis-rs suporta modos síncrono e assíncrono (tokio/async-std).
- Pipeline: agrupamento de comandos para reduzir latência.
- Clusterização: suporte a Redis Cluster via
redis::cluster.
2. Memcached através do crate memcached-rs
Memcached é um armazenamento distribuído leve do tipo chave-valor. Para Rust, existe o crate memcached-rs (ou memcache).
Exemplo de uso
use memcache::Client;
fn main() -> memcache::MemcacheResult<()> { let client = Client::connect("memcache://127.0.0.1:11211")?;
// Escrita com TTL client.set("session:token_abc", "user_data", 30)?;
// Leitura let value: Option<String> = client.get("session:token_abc")?; println!("Do Memcached: {:?}", value);
// Remoção client.delete("session:token_abc")?;
Ok(())}Quando escolher Memcached em vez de Redis:
- Se precisar apenas de cache simples (chave-valor).
- Se a latência mínima for importante (Memcached é mais rápido que Redis para operações simples).
- Se não precisar das estruturas de dados do Redis (listas, hashes, sets).
3. Caches in-memory embutidos: moka e cached
Para cache dentro de um único processo (sem servidor externo), os crates moka e cached são excelentes opções.
3.1 Moka — cache de alto desempenho
moka é um cache assíncrono, thread-safe, com suporte a TTL, tamanho máximo e política de despejo (LRU, LFU).
use moka::future::Cache;use std::time::Duration;
#[tokio::main]async fn main() { let cache: Cache<String, String> = Cache::builder() .max_capacity(10_000) // máximo de 10.000 entradas .time_to_live(Duration::from_secs(300)) // TTL de 5 minutos .build();
// Inserção cache.insert("key1".to_string(), "value1".to_string()).await;
// Obtenção if let Some(value) = cache.get(&"key1".to_string()).await { p