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

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, Memcached e soluções embutidas



Cache é um dos mecanismos-chave para otimizar o desempenho de aplicações modernas. No ecossistema Rust, conhecido por sua velocidade e segurança de memória, escolher a ferramenta certa para cache pode impactar significativamente a eficiência do programa. Neste artigo, exploraremos três abordagens principais: sistemas externos Redis e Memcached, além de soluções embutidas disponíveis na biblioteca padrão e em crates populares.



Por que usar cache em Rust?

Rust já é muito rápido por si só, mas ao trabalhar com bancos de dados, APIs externas ou cálculos complexos, o cache permite:

  • Reduzir a latência (latency) em requisições repetidas
  • Diminuir a carga em bancos de dados e serviços externos
  • Economizar recursos computacionais e tempo de CPU


1. Soluções embutidas: HashMap e cache LRU

A maneira mais simples de fazer cache em Rust é usar HashMap da biblioteca padrão. Para aplicações multithread, é necessário um wrapper Mutex<HashMap> ou RwLock<HashMap>. No entanto, essa abordagem não possui política de despejo (eviction policy), o que pode levar ao crescimento infinito da memória.



Exemplo de cache simples com 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); }}


Cache LRU com o crate lru

Para limitar o tamanho do cache e despejar automaticamente entradas antigas, use o crate lru. Ele implementa o algoritmo Least Recently Used — remove os elementos menos usados recentemente.



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á despejado

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


Prós: latência de rede zero, simplicidade, controle total. Contras: o cache vive apenas dentro de um único processo, sem persistência.



2. Cache com Redis usando redis-rs

Redis é um armazenamento in-memory do tipo chave-valor, frequentemente usado como cache distribuído. Em Rust, o crate redis (ou redis-rs) é usado para trabalhar com Redis.



Conexão e operações básicas

use redis::Commands;

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

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

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

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

Ok(())}


Funcionalidades avançadas do Redis

  • TTL (Time To Live): remoção automática de entradas expiradas
  • Estruturas de dados: listas, conjuntos, hashes — para cenários complexos
  • Pub/Sub: notificações sobre mudanças no cache
  • Clusterização: escalabilidade horizontal


Prós: dis

Blogs

Book Recommendations