Cliente Redis para Rust: biblioteca redis-rs
A biblioteca redis-rs é o principal e mais popular cliente para trabalhar com Redis no ecossistema Rust. Ela fornece um conjunto completo de funções para interagir com Redis: desde comandos simples GET/SET até transações complexas, pipelines e Pub/Sub. Graças ao suporte tanto para modos síncrono quanto assíncrono (async/await), o redis-rs é adequado para qualquer projeto — desde scripts até servidores web de alta carga.
A biblioteca é escrita em Rust puro, utiliza gerenciamento seguro de memória e segurança de tipos, o que minimiza erros em tempo de execução. Todos os tipos de dados populares do Redis são suportados: strings, listas, conjuntos, hashes, conjuntos ordenados, mapas de bits, HyperLogLog e streams.
Instalação e configuração
Adicione a dependência no arquivo Cargo.toml:
[dependencies]redis = { version = "0.27", features = ["tokio-comp"] }Para uso síncrono, basta redis = "0.27". Para uso assíncrono, escolha um dos executores: tokio-comp (padrão) ou async-std-comp.
Uso básico (modo síncrono)
Exemplo de conexão a um Redis local e execução de comandos simples:
use redis::Commands;
fn main() -> redis::RedisResult<()> { let client = redis::Client::open("redis://127.0.0.1:6379/")?; let mut con = client.get_connection()?;
con.set("my_key", "hello world")?; let value: String = con.get("my_key")?; println!("Valor obtido: {}", value);
// Trabalhando com hashes con.hset("user:1", "name", "Alice")?; con.hset("user:1", "age", "30")?; let name: String = con.hget("user:1", "name")?; println!("Nome do usuário: {}", name);
Ok(())}Observe a desserialização automática: você especifica o tipo no qual deseja converter o resultado (String, i32, Vec<String>, etc.), e a biblioteca faz tudo sozinha.
Modo assíncrono com Tokio
Para aplicações de alto desempenho, use a API assíncrona:
use redis::AsyncCommands;use tokio;
#[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?;
// Definir com TTL (tempo de vida da chave) con.set_ex("temp_key", "valor temporário", 60).await?; let val: Option<String> = con.get("temp_key").await?; println!("Valor: {:?}", val);
// Trabalhando com listas con.lpush("queue", "task1").await?; con.lpush("queue", "task2").await?; let tasks: Vec<String> = con.lrange("queue", 0, -1).await?; println!("Tarefas na fila: {:?}", tasks);
Ok(())}O cliente assíncrono usa conexões multiplexadas (um único socket TCP para múltiplas requisições), o que aumenta significativamente o desempenho.
Recursos avançados
Pipelines (processamento em pipeline)
Permite enviar vários comandos em uma única chamada de rede, acelerando operações em lote:
use redis::pipe;
fn main() -> redis::RedisResult<()> { let client = redis::Client::open("redis://127.0.0.1:6379/")?; let mut con = client.get_connection()?;
let (val1, val2): (i32, i32) = redis::pipe() .cmd("INCR").arg("counter_a").ignore() .cmd("INCR").arg("counter_b").ignore() .cmd("GET").arg("counter_a").query(&mut con)? .cmd("GET").arg("counter_b").query(&mut con)?;
println!("Contadores: {}, {}", val1, val2); Ok(())}Pub/Sub (publicador-assinante)
Exemplo de inscrição em canais:
use redis::pubsub::PubSubCommands;
fn main() -> redis::RedisResult<()> {