# expire_cache: 高性能分代缓存
`expire_cache` 实现了基于分代收集策略的高效过期缓存。它不追踪单个条目的过期时间,而是维护两个数据桶(代),显著降低过期检查的内存开销和 CPU 使用率。
## 特性
- **高性能**:每条目摊销 O(1) 过期开销
- **并发访问**:基于 DashMap 的线程安全操作
- **异步支持**:原生异步初始化 `get_or_init_async`
- **灵活存储**:支持键值映射和集合
- **简洁 API**:清晰的 `get`、`insert` 和初始化接口
## 安装
```toml
[dependencies]
expire_cache = { version = "0.1.17", features = ["dashmap", "get_or_init_async"] }
```
可用特性:
- `dashmap`:启用 DashMap 支持
- `dashset`:启用 DashSet 支持
- `get_or_init`:启用同步初始化
- `get_or_init_async`:启用异步初始化
## 快速开始
### 基本用法
```rust
use expire_cache::Expire;
use dashmap::DashMap;
use std::time::Duration;
#[tokio::main]
async fn main() {
let cache: Expire<DashMap<&str, &str>> = Expire::new(60);
cache.insert("key", "value");
if let Some(val) = cache.get("key") {
println!("Found: {}", *val);
}
// 等待过期
tokio::time::sleep(Duration::from_secs(120)).await;
assert!(cache.get("key").is_none());
}
```
### 异步初始化
```rust
use expire_cache::Expire;
use dashmap::DashMap;
#[tokio::main]
async fn main() -> Result<(), std::io::Error> {
let cache: Expire<DashMap<String, String>> = Expire::new(60);
let value = cache
.get_or_init_async("user_123", |key| async move {
Ok(format!("data_for_{key}"))
})
.await?;
println!("Loaded: {}", *value);
Ok(())
}
```
### 同步初始化
```rust
use expire_cache::Expire;
use dashmap::DashMap;
fn main() -> Result<(), std::io::Error> {
let cache: Expire<DashMap<String, String>> = Expire::new(60);
let value = cache.get_or_init("user_123", |key| {
Ok(format!("data_for_{key}"))
})?;
println!("Loaded: {}", *value);
Ok(())
}
```
### 集合用法
```rust
use expire_cache::Expire;
use dashmap::DashSet;
#[tokio::main]
async fn main() {
let cache: Expire<DashSet<&str>> = Expire::new(60);
cache.insert("active_session", ());
if cache.get("active_session").is_some() {
println!("Session exists");
}
}
```
## API 参考
### `Expire<T: Map>`
- `new(expire: u64) -> Self`:创建带过期周期的缓存(秒)
- `get(&self, key) -> Option<RefVal>`:从缓存检索值
- `insert(&self, key, val)`:向缓存插入值
- `get_or_init(&self, key, func) -> Result<RefVal, E>`:同步初始化
- `get_or_init_async(&self, key, func) -> Result<RefVal, E>`:异步初始化
## 设计
### 分代收集策略
缓存使用双缓冲方法,包含两个代:
1. **插入**:新条目总是进入活跃代
2. **查找**:先检查活跃代,再检查被动代
3. **过期**:后台任务定期清空被动代并交换角色
4. **生命周期**:条目存活时间在 `expire` 到 `2 * expire` 秒之间
这种方法牺牲了绝对精度,换取了显著的吞吐量提升和内存碎片减少。
## 许可证
MulanPSL-2.0