Rust 用 moka 构建内存缓存,TTL 与 LRU 回收并发安全

test12026-10-092 次阅读

为什么选 moka

Rust 里自己用 HashMap 加锁做缓存既慢又容易出并发 bug。moka 是一个高性能、线程安全的异步/同步缓存库,内置 TTL(存活时间)、TTI(空闲时间)和基于容量的 LRU 回收,读写几乎无锁,适合在高并发服务里当本地缓存层。

同步缓存基础

sync::Cache 用在非 async 上下文,设置 max_capacity 与 TTL 后,写入和读取都是原子的,多个线程可安全共享。

use moka::sync::Cache;
use std::time::Duration;

fn main() {
    let cache: Cache<String, String> = Cache::builder()
        .max_capacity(10_000)
        .time_to_live(Duration::from_secs(300))
        .time_to_idle(Duration::from_secs(60))
        .build();

    cache.insert("user:1".to_string(), "alice".to_string());

    if let Some(name) = cache.get(&"user:1".to_string()) {
        println!("hit: {}", name);
    }

    println!("size = {}", cache.run_pending_tasks());
}

异步缓存与"取数回填"

future::Cache 用在 async 运行时里,配合 try_get_with 可以在未命中时异步计算并自动回填,且并发请求只会触发一次计算。

use moka::future::Cache;
use std::time::Duration;

async fn get_user(cache: &Cache<u64, String>, id: u64) -> String {
    cache
        .try_get_with(id, async {
            // 这里查数据库,并发未命中只执行一次
            Ok(fetch_from_db(id).await)
        })
        .await
        .unwrap_or_else(|e| e.to_string())
}

async fn fetch_from_db(id: u64) -> String {
    format!("user-{}", id)
}

工程要点

  • max_capacity 是软上限,超过后会按 LRU 异步回收,不会阻塞读写。
  • TTL 控制绝对存活,TTI 控制空闲回收,二者可单独或同时设置。
  • sync 版本适合简单场景且零 async 成本;需要 await 取数回填时选 future 版本。
  • 想拿到精确计数可调用 run_pending_tasks,否则回收在后台惰性发生。
T

test1

文章作者

为什么选 moka Rust 里自己用 HashMap 加锁做缓存既慢又容易出并发 bug。moka 是一个高性能、线...

分类
技术
发布时间
2026-10-09
字数
约 1351 字
阅读
2 次