#cache #foyer #hybrid #user-friendly #hybrid-cache #disk #facebook-cache-lib

foyer-workspace-hack

由 hakari 管理的 workspace-hack 包

8 个版本 (4 个重大变更)

使用旧的 Rust 2015

0.5.2 2024 年 4 月 24 日
0.5.1 2024 年 4 月 24 日
0.4.0 2024 年 4 月 11 日
0.3.0 2024 年 3 月 12 日
0.1.0 2023 年 11 月 29 日

#5#hybrid-cache

Download history 4347/week @ 2024-04-13 4081/week @ 2024-04-20 1912/week @ 2024-04-27 3275/week @ 2024-05-04 667/week @ 2024-05-11 396/week @ 2024-05-18 467/week @ 2024-05-25 348/week @ 2024-06-01 137/week @ 2024-06-08 164/week @ 2024-06-15 109/week @ 2024-06-22 96/week @ 2024-06-29 27/week @ 2024-07-06 47/week @ 2024-07-20 77/week @ 2024-07-27

每月 165 次下载

Apache-2.0

13KB

foyer

Crates.io Version Crates.io MSRV GitHub License

CI (main) License Checker codecov

foyer 旨在成为 Rust 中的用户友好型混合缓存库。

foyerFacebook/CacheLibben-manes/caffeine 以及其他项目启发,这些项目是 C++ 中的优秀混合缓存库。 foyer 不仅是一个 '用 Rust 重写项目',还提供了一些 CacheLib 目前没有的功能。

特性

  • 混合缓存:无缝集成内存和基于磁盘的缓存,以实现最佳性能和灵活性。
  • 即插即用算法:为用户提供易于替换的缓存算法,确保适应不同的使用场景。
  • 线程安全:构建用于处理高并发,具备强大的线程安全机制,在重负载下保证可靠性能。
  • 用户友好界面:提供简单直观的 API,使缓存集成变得轻松且易于所有级别的开发者使用。

使用方法

要在您的项目中使用 foyer,请将此行添加到 依赖项 部分的 Cargo.toml

foyer = "0.8"

如果您的项目使用的是 nightly Rust 工具链,则必须启用 nightly 功能。

foyer = { version = "0.8", features = ["nightly"] }

开箱即用的内存缓存

use foyer::{Cache, CacheBuilder};

fn main() {
    let cache: Cache<String, String> = CacheBuilder::new(16).build();

    let entry = cache.insert("hello".to_string(), "world".to_string());
    let e = cache.get("hello").unwrap();

    assert_eq!(entry.value(), e.value());
}

易于使用的混合缓存

use foyer::{FsDeviceConfigBuilder, HybridCache, HybridCacheBuilder};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let dir = tempfile::tempdir()?;

    let hybrid: HybridCache<u64, String> = HybridCacheBuilder::new()
        .memory(64 * 1024 * 1024)
        .storage()
        .with_device_config(
            FsDeviceConfigBuilder::new(dir.path())
                .with_capacity(256 * 1024 * 1024)
                .build(),
        )
        .build()
        .await?;

    hybrid.insert(42, "The answer to life, the universe, and everything.".to_string());
    assert_eq!(
        hybrid.get(&42).await?.unwrap().value(),
        "The answer to life, the universe, and everything."
    );

    Ok(())
}

完全配置的混合缓存

use std::sync::Arc;

use anyhow::Result;
use chrono::Datelike;
use foyer::{
    CacheContext, FsDeviceConfigBuilder, HybridCache, HybridCacheBuilder, LfuConfig, LruConfig,
    RatedTicketAdmissionPolicy, RatedTicketReinsertionPolicy, RuntimeConfigBuilder,
};
use tempfile::tempdir;

#[tokio::main]
async fn main() -> Result<()> {
    let dir = tempdir()?;

    let hybrid: HybridCache<u64, String> = HybridCacheBuilder::new()
        .memory(1024)
        .with_shards(4)
        .with_eviction_config(LruConfig {
            high_priority_pool_ratio: 0.1,
        })
        .with_object_pool_capacity(1024)
        .with_hash_builder(ahash::RandomState::default())
        .with_weighter(|_key, value: &String| value.len())
        .storage()
        .with_name("foyer")
        .with_eviction_config(LfuConfig {
            window_capacity_ratio: 0.1,
            protected_capacity_ratio: 0.8,
            cmsketch_eps: 0.001,
            cmsketch_confidence: 0.9,
        })
        .with_device_config(
            FsDeviceConfigBuilder::new(dir.path())
                .with_capacity(64 * 1024 * 1024)
                .with_file_size(4 * 1024 * 1024)
                .with_align(4 * 1024)
                .with_io_size(16 * 1024)
                .build(),
        )
        .with_catalog_shards(4)
        .with_admission_policy(Arc::new(RatedTicketAdmissionPolicy::new(10 * 1024 * 1024)))
        .with_reinsertion_policy(Arc::new(RatedTicketReinsertionPolicy::new(10 * 1024 * 1024)))
        .with_flushers(2)
        .with_reclaimers(2)
        .with_clean_region_threshold(2)
        .with_recover_concurrency(4)
        .with_compression(foyer::Compression::Lz4)
        .with_flush(true)
        .with_runtime_config(
            RuntimeConfigBuilder::new()
                .with_thread_name("foyer")
                .with_worker_threads(4)
                .build(),
        )
        .with_lazy(true)
        .build()
        .await?;

    hybrid.insert(42, "The answer to life, the universe, and everything.".to_string());
    assert_eq!(
        hybrid.get(&42).await?.unwrap().value(),
        "The answer to life, the universe, and everything."
    );

    let e = hybrid
        .entry(20230512, || async {
            let value = fetch().await?;
            Ok((value, CacheContext::default()))
        })
        .await?;
    assert_eq!(e.key(), &20230512);
    assert_eq!(e.value(), "Hello, foyer.");

    Ok(())
}

async fn fetch() -> Result<String> {
    let now = chrono::Utc::now();
    if format!("{}{}{}", now.year(), now.month(), now.day()) == "20230512" {
        return Err(anyhow::anyhow!("Hi, time traveler!"));
    }
    Ok("Hello, foyer.".to_string())
}

其他情况

更多示例和详情请见 此处

支持的 Rust 版本

foyer 是基于最新稳定版本的。最低支持版本为 1.76。当前 foyer 版本不一定能在低于最低支持版本的 Rust 版本上构建。

开发状态 & 路线图

目前,foyer 仍在积极开发中。

开发状态和路线图请见 此处

贡献

欢迎为 foyer 做出贡献! 🥰

提交PR之前,别忘了在本地执行 make checkmake test。🚀

如果CI上的 hakari 检查失败,请删除本地的 Cargo.lock 文件,并再次运行 make fast。🙏

依赖项

~12–22MB
~303K SLoC