13个版本 (6个重大变更)
0.7.5 | 2024年4月28日 |
---|---|
0.7.4 | 2024年4月28日 |
0.6.0 | 2024年4月11日 |
0.5.1 | 2024年3月13日 |
0.1.0 | 2023年11月29日 |
#6 in #hybrid-cache
510KB
11K SLoC
foyer
foyer旨在成为Rust中用户友好的混合缓存库。
foyer受到Facebook/CacheLib、ben-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, RecoverMode, 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)
.with_direct(true)
.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_mode(RecoverMode::QuietRecovery)
.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。不能保证在低于最低支持版本的Rust版本上构建当前的foyer版本。
开发状态 & 路线图
目前,foyer仍在积极开发中。
开发状态和路线图请参见此处。
贡献
foyer的热心贡献受到欢迎!🥰
在提交PR之前,请务必在本地上执行make check
和make test
。🚀
依赖项
~22–35MB
~537K SLoC