Caching in Rust: Redis and Other Tools for Application Acceleration
Caching is one of the key mechanisms for performance optimization. In Rust, with its emphasis on speed and safety, choosing the right caching tool can provide significant gains. This article covers popular libraries: redis-rs (with connection pooling), moka (in-memory cache), and cached (function decorators).
1. Redis: External Cache via redis-rs and deadpool
Redis is the most common external cache. The redis-rs crate is used to work with it in Rust. For production workloads, it is recommended to use a connection pool via deadpool-redis.
Installation
[dependencies]redis = { version = "0.25", features = ["tokio-comp"] }deadpool-redis = "0.14"tokio = { version = "1", features = ["full"] }serde = { version = "1", features = ["derive"] }serde_json = "1"Example: Basic Redis Operations
use redis::AsyncCommands;use deadpool_redis::{Config, Runtime};
#[tokio::main]async fn main() -> Result<(), Box<dyn std::error::Error>> { // Create a connection pool let cfg = Config::from_url("redis://127.0.0.1:6379"); let pool = cfg.create_pool(Some(Runtime::Tokio1))?;
// Get a connection from the pool let mut conn = pool.get().await?;
// Set a value with TTL of 60 seconds conn.set_ex("user:42", "{\\"name\\":\\"Alice\\",\\"role\\":\\"admin\\"}", 60).await?;
// Read let value: String = conn.get("user:42").await?; println!("Retrieved: {}", value);
// Delete conn.del("user:42").await?;
Ok(())}Struct Serialization
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize, Debug)]struct User { id: u64, name: String, email: String,}
async fn cache_user(conn: &mut redis::aio::Connection, user: &User) -> redis::RedisResult<()> { let key = format!("user:{}", user.id); let json = serde_json::to_string(user).unwrap(); conn.set_ex(key, json, 300).await}
async fn get_cached_user(conn: &mut redis::aio::Connection, id: u64) -> Option<User> { let key = format!("user:{}", id); let result: Option<String> = conn.get(key).await.ok()?; result.and_then(|json| serde_json::from_str(&json).ok())}2. Moka: Fast In-Memory Cache
Moka is a high-performance in-memory cache inspired by Caffeine (Java). It supports TTL, size limits, and asynchronous updates.
Installation
[dependencies]moka = { version = "0.12", features = ["future"] }tokio = { version = "1", features = ["full"] }Example: Cache with 1000 Element Limit and 10-Minute TTL
use moka::future::Cache;use std::time::Duration;
#[tokio::main]async fn main() { let cache: Cache<String, String> = Cache::builder() .max_capacity(1000) .time_to_live(Duration::from_secs(600)) .build();
// Insert cache.insert("key1".to_string(), "value1".to_string()).await;
// Read if let Some(v) = cache.get(&"key1".to_string()).await { println!("Found: {}", v); }
// Delete cache.invalidate(&"key1".to_string()).await;}Auto-Refresh on TTL Expiry
let cache: Cache<String, String> = Cache::builder() .time_to_live(Duration::from_secs(60)) .time_to_idle(Duration::from_secs(30)) // reset TTL on read .build();3. Cached: Function Decorators
The cached crate allows caching function results using attributes. It supports various backends, including Redis and in-memory.
Installation
[dependencies]cach Also in library
Task Scheduler in TypeScript: A Detailed Guide to the node-schedule Library
Working with Excel in PHP: PhpSpreadsheet and OpenSpout Libraries
Internationalization (i18n) in C# (.NET): A Complete Guide
Working with ZIP Archives in C# (.NET): A Complete Guide
Data Validation in C# (.NET): Libraries and Approaches