| name | hai-cache |
| description | 使用 @h-ai/cache 进行内存或 Redis 缓存操作(kv/hash/list/set/zset/分布式锁);当需求涉及缓存读写、TTL 管理、集合运算、排行榜、缓存一致性策略或分布式互斥锁时使用。 |
hai-cache
能力契约
| 项目 | 契约 |
|---|
| 能力 | 使用 @h-ai/cache 进行内存或 Redis 缓存操作(kv/hash/list/set/zset/分布式锁);当需求涉及缓存读写、TTL 管理、集合运算、排行榜、缓存一致性策略或分布式互斥锁时使用。 |
| 适用场景 | 当任务与 hai-cache 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
| 输入 | 模块配置、类型化业务参数、依赖初始化状态和目标运行环境 |
| 输出 | 符合模块公共 API 的实现或示例;业务结果使用 HaiResult,并同步必要测试与文档 |
| 限制 | 遵守 init → use → close 生命周期与运行环境边界;不绕过类型、授权、输入校验或敏感信息保护 |
@h-ai/cache 提供统一缓存接口,支持 Memory 与 Redis 后端,包含 KV / Hash / List / Set / ZSet / 分布式锁 六类操作。
运行环境
⚠️ 服务端模块(Node.js only)。 浏览器端无需直接操作缓存,由服务端模块(如 IAM、Scheduler)内部使用。
适用场景
- 缓存热点数据减少数据库查询
- 会话存储(配合 IAM)
- 分布式缓存(Redis)与本地测试缓存(Memory)
- 集合操作(权限缓存、标签集合)
- 排行榜(ZSet)与队列(List)
- 分布式锁(多节点部署互斥控制)
使用步骤
1. 配置
type: ${HAI_CACHE_TYPE:memory}
2. 初始化与关闭
import { cache } from '@h-ai/cache'
await cache.init(core.config.get('cache'))
await cache.close()
cache.config 返回的是脱敏后的配置快照;Redis password / url 等敏感值不会原样暴露给日志或调试输出。
核心 API
KV 操作(cache.kv)
| 方法 | 说明 |
|---|
get / set / del / exists | 基础读写与存在性判断 |
expire / expireAt / ttl / persist | TTL 管理 |
incr / incrBy / decr / decrBy | 计数器操作 |
mget / mset | 批量读写 |
scan / keys / type | Key 检索与类型判断 |
await cache.kv.set('user:123', { name: '张三' }, { ex: 3600 })
const result = await cache.kv.get<{ name: string }>('user:123')
if (result.success && result.data) {
}
await cache.kv.del('user:123')
Hash/List/Set/ZSet(cache.hash/list/set_/zset)
cache.hash:对象字段读写(如用户 profile 局部更新)
cache.list:队列/消息顺序处理
cache.set_:去重集合(成员关系、权限集合)
cache.zset:分数排序(排行榜、权重调度)
await cache.hash.hset('profile:1', { nickname: 'alice' })
await cache.list.lpush('queue:jobs', 'job-1', 'job-2')
await cache.set_.sadd('role:admin:perms', 'user.read', 'user.write')
await cache.zset.zadd('rank:daily', { member: 'u1', score: 100 })
分布式锁(cache.lock)
| 方法 | 说明 |
|---|
acquire | 尝试获锁(SET NX EX),返回 true/false |
release | 释放锁(支持 owner 验证,防止误释放) |
isLocked | 检查锁是否被持有 |
extend | 续期锁 TTL(支持 owner 验证) |
const acquired = await cache.lock.acquire('my-lock', { ttl: 30, owner: 'node-1' })
if (acquired.success && acquired.data) {
try {
}
finally {
await cache.lock.release('my-lock', 'node-1')
}
}
await cache.lock.extend('my-lock', 60, 'node-1')
const locked = await cache.lock.isLocked('my-lock')
最佳实践:
owner 使用稳定的节点标识(如 nodeId),不要每次随机生成
- 释放锁时传入
owner 防止误释放他人锁
- Memory 后端适合开发/测试;Redis 后端用 Lua 脚本保证 release/extend 原子性
错误码 — HaiCacheError
| 错误码 | code | 说明 |
|---|
HaiCacheError.CONNECTION_FAILED | hai:cache:001 | 连接失败 |
HaiCacheError.OPERATION_FAILED | hai:cache:002 | 操作失败 |
HaiCacheError.SERIALIZATION_FAILED | hai:cache:003 | 序列化失败 |
HaiCacheError.DESERIALIZATION_FAILED | hai:cache:004 | 反序列化失败 |
HaiCacheError.KEY_NOT_FOUND | hai:cache:005 | 键不存在 |
HaiCacheError.TIMEOUT | hai:cache:006 | 超时 |
HaiCacheError.NOT_INITIALIZED | hai:cache:010 | 未初始化 |
HaiCacheError.UNSUPPORTED_TYPE | hai:cache:011 | 不支持的缓存类型 |
HaiCacheError.CONFIG_ERROR | hai:cache:012 | 配置错误 |
常见模式
缓存穿透保护
async function getUserCached(userId: string) {
const cached = await cache.kv.get<User>(`user:${userId}`)
if (cached.success && cached.data)
return cached.data
const user = await userRepo.findById(userId)
if (user.success && user.data) {
await cache.kv.set(`user:${userId}`, user.data, { ex: 3600 })
return user.data
}
return null
}
分布式锁保护共享资源
const lockKey = 'batch:import'
const acquired = await cache.lock.acquire(lockKey, { ttl: 60, owner: nodeId })
if (acquired.success && acquired.data) {
try {
await runBatchImport()
}
finally {
await cache.lock.release(lockKey, nodeId)
}
}
else {
logger.info('Another node is running the import')
}
相关 Skills
hai-build:模块初始化顺序(cache 在 db 之后、iam 之前)
hai-core:配置与 HaiResult 模型
hai-iam:会话存储与权限缓存(底层使用 cache)
hai-scheduler:定时任务分布式锁(底层使用 cache.lock)
hai-reach:消息发送互斥锁(底层使用 cache.lock)
hai-kit:SvelteKit 集成层