| Crates.io | expire_set |
| lib.rs | expire_set |
| version | 0.1.9 |
| created_at | 2025-11-21 12:29:04.893286+00 |
| updated_at | 2025-12-19 14:09:50.019873+00 |
| description | High-performance concurrent expiration set using unsafe raw pointers / 基于非安全原始指针的高性能并发过期集合 |
| homepage | https://github.com/js0-site/rust/tree/main/expire_set |
| repository | https://github.com/js0-site/rust.git |
| max_upload_size | |
| id | 1943472 |
| size | 49,001 |
A high-performance, concurrent set with automatic item expiration, built on top of expire_cache using unsafe raw pointers for maximum performance.
expire_set is a specialized Rust library designed for high-throughput scenarios where items need to expire after a short duration, such as caching 404 request paths to prevent DoS attacks.
It is a wrapper around expire_cache, providing a simplified Set interface while leveraging the efficient double-buffering expiration strategy of the underlying library. The implementation uses unsafe raw pointers for optimal performance in concurrent environments.
expire_cache's lock-free and double-buffering mechanisms with unsafe raw pointers.Add this to your Cargo.toml:
[dependencies]
expire_set = "0.1.7"
tokio = { version = "1", features = ["time", "rt"] }
Example usage:
use expire_set::ExpireSet;
use std::time::Duration;
#[tokio::main]
async fn main() {
// Create a set where items expire every 10 seconds
let set = ExpireSet::<String>::new(10);
// Insert items
set.insert("key1".to_string());
// Check existence
if set.contains(&"key1".to_string()) {
println!("Key exists!");
}
// Wait for expiration
tokio::time::sleep(Duration::from_secs(25)).await;
// Item should be gone
assert!(!set.contains(&"key1".to_string()));
}
The core design relies on the Double Buffering mechanism provided by expire_cache:
expire_cache::Expire<HashSet<K>> internally (powered by Papaya).insert and contains methods tailored for Set operations.ExpireSet<K>The main struct. K must implement Hash + Eq + Send + Sync + 'static.
fn new(expire: u64) -> SelfCreates a new ExpireSet.
expire: The duration in seconds before the buffer rotates. Items live for roughly expire to 2 * expire seconds.fn insert(&self, key: K)Inserts a key into the set.
fn contains<Q>(&self, key: &Q) -> boolChecks if the key exists in the set.
Q: The query type that can be borrowed as Ktrue if the key exists, false otherwiseexpire_cache)..
├── Cargo.toml # Project configuration
├── readme/ # Documentation
│ ├── en.md # English README
│ └── zh.md # Chinese README
├── src/
│ └── lib.rs # Source code (ExpireSet implementation)
└── tests/
│ └── main.rs # Integration tests
The Origin of Double Buffering
The "rotating cache" technique used in this project is analogous to Double Buffering in computer graphics.
Double buffering originated in the late 1960s and became standard in the 1980s with systems like the Amiga. In graphics, it involves drawing to a hidden "back buffer" while displaying the "front buffer," then swapping them instantly to prevent screen tearing.
Similarly, expire_set (via expire_cache) writes to a "current" buffer while keeping the "previous" buffer available for reads. When the timer fires, it "swaps" the buffers and clears the old one, ensuring a smooth transition and efficient bulk expiration.
This project is an open-source component of js0.site ⋅ Refactoring the Internet Plan.
We are redefining the development paradigm of the Internet in a componentized way. Welcome to follow us:
基于 expire_cache 构建的高性能并发集合,使用非安全原始指针实现最大性能,支持自动过期。
expire_set 是一个专为高吞吐量场景设计的 Rust 库,适用于需要短时间过期的项目,例如缓存 404 请求路径以防止 DoS 攻击。
它是 expire_cache 的封装,提供了简化的 Set 接口,同时利用了底层库高效的双缓冲过期策略。实现使用非安全原始指针在并发环境中实现最佳性能。
expire_cache 的无锁和双缓冲机制,配合非安全原始指针实现最优性能。在 Cargo.toml 中添加:
[dependencies]
expire_set = "0.1.7"
tokio = { version = "1", features = ["time", "rt"] }
代码示例:
use expire_set::ExpireSet;
use std::time::Duration;
#[tokio::main]
async fn main() {
// 创建集合,每 10 秒轮转一次
let set = ExpireSet::<String>::new(10);
// 插入数据
set.insert("key1".to_string());
// 查询存在性
if set.contains(&"key1".to_string()) {
println!("Key exists!");
}
// 等待过期
tokio::time::sleep(Duration::from_secs(25)).await;
// 数据已清除
assert!(!set.contains(&"key1".to_string()));
}
核心设计依赖于 expire_cache 提供的 双缓冲 机制:
expire_cache::Expire<HashSet<K>>(基于 Papaya)。insert 和 contains 方法。ExpireSet<K>主结构体。K 必须实现 Hash + Eq + Send + Sync + 'static。
fn new(expire: u64) -> Self创建新 ExpireSet。
expire: 缓冲区轮转间隔(秒)。项目存活时间约为 expire 到 2 * expire 秒。fn insert(&self, key: K)将键插入集合。
fn contains<Q>(&self, key: &Q) -> bool检查键是否存在于集合中。
Q: 可借用的查询类型true,否则返回 falseexpire_cache)。.
├── Cargo.toml # 项目配置
├── readme/ # 文档目录
│ ├── en.md # 英文说明
│ └── zh.md # 中文说明
├── src/
│ └── lib.rs # 源代码 (ExpireSet 实现)
└── tests/
└── main.rs # 集成测试
双缓冲技术的起源
本项目使用的"轮转缓存"技术类比于计算机图形学中的 双缓冲(Double Buffering)。
双缓冲起源于 20 世纪 60 年代末,并在 80 年代随着 Amiga 等系统的出现成为标准。在图形学中,它涉及在显示"前缓冲区"的同时向隐藏的"后缓冲区"绘图,然后瞬间交换两者以防止画面撕裂。
类似地,expire_set(通过 expire_cache)写入"当前"缓冲区,同时保留"上一个"缓冲区供读取。当定时器触发时,它"交换"缓冲区并清空旧缓冲区,确保平滑过渡和高效批量过期。
本项目为 js0.site ⋅ 重构互联网计划 的开源组件。
我们正在以组件化的方式重新定义互联网的开发范式,欢迎关注: