Rust语言

关注公众号 jb51net

关闭
首页 > 软件编程 > Rust语言 > Rust 内存缓存moka

Rust 高性能内存缓存 moka 完全指南

作者:Rust研习社

本文介绍了Rust高性能内存缓存库moka,涵盖其核心特性、基础环境搭建、同步/异步实战、高级配置及生产环境最佳实践等内容,感兴趣的可以了解一下

本文将带你全面掌握 moka,从核心特性、基础环境搭建,到同步/异步实战、高级配置,再到生产环境最佳实践与避坑指南,让你快速在项目中落地这款高性能缓存库。

moka 是什么?以及优势

moka 是一款纯 Rust 实现的并发安全、高性能内存缓存库,灵感源自 Java 生态的 Caffeine 缓存库,专为高并发服务端场景设计,专注于本地内存缓存。

环境搭建

moka 的使用门槛极低,只需简单引入依赖,即可快速上手。不过需要注意的是 moka 并没有达到稳定版本,还是存在破坏性更新的情况,在使用时需要注意这一点。

Cargo.toml 中添加 moka 依赖,根据业务场景选择同步或异步版本,在实际开发中,更推荐使用异步版本:

[dependencies]
# 同步缓存
moka = { version = "0.12", features = ["sync"] }
# 异步缓存
moka = { version = "0.12", features = ["future"] }
tokio = { version = "1", features = ["full"] }
anyhow = "1.0"

moka 提供两种核心缓存类型:

基础使用

先从最简单的同步缓存入手,掌握插入、获取、删除、过期等核心操作,后续异步缓存的 API 与之高度一致,降低学习成本。

同步缓存操作入门

演示缓存的创建、插入、获取、删除、清空等基础操作,代码可直接运行:

use moka::sync::Cache;

fn main() {
    // 创建缓存:最大容量1000条数据,超过容量将按 TinyLFU 算法淘汰
    let cache = Cache::builder()
        .max_capacity(1000) // 核心配置:缓存最大条目数
        .build();

    // 插入数据
    cache.insert("user:1", "张三");
    cache.insert("user:2", "李四");

    // 获取数据(返回 Option<T>,不存在则返回 None)
    if let Some(name) = cache.get(&"user:1") {
        println!("获取缓存:{}", name);
    }

    // 删除指定数据(两种方式:invalidate 无返回值,remove 会返回被删除的值)
    // invalidate 删除数据无返回值
    cache.invalidate(&"user:2");
    // remove 删除数据并返回被删除的值
    let removed = cache.remove("user:1"); // 返回 Option<T>,此处为 Some("王五")
    println!("被删除的值:{:?}", removed);

    // 清空所有缓存,谨慎使用,生产环境需避免误操作
    cache.invalidate_all();

    //  获取缓存当前条目数
    println!("缓存当前大小:{}", cache.entry_count());
}

带过期时间的缓存

moka 支持两种常用过期策略,可单独使用或组合使用,满足不同业务的过期需求:

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

fn main() {
    // 创建带过期策略的缓存:存活60秒(TTL),空闲30秒(TTI)
    let cache = Cache::builder()
        .max_capacity(100)
        .time_to_live(Duration::from_secs(60)) // 插入后,60秒内有效
        .time_to_idle(Duration::from_secs(30)) // 最后一次访问后,30秒内无访问则失效
        .build();

    cache.insert("key1", "value1");

    // 5秒后访问,刷新 TTI 计时
    std::thread::sleep(Duration::from_secs(5));
    if let Some(val) = cache.get(&"key1") {
        println!("5秒后访问:{}", val); // 输出:5秒后访问:value1
    }

    // 再等待35秒(累计空闲35秒,超过 TTI 30秒)
    std::thread::sleep(Duration::from_secs(35));
    if cache.get(&"key1").is_none() {
        println!("35秒后,缓存已失效(TTL未到,但TTI超时)");
    }

    // 插入新数据,测试 TTL
    cache.insert("key2", "value2");
    std::thread::sleep(Duration::from_secs(65)); // 超过 TTL 60秒
    if cache.get(&"key2").is_none() {
        println!("65秒后,缓存已失效(TTL超时)");
    }
}

异步缓存操作入门

异步缓存需依赖 tokio 或 async-std 运行时,以下以 tokio 为例,演示异步插入、获取、删除操作:

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

#[tokio::main]
async fn main() {
    //创建异步缓存:最大容量1000,TTL 60秒
    let cache = Cache::builder()
        .max_capacity(1000)
        .time_to_live(Duration::from_secs(60))
        .build();

    // 异步插入
    cache.insert("user:100", "赵六").await;

    // 异步获取
    if let Some(name) = cache.get(&"user:100").await {
        println!("异步获取缓存:{}", name); // 输出:异步获取缓存:赵六
    }

    // 异步删除
    cache.invalidate(&"user:100").await;

    // 异步原子填充:get_with(不存在则计算并插入,避免并发重复计算)
    // 场景:缓存不存在时,从数据库查询并插入缓存,这里模拟耗时操作
    let user = cache
        .get_with("user:101", async {
            tokio::time::sleep(Duration::from_millis(50)).await;
            "孙七"
        })
        .await;
    println!("原子填充缓存:{}", user); // 输出:原子填充缓存:孙七
}

生产环境注意事项

避免手动加锁,正确共享缓存

moka 的缓存实例本身已实现线程安全,无需手动用 Mutex/RwLock 包裹。多线程/异步任务共享缓存时,直接 clone 即可(内部采用 Arc 共享,clone 成本极低),避免多余的锁开销导致性能下降。

大值优化:用 Arc 包装减少克隆开销

moka 的 get 方法会返回 value 的克隆副本,若 value 是大结构体(如大字符串、复杂 JSON),频繁克隆会产生较大内存开销和性能损耗。此时可使用 Arc 包装 value,减少克隆成本:

use moka::sync::Cache;
use std::sync::Arc;

fn main() {
    // 用 Arc 包装大值
    let cache = Cache::new(1000);
    let large_value = Arc::new("大字符串...".repeat(10000));
    cache.insert("key", large_value);

    // 获取时克隆 Arc(成本极低,仅增加引用计数)
    if let Some(val) = cache.get(&"key") {
        let inner_val = &*val; // 无需克隆内部值,直接引用
    }
}

缓存穿透、击穿、雪崩的处理

内存控制:合理设置容量与权重

生产环境中,需根据服务内存大小合理设置缓存容量/权重,避免缓存占用过多内存导致 OOM。建议设置缓存容量为服务可用内存的10%~20%,并结合缓存统计,动态调整容量。

总结

moka 作为 Rust 生态中高性能内存缓存的代表,在我看来现阶段仍不足以用于实际开发环境,毕竟还时不时存在破坏性更新,可以先关注着,实在有本地缓存的需求,那么也还是可以考虑使用 moka 的。

到此这篇关于Rust 高性能内存缓存 moka 完全指南的文章就介绍到这了,更多相关Rust 内存缓存moka内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文