secra-memory

Crates.iosecra-memory
lib.rssecra-memory
version0.1.1
created_at2025-12-30 08:47:57.300246+00
updated_at2025-12-30 08:57:36.114816+00
descriptionA unified memory cache management library for plugin systems, built on top of moka
homepage
repository
max_upload_size
id2012308
size87,282
(BadassFree)

documentation

https://docs.rs/secra-memory

README

Secra Memory

一个为插件系统提供统一内存缓存管理的 Rust 库,基于 moka 构建。

📋 目录

✨ 功能特性

  • 统一治理:所有缓存操作必须通过 MemoryManager,插件不能直接访问底层缓存库
  • 强隔离:每个插件拥有独立的命名空间,避免 Key 冲突
  • 生命周期管理:插件卸载/升级时自动清理相关缓存
  • 极简 API:插件侧 API 简单易用,隐藏底层实现细节
  • 与 Cache 模块一致:实现统一的 Cache trait,支持与其他缓存实现(如 Redis)无缝切换
  • 高性能:使用 DashMap 和并发优化,支持高并发场景
  • TTL 支持:支持全局 TTL 配置和 TTL 随机化(防缓存雪崩)
  • 模块化清理:支持按模块清理缓存,灵活管理缓存生命周期

📦 安装

Cargo.toml 中添加依赖:

[dependencies]
secra-memory = "0.1.0"

或者从本地路径:

[dependencies]
secra-memory = { path = "../secra-memory" }

🚀 快速开始

基座系统

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());

插件代码

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

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:用户信息缓存

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:订单缓存(按模块管理)

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:插件生命周期管理

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 类型

pub enum CacheError {
    InvalidKey(String),              // Key 格式错误
    SerializationFailed(String),    // 序列化失败
    DeserializationFailed(String),  // 反序列化失败
    PermissionDenied(String),       // 权限拒绝
    Other(String),                  // 其他错误
}

错误处理示例

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. 序列化要求

    • 所有缓存值必须实现 SerializeDeserializeOwned
    • 使用 JSON 格式进行序列化/反序列化

🔧 开发

构建项目

cargo build

运行测试

cargo test

运行示例

cargo run --example your_example

📄 许可证

[在此添加许可证信息]

🤝 贡献

欢迎提交 Issue 和 Pull Request!

📞 联系方式

[在此添加联系方式]

Commit count: 0

cargo fmt