Mise en cache en Rust : Redis, Memcached et solutions intégrées

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Introduction : Pourquoi la mise en cache en Rust ?

\n

La vitesse est le principal avantage de Rust. Mais même le code le plus rapide peut se heurter à des entrées/sorties (E/S) lentes : requêtes vers une base de données, API externes ou calculs de données complexes. La mise en cache résout ce problème en stockant les résultats d'opérations coûteuses dans un stockage rapide. Rust propose des outils flexibles pour la mise en cache : des structures de données intégrées simples aux puissants systèmes distribués comme Redis et Memcached.

\n

Dans cet article, nous aborderons tous les niveaux de mise en cache en Rust : du simple HashMap aux solutions professionnelles avec TTL (durée de vie) et synchronisation. Vous apprendrez à choisir l'outil adapté à votre projet et à éviter les erreurs courantes.

\n\n

1. Mise en cache intégrée : HashMap et ses variantes

\n

La façon la plus simple de mettre en cache en Rust est d'utiliser HashMap de la bibliothèque standard. Cependant, dans un environnement multithread, des mécanismes de synchronisation supplémentaires sont nécessaires.

\n\n

1.1. HashMap simple (monothread)

\n

Pour les applications monothread, un HashMap standard convient. Exemple :

\n
use std::collections::HashMap;\n\nfn main() {\n    let mut cache: HashMap<String, String> = HashMap::new();\n    cache.insert("user:1".to_string(), "Alice".to_string());\n    \n    if let Some(name) = cache.get("user:1") {\n        println!("Valeur en cache : {}", name);\n    }\n}
\n

Avantages : code minimal, aucune dépendance.
\nInconvénients : pas de TTL, non thread-safe, mémoire non limitée.

\n\n

1.2. Cache thread-safe avec Mutex et Arc

\n

Pour les applications multithread, utilisez Arc<Mutex<HashMap>> :

\n
use std::collections::HashMap;\nuse std::sync::{Arc, Mutex};\nuse std::thread;\n\nstruct Cache {\n    store: Arc<Mutex<HashMap<String, String>>>,\n}\n\nimpl Cache {\n    fn new() -> Self {\n        Cache { store: Arc::new(Mutex::new(HashMap::new())) }\n    }\n    \n    fn get(&self, key: &str) -> Option<String> {\n        self.store.lock().ok()?.get(key).cloned()\n    }\n    \n    fn set(&self, key: String, value: String) {\n        self.store.lock().unwrap().insert(key, value);\n    }\n}\n\nfn main() {\n    let cache = Cache::new();\n    let c1 = cache.clone();\n    thread::spawn(move || {\n        c1.set("key".to_string(), "value".to_string());\n    });\n    println!("{:?}", cache.get("key"));\n}
\n

Inconvénient : le verrouillage Mutex peut réduire les performances en cas de forte concurrence.

\n\n

1.3. Bibliothèques avancées : lru et cached

\n

Pour le code de production, il est préférable d'utiliser des crates prêts à l'emploi :

\n
    \n
  • lru — implémente l'algorithme d'éviction LRU (Least Recently Used). Convient pour un cache limité.
  • \n
  • cached — fournit des macros pour la mise en cache automatique des fonctions avec prise en charge du TTL et du LRU.
  • \n
\n

Exemple avec cached :

\n
use cached::proc_macro::cached;\n\n#[cached(size = 100, time = 300)]\nfn expensive_computation(x: u32) -> u32 {\n    std::thread::sleep(std::time::Duration::from_secs(2));\n    x * x\n}\n\nfn main() {\n    let result = expensive_computation(5); // s'exécute en 2 sec\n    let cached_result = expensive_computation(5); // instantané\n    println!("{}", cached_result);\n}
\n\n

2. Redis : cache distribué pour les systèmes évolutifs

\n

Redis est un magasin de données en mémoire, idéal pour la mise en cache distribuée. En Rust, la crate redis est utilisée pour travailler avec Redis.

\n\n

2.1. Connexion et opérations de base

\n
use redis::Commands;\n\nfn main() -> redis::RedisResult<()> {\n    let client = redis::Client::open("redis://127.0.0.1:6379/")?;\n    let mut con = client.get_connection()?;\n    \n    // Définition d'une valeur avec TTL (durée de vie)\n    con.set_ex("user:1", "Alice", 3600)?; //                

Blogs

Book Recommendations