# Secra Memory
一个为插件系统提供统一内存缓存管理的 Rust 库,基于 [moka](https://github.com/moka-rs/moka) 构建。
## 📋 目录
- [功能特性](#功能特性)
- [安装](#安装)
- [快速开始](#快速开始)
- [配置说明](#配置说明)
- [API 文档](#api-文档)
- [使用示例](#使用示例)
- [架构设计](#架构设计)
- [性能优化](#性能优化)
- [错误处理](#错误处理)
- [许可证](#许可证)
## ✨ 功能特性
- **统一治理**:所有缓存操作必须通过 `MemoryManager`,插件不能直接访问底层缓存库
- **强隔离**:每个插件拥有独立的命名空间,避免 Key 冲突
- **生命周期管理**:插件卸载/升级时自动清理相关缓存
- **极简 API**:插件侧 API 简单易用,隐藏底层实现细节
- **与 Cache 模块一致**:实现统一的 `Cache` trait,支持与其他缓存实现(如 Redis)无缝切换
- **高性能**:使用 `DashMap` 和并发优化,支持高并发场景
- **TTL 支持**:支持全局 TTL 配置和 TTL 随机化(防缓存雪崩)
- **模块化清理**:支持按模块清理缓存,灵活管理缓存生命周期
## 📦 安装
在 `Cargo.toml` 中添加依赖:
```toml
[dependencies]
secra-memory = "0.1.0"
```
或者从本地路径:
```toml
[dependencies]
secra-memory = { path = "../secra-memory" }
```
## 🚀 快速开始
### 基座系统
```rust
use secra_memory::{MemoryManager, MemoryConfig};
use std::time::Duration;
// 1. 创建 MemoryManager(使用默认配置)
let memory_manager = MemoryManager::new_with_defaults();
// 或者使用自定义配置
let config = MemoryConfig::default()
.with_system_name("my_system".to_string())
.with_initial_capacity(1000);
let memory_manager = MemoryManager::new(config);
// 2. 为插件创建 Cache 实例
let plugin_cache = memory_manager.create_plugin_cache("user_plugin".to_string());
```
### 插件代码
```rust
use secra_memory::Cache;
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
struct User {
id: u64,
name: String,
email: String,
}
// 1. 设置缓存
let user = User {
id: 123,
name: "Alice".to_string(),
email: "alice@example.com".to_string(),
};
plugin_cache.set("user:123", &user, None).await?;
// 2. 获取缓存
let user: Option<User> = plugin_cache.get("user:123").await?;
// 3. 检查缓存是否存在
let exists = plugin_cache.exists("user:123").await?;
// 4. 删除缓存
plugin_cache.delete("user:123").await?;
// 5. 清理所有缓存
plugin_cache.clear().await?;
// 6. 按模块清理缓存
plugin_cache.clear_module("user").await?; // 清理 user 模块的所有缓存
```
## ⚙️ 配置说明
### MemoryConfig
```rust
use secra_memory::MemoryConfig;
use std::time::Duration;
let config = MemoryConfig {
max_capacity: 10_000, // 最大容量(条目数)
initial_capacity: 100, // 初始容量(条目数)
default_ttl: Duration::from_secs(3600), // 默认 TTL(1 小时)
ttl_random_range: Some(Duration::from_secs(300)), // TTL 随机化范围(±5 分钟)
time_to_idle: Some(Duration::from_secs(1800)), // 空闲过期时间(30 分钟)
system_name: "secra".to_string(), // 系统标识(用于 Key 前缀)
};
```
### 默认配置
- `max_capacity`: 10,000 条目
- `initial_capacity`: 100 条目
- `default_ttl`: 1 小时
- `ttl_random_range`: ±5 分钟(防缓存雪崩)
- `time_to_idle`: 30 分钟
- `system_name`: "secra"
## 📚 API 文档
### MemoryManager
#### `new(config: MemoryConfig) -> Self`
创建新的 `MemoryManager` 实例。
#### `new_with_defaults() -> Self`
使用默认配置创建 `MemoryManager` 实例。
#### `create_plugin_cache(plugin_id: String) -> PluginMemoryCache`
为指定插件创建缓存实例。
#### `clear_plugin(plugin_id: &str) -> Result<u64, CacheError>`
清理指定插件的所有缓存。
#### `clear_plugin_for_upgrade(plugin_id: &str) -> Result<u64, CacheError>`
清理指定插件的缓存(用于升级场景)。
#### `clear_plugin_for_disable(plugin_id: &str, force: bool) -> Result<u64, CacheError>`
清理指定插件的缓存(用于禁用场景)。
#### `clear_module(plugin_id: &str, module: &str) -> Result<u64, CacheError>`
清理指定插件的指定模块缓存。
### Cache Trait
所有缓存实现都实现了 `Cache` trait,提供统一的 API:
#### `get<T>(&self, key: &str) -> Result<Option<T>, CacheError>`
获取缓存值。
#### `set<T>(&self, key: &str, value: &T, ttl: Option<Duration>) -> Result<(), CacheError>`
设置缓存值。
#### `delete(&self, key: &str) -> Result<bool, CacheError>`
删除缓存值。
#### `exists(&self, key: &str) -> Result<bool, CacheError>`
检查缓存键是否存在。
#### `expire(&self, key: &str, ttl: Duration) -> Result<bool, CacheError>`
设置过期时间。
#### `ttl(&self, key: &str) -> Result<Option<Duration>, CacheError>`
获取剩余过期时间。
#### `clear(&self) -> Result<u64, CacheError>`
清空所有缓存。
#### `clear_module(&self, module: &str) -> Result<u64, CacheError>`
清空指定模块的缓存。
## 💡 使用示例
### 示例 1:用户信息缓存
```rust
use secra_memory::Cache;
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize, Clone)]
struct UserInfo {
id: u64,
name: String,
avatar: String,
}
// 设置用户信息缓存
async fn cache_user_info(cache: &impl Cache, user: &UserInfo) -> Result<(), CacheError> {
let key = format!("user:{}", user.id);
cache.set(&key, user, None).await
}
// 获取用户信息缓存
async fn get_user_info(cache: &impl Cache, user_id: u64) -> Result<Option<UserInfo>, CacheError> {
let key = format!("user:{}", user_id);
cache.get(&key).await
}
```
### 示例 2:订单缓存(按模块管理)
```rust
use secra_memory::Cache;
// 设置订单缓存
async fn cache_order(cache: &impl Cache, order_id: &str, order_data: &Order) -> Result<(), CacheError> {
let key = format!("order:{}", order_id);
cache.set(&key, order_data, None).await
}
// 清理所有订单缓存
async fn clear_all_orders(cache: &impl Cache) -> Result<u64, CacheError> {
cache.clear_module("order").await
}
```
### 示例 3:插件生命周期管理
```rust
use secra_memory::MemoryManager;
// 插件升级时清理缓存
async fn upgrade_plugin(manager: &MemoryManager, plugin_id: &str) -> Result<(), CacheError> {
manager.clear_plugin_for_upgrade(plugin_id).await?;
// ... 执行插件升级逻辑 ...
Ok(())
}
// 插件禁用时清理缓存
async fn disable_plugin(manager: &MemoryManager, plugin_id: &str, force: bool) -> Result<(), CacheError> {
manager.clear_plugin_for_disable(plugin_id, force).await?;
// ... 执行插件禁用逻辑 ...
Ok(())
}
```
## 🏗️ 架构设计
### Key 格式规范
所有内存缓存 Key 必须遵循以下格式:
```
{system}:plugin:{plugin_id}:{biz}:{key}
```
**示例:**
- `secra:plugin:user_plugin:user:123`
- `secra:plugin:order_service:order:2024:001`
- `secra:plugin:config_service:config:app:theme`
### 组件说明
1. **MemoryManager**:全局缓存管理器,负责:
- moka 缓存实例管理
- Key 索引维护(使用 `DashMap` 提高并发性能)
- 插件缓存清理
2. **PluginMemoryCache**:插件缓存实例,负责:
- 自动添加命名空间前缀
- Key 格式验证
- 权限检查(确保插件只能操作自己的 Key)
3. **Cache Trait**:统一的缓存接口,支持:
- 与其他缓存实现(如 Redis)无缝切换
- 类型安全的序列化/反序列化
### 数据流
```
插件代码
↓
PluginMemoryCache (添加命名空间前缀)
↓
MemoryManager (Key 索引维护)
↓
moka Cache (底层存储)
```
## ⚡ 性能优化
1. **并发优化**:
- 使用 `DashMap` 替代 `RwLock<HashMap>` 提高并发性能
- 使用 `join_all` 批量并行删除,避免过度 spawn
2. **内存优化**:
- 使用 `String::with_capacity` 预分配容量
- 及时清理索引中的空集合
3. **缓存策略**:
- 支持 TTL 随机化,防止缓存雪崩
- 支持空闲过期时间(TTI)
## 🛡️ 错误处理
### CacheError 类型
```rust
pub enum CacheError {
InvalidKey(String), // Key 格式错误
SerializationFailed(String), // 序列化失败
DeserializationFailed(String), // 反序列化失败
PermissionDenied(String), // 权限拒绝
Other(String), // 其他错误
}
```
### 错误处理示例
```rust
use secra_memory::CacheError;
match cache.get::<User>("user:123").await {
Ok(Some(user)) => println!("找到用户: {:?}", user),
Ok(None) => println!("用户不存在"),
Err(CacheError::InvalidKey(msg)) => eprintln!("Key 格式错误: {}", msg),
Err(CacheError::DeserializationFailed(msg)) => eprintln!("反序列化失败: {}", msg),
Err(e) => eprintln!("其他错误: {}", e),
}
```
## 📝 注意事项
1. **Key 格式限制**:
- Key 不能为空
- Key 长度不能超过 200 字符
- Key 不能包含 `plugin:` 模式(防止绕过隔离)
- Key 只能包含字母、数字、下划线、连字符、冒号
2. **TTL 限制**:
- 当前实现使用全局 TTL 配置
- `set` 方法中的 `ttl` 参数会被忽略(使用全局配置)
- 如需支持每个条目独立的 TTL,需要实现 moka 的 `Expiry` trait
3. **序列化要求**:
- 所有缓存值必须实现 `Serialize` 和 `DeserializeOwned`
- 使用 JSON 格式进行序列化/反序列化
## 🔧 开发
### 构建项目
```bash
cargo build
```
### 运行测试
```bash
cargo test
```
### 运行示例
```bash
cargo run --example your_example
```
## 📄 许可证
[在此添加许可证信息]
## 🤝 贡献
欢迎提交 Issue 和 Pull Request!
## 📞 联系方式
[在此添加联系方式]