Redis client for Rust: redis-rs library
The redis-rs library is the primary and most popular client for working with Redis in the Rust ecosystem. It provides a full set of functions for interacting with Redis: from simple GET/SET commands to complex transactions, pipelines, and Pub/Sub. With support for both synchronous and asynchronous (async/await) modes, redis-rs is suitable for any project — from scripts to high-load web servers.
The library is written in pure Rust, uses safe memory management and type safety, which minimizes runtime errors. All popular Redis data types are supported: strings, lists, sets, hashes, sorted sets, bitmaps, HyperLogLog, and streams.
Installation and setup
Add the dependency to your Cargo.toml file:
[dependencies]redis = { version = "0.27", features = ["tokio-comp"] }For synchronous use, simply redis = "0.27" is enough. For asynchronous use, choose one of the executors: tokio-comp (default) or async-std-comp.
Basic usage (synchronous mode)
Example of connecting to a local Redis instance and executing simple commands:
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!("Retrieved value: {}", value);
// Working with hashes con.hset("user:1", "name", "Alice")?; con.hset("user:1", "age", "30")?; let name: String = con.hget("user:1", "name")?; println!("User name: {}", name);
Ok(())}Note the automatic deserialization: you specify the type you want the result to be converted to (String, i32, Vec<String>, etc.), and the library handles everything.
Asynchronous mode with Tokio
For high-performance applications, use the asynchronous API:
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?;
// Setting with TTL (key time-to-live) con.set_ex("temp_key", "temporary value", 60).await?; let val: Option<String> = con.get("temp_key").await?; println!("Value: {:?}", val);
// Working with lists con.lpush("queue", "task1").await?; con.lpush("queue", "task2").await?; let tasks: Vec<String> = con.lrange("queue", 0, -1).await?; println!("Tasks in queue: {:?}", tasks);
Ok(())}The asynchronous client uses multiplexed connections (one TCP socket for multiple requests), which significantly improves performance.
Advanced features
Pipelines
Allow sending multiple commands in a single network call, speeding up batch operations:
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!("Counters: {}, {}", val1, val2); Ok(())}Pub/Sub
Example of subscribing to channels:
use redis::pubsub::PubSubCommands;
fn main() -> redis::RedisResult<()> {