# Secra Cache
一个基于 Redis 的统一缓存管理库,专为插件化架构设计,提供强隔离、生命周期管理和极简 API。
## 📋 目录
- [功能特性](#功能特性)
- [快速开始](#快速开始)
- [安装](#安装)
- [使用文档](#使用文档)
- [基座系统集成](#基座系统集成)
- [插件使用](#插件使用)
- [API 参考](#api-参考)
- [Key 格式规范](#key-格式规范)
- [配置说明](#配置说明)
- [错误处理](#错误处理)
- [最佳实践](#最佳实践)
- [设计文档](#设计文档)
## ✨ 功能特性
- **统一治理**:所有缓存操作必须通过 `CacheManager`,插件不能直接访问 Redis
- **强隔离**:每个插件拥有独立的命名空间,避免 Key 冲突
- **生命周期管理**:插件卸载/升级时自动清理相关缓存
- **极简 API**:插件侧 API 简单易用,隐藏 Redis 细节
- **可扩展性**:支持未来扩展(配额、监控、限流等)
- **异步支持**:基于 Tokio 异步运行时,高性能
- **类型安全**:利用 Rust 类型系统,编译时保证安全
## 🚀 快速开始
### 安装
在 `Cargo.toml` 中添加依赖:
```toml
[dependencies]
secra-cache = { version = "0.1.2", features = ["rustis"] }
```
### 运行示例
项目提供了一个完整的示例,展示所有主要功能:
```bash
# 确保 Redis 服务正在运行(默认 localhost:6379)
# 或设置环境变量指定 Redis 地址
export REDIS_URL="redis://localhost:6379"
# 运行示例
cargo run --example basic_demo
```
示例演示了以下功能:
- 创建 CacheManager 和插件缓存实例
- 基本缓存操作(set、get、delete、exists)
- TTL 管理(设置、查询、延长过期时间)
- 循环操作(模拟批量操作)
- 模块化缓存管理
- 插件生命周期管理
- Redis 连接健康检查
- 错误处理
### 基本使用
#### 基座系统
```rust
use secra_cache::CacheManager;
// 1. 创建 CacheManager
let cache_manager = CacheManager::new_with_defaults(
"redis://localhost:6379",
).await?;
// 或者:传入已创建的 Redis client
// let client = rustis::client::Client::connect("redis://localhost:6379").await?;
// let cache_manager = CacheManager::new_with_client_defaults(client).await?;
// 2. 为插件创建 Cache 实例
let plugin_cache = cache_manager.create_plugin_cache("user_plugin".to_string());
```
#### 插件代码
```rust
use secra_cache::Cache;
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
struct User {
id: u64,
name: String,
}
// 1. 设置缓存
let user = User {
id: 123,
name: "Alice".to_string(),
};
plugin_cache.set("user:123", &user, None).await?;
// 2. 获取缓存
let user: Option<User> = plugin_cache.get("user:123").await?;
// 3. 删除缓存
plugin_cache.delete("user:123").await?;
// 4. 检查缓存是否存在
let exists = plugin_cache.exists("user:123").await?;
// 5. 清理所有缓存
plugin_cache.clear().await?;
// 6. 按模块清理缓存
plugin_cache.clear_module("user").await?; // 清理 user 模块的所有缓存
```
## 📖 使用文档
### 基座系统集成
基座系统负责创建和管理 `CacheManager` 实例,并为每个插件创建独立的缓存实例。
#### 创建 CacheManager
```rust
use secra_cache::{CacheManager, CacheConfig};
// 方式 1: 使用默认配置
let cache_manager = CacheManager::new_with_defaults(
"redis://localhost:6379"
).await?;
// 方式 1.1: 传入已创建的 Redis client(默认配置)
// let client = rustis::client::Client::connect("redis://localhost:6379").await?;
// let cache_manager = CacheManager::new_with_client_defaults(client).await?;
// 方式 2: 使用自定义配置
let config = CacheConfig {
redis_url: "redis://localhost:6379".to_string(),
key_prefix: "secra".to_string(),
default_ttl: Some(3600), // 默认 TTL 1 小时
// ... 其他配置
};
let cache_manager = CacheManager::new(config).await?;
// 方式 2.1: 传入已创建的 Redis client(自定义配置)
// let client = rustis::client::Client::connect("redis://localhost:6379").await?;
// let cache_manager = CacheManager::new_with_client(client, config).await?;
```
#### 为插件创建缓存实例
```rust
// 为插件创建缓存实例
let plugin_cache = cache_manager.create_plugin_cache("user_plugin".to_string());
// 插件卸载时,清理该插件的所有缓存
cache_manager.remove_plugin_cache("user_plugin").await?;
```
### 插件使用
插件通过 `Cache` trait 提供的 API 进行缓存操作,无需关心 Redis 细节。
#### 基本操作
```rust
use secra_cache::Cache;
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize, Clone, Debug)]
struct Product {
id: u64,
name: String,
price: f64,
}
// 设置缓存(无 TTL)
let product = Product {
id: 1,
name: "iPhone".to_string(),
price: 9999.0,
};
cache.set("product:1", &product, None).await?;
// 设置缓存(带 TTL,单位:秒)
cache.set("product:1", &product, Some(3600)).await?;
// 获取缓存
match cache.get::<Product>("product:1").await? {
Some(product) => println!("找到产品: {:?}", product),
None => println!("缓存未命中"),
}
// 删除缓存
cache.delete("product:1").await?;
// 检查缓存是否存在
if cache.exists("product:1").await? {
println!("缓存存在");
}
```
#### 批量操作
```rust
// 批量设置
let mut items = Vec::new();
items.push(("key1", "value1"));
items.push(("key2", "value2"));
cache.set_many(&items, Some(3600)).await?;
// 批量获取
let keys = vec!["key1", "key2"];
let values: Vec<Option<String>> = cache.get_many(&keys).await?;
// 批量删除
cache.delete_many(&keys).await?;
```
#### 模块化缓存管理
```rust
// 按模块设置缓存(推荐)
cache.set("user:123", &user, None).await?; // user 模块
cache.set("order:456", &order, None).await?; // order 模块
// 清理特定模块的所有缓存
cache.clear_module("user").await?; // 只清理 user 模块的缓存
// 清理所有缓存
cache.clear().await?; // 清理该插件的所有缓存
```
#### TTL 管理
```rust
// 设置 TTL
cache.set_ttl("key", 3600).await?;
// 获取剩余 TTL(秒)
let ttl = cache.get_ttl("key").await?;
match ttl {
Some(seconds) => println!("剩余 TTL: {} 秒", seconds),
None => println!("Key 不存在或没有设置 TTL"),
}
// 移除 TTL(使 Key 永久有效)
cache.remove_ttl("key").await?;
```
## 🔑 Key 格式规范
所有 Redis Key 必须遵循以下格式:
```
{system}:{plugin_id}:{biz}:{key}
```
### 格式说明
- `{system}`: 系统前缀,默认 `secra`,可通过配置修改
- `{plugin_id}`: 插件 ID,由基座系统传入
- `{biz}`: 业务模块标识,建议使用业务领域名称(如 `user`、`order`)
- `{key}`: 具体的缓存键
### 示例
```
secra:user_plugin:user:123
secra:order_service:order:2024:001
secra:payment_plugin:payment:txn:abc123
```
### 命名建议
- **业务模块** (`biz`):使用小写字母和下划线,如 `user_profile`、`order_list`
- **缓存键** (`key`):使用有意义的标识符,如用户 ID、订单号等
- **避免冲突**:不同业务模块使用不同的 `biz` 前缀
## ⚙️ 配置说明
### CacheConfig
```rust
use secra_cache::CacheConfig;
let config = CacheConfig {
redis_url: "redis://localhost:6379".to_string(),
key_prefix: "secra".to_string(), // Key 前缀
default_ttl: Some(3600), // 默认 TTL(秒),None 表示永久
connection_timeout: Some(5000), // 连接超时(毫秒)
// ... 其他配置项
};
```
### 环境变量支持
可以通过环境变量配置 Redis 连接:
```bash
export REDIS_URL="redis://localhost:6379"
export REDIS_KEY_PREFIX="secra"
export REDIS_DEFAULT_TTL="3600"
```
## 🛠️ API 参考
### Cache Trait
`Cache` trait 定义了插件可用的所有缓存操作:
```rust
#[async_trait]
pub trait Cache: Send + Sync {
/// 设置缓存
async fn set<T: Serialize + Send + Sync>(
&self,
key: &str,
value: &T,
ttl: Option<u64>,
) -> Result<(), CacheError>;
/// 获取缓存
async fn get<T: DeserializeOwned + Send + Sync>(
&self,
key: &str,
) -> Result<Option<T>, CacheError>;
/// 删除缓存
async fn delete(&self, key: &str) -> Result<(), CacheError>;
/// 检查缓存是否存在
async fn exists(&self, key: &str) -> Result<bool, CacheError>;
/// 设置 TTL
async fn set_ttl(&self, key: &str, ttl: u64) -> Result<(), CacheError>;
/// 获取剩余 TTL
async fn get_ttl(&self, key: &str) -> Result<Option<u64>, CacheError>;
/// 移除 TTL
async fn remove_ttl(&self, key: &str) -> Result<(), CacheError>;
/// 批量设置
async fn set_many<T: Serialize + Send + Sync>(
&self,
items: &[(&str, &T)],
ttl: Option<u64>,
) -> Result<(), CacheError>;
/// 批量获取
async fn get_many<T: DeserializeOwned + Send + Sync>(
&self,
keys: &[&str],
) -> Result<Vec<Option<T>>, CacheError>;
/// 批量删除
async fn delete_many(&self, keys: &[&str]) -> Result<(), CacheError>;
/// 清理所有缓存
async fn clear(&self) -> Result<(), CacheError>;
/// 清理指定模块的缓存
async fn clear_module(&self, module: &str) -> Result<(), CacheError>;
}
```
### CacheManager
```rust
impl CacheManager {
/// 创建 CacheManager(使用默认配置)
pub async fn new_with_defaults(redis_url: &str) -> Result<Self, CacheError>;
/// 创建 CacheManager(使用自定义配置)
pub fn new(config: CacheConfig) -> Result<Self, CacheError>;
/// 为插件创建缓存实例
pub fn create_plugin_cache(&self, plugin_id: String) -> PluginCache;
/// 移除插件缓存(清理该插件的所有缓存)
pub async fn remove_plugin_cache(&self, plugin_id: &str) -> Result<(), CacheError>;
}
```
## ❌ 错误处理
### CacheError
所有操作可能返回 `CacheError`:
```rust
use secra_cache::CacheError;
match cache.get::<User>("user:123").await {
Ok(Some(user)) => println!("找到用户: {:?}", user),
Ok(None) => println!("缓存未命中"),
Err(CacheError::RedisError(e)) => eprintln!("Redis 错误: {}", e),
Err(CacheError::SerializationError(e)) => eprintln!("序列化错误: {}", e),
Err(e) => eprintln!("其他错误: {}", e),
}
```
### 错误类型
- `RedisError`: Redis 连接或操作错误
- `SerializationError`: 序列化/反序列化错误
- `InvalidKeyError`: Key 格式错误
- `TimeoutError`: 操作超时
## 💡 最佳实践
### 1. 使用模块化 Key 设计
```rust
// ✅ 推荐:使用模块前缀
cache.set("user:123", &user, None).await?;
cache.set("user:profile:123", &profile, None).await?;
cache.set("order:456", &order, None).await?;
// ❌ 不推荐:扁平化 Key
cache.set("123", &user, None).await?;
cache.set("456", &order, None).await?;
```
### 2. 合理设置 TTL
```rust
// 根据数据特性设置 TTL
cache.set("user:123", &user, Some(3600)).await?; // 用户数据:1 小时
cache.set("hot_news:1", &news, Some(300)).await?; // 热点新闻:5 分钟
cache.set("config:app", &config, None).await?; // 配置数据:永久
```
### 3. 使用批量操作提高性能
```rust
// ✅ 推荐:批量操作
let keys = vec!["user:1", "user:2", "user:3"];
let users: Vec<Option<User>> = cache.get_many(&keys).await?;
// ❌ 不推荐:循环单个操作
for key in keys {
let user = cache.get::<User>(key).await?;
// ...
}
```
### 4. 插件卸载时清理缓存
```rust
// 基座系统:插件卸载时
cache_manager.remove_plugin_cache("user_plugin").await?;
```
### 5. 处理缓存未命中
```rust
match cache.get::<User>("user:123").await? {
Some(user) => Ok(user),
None => {
// 从数据库加载
let user = load_user_from_db(123).await?;
// 写入缓存
cache.set("user:123", &user, Some(3600)).await?;
Ok(user)
}
}
```
### 6. 类型安全
```rust
// ✅ 推荐:使用强类型
#[derive(Serialize, Deserialize)]
struct User { /* ... */ }
cache.set("user:123", &user, None).await?;
let user: Option<User> = cache.get("user:123").await?;
// ❌ 不推荐:使用字符串
cache.set("user:123", &user_json_string, None).await?;
```
## 📚 设计文档
详细的设计文档请参考项目文档目录(如果存在):
- `01-架构设计.md`:整体架构和调用关系
- `02-Key设计规范.md`:Key 命名规范和隔离机制
- `03-核心能力设计.md`:get/set/del/exists、TTL、序列化
- `04-生命周期管理.md`:插件卸载/升级时的缓存清理
- `05-接口设计.md`:Cache trait、CacheManager、使用示例
- `06-进阶能力.md`:批量操作、分布式锁、防穿透/雪崩
- `07-反模式与约束.md`:禁止行为和强制约束
- `08-实现指南.md`:实现步骤和最佳实践
## 🔧 依赖项
主要依赖:
- `rustis`: Redis 客户端
- `serde` / `serde_json`: 序列化/反序列化
- `tokio`: 异步运行时
- `async-trait`: 异步 trait 支持
- `dashmap`: 并发数据结构
- `tracing`: 结构化日志
- `thiserror`: 错误处理
详细依赖信息请参考 [DEPENDENCIES.md](./DEPENDENCIES.md)。
## 📝 许可证
本项目采用双重许可证:
- **MIT License** - 详见 [LICENSE-MIT](LICENSE-MIT)
- **Apache License 2.0** - 详见 [LICENSE-APACHE](LICENSE-APACHE)
您可以选择任一许可证使用本项目。
## 🤝 贡献
欢迎提交 Issue 和 Pull Request!
## 📞 联系方式
- **项目仓库**: [https://github.com/secra/secra-cache](https://github.com/secra/secra-cache)
- **问题反馈**: 请在 GitHub Issues 中提交