缓存
为你的应用按需接入 Redis、Upstash 或 Cloudflare KV 缓存
LaunchSaaS 采用拆包设计实现缓存支持。核心包 @launchsaas/cache 定义接口;每个 Provider 是独立的包,按需安装即可。
更新时间: 2026-03-15
架构
@launchsaas/cache ← 接口 + Cache 服务类(必须)
@launchsaas/cache-redis ← Redis(TCP,Node.js)
@launchsaas/cache-upstash ← Upstash Redis(HTTP,Serverless / Edge)
@launchsaas/cache-cloudflare-kv ← Cloudflare KV(HTTP,Cloudflare Workers)你只需要安装实际使用的 Provider 包,避免引入不需要的 SDK(redis、@upstash/redis、cloudflare),保持构建体积最小。
LaunchSaaS 默认不安装任何 cache provider,因为具体选择取决于你的部署环境。在你自己的应用中,按需安装匹配部署目标的提供商包。
在你的应用中启用缓存
1. 安装 Provider 包
在你的应用目录下,选择 一个 Provider 安装:
# Node.js 服务器(Redis)
pnpm add @launchsaas/cache-redis
# Serverless / Edge / Vercel(Upstash)
pnpm add @launchsaas/cache-upstash
# Cloudflare Workers / Pages
pnpm add @launchsaas/cache-cloudflare-kv2. 注册环境变量校验
将 Provider 的 keys 导出添加到你应用的 env.ts,确保启动时校验环境变量:
// your-app/src/env.ts
import { createEnv } from "@t3-oss/env-nextjs";
// Redis
import { keys as cacheKeys } from "@launchsaas/cache-redis/keys";
// 或 Upstash
// import { keys as cacheKeys } from "@launchsaas/cache-upstash/keys";
// 或 Cloudflare KV
// import { keys as cacheKeys } from "@launchsaas/cache-cloudflare-kv/keys";
export const env = createEnv({
extends: [
cacheKeys,
// ... 其他 keys
],
// ...
});3. 配置环境变量
Redis
REDIS_URL=redis://localhost:6379
# 带认证:redis://user:password@host:6379
# 带 TLS: rediss://user:password@host:6379Upstash Redis
UPSTASH_REDIS_REST_URL=https://your-endpoint.upstash.io
UPSTASH_REDIS_REST_TOKEN=your-rest-tokenCloudflare KV
CLOUDFLARE_ACCOUNT_ID=your-account-id
CLOUDFLARE_KV_NAMESPACE_ID=your-namespace-id
CLOUDFLARE_API_TOKEN=your-api-token4. 在 src/capabilities.ts 中注册
打开你的应用的 src/capabilities.ts,在 cache 字段中配置缓存 Provider:
// src/capabilities.ts (你的应用 — apps/launchsaas/src/capabilities.ts)
// Redis
import { RedisCacheProvider } from "@launchsaas/cache-redis";
// Upstash Redis
// import { UpstashRedisCacheProvider } from "@launchsaas/cache-upstash";
// Cloudflare KV
// import { CloudflareKVCacheProvider } from "@launchsaas/cache-cloudflare-kv";
export const capabilities = {
// 设为 null 即可禁用缓存
cache: RedisCacheProvider.create(),
// cache: UpstashRedisCacheProvider.create(),
// cache: CloudflareKVCacheProvider.create(),
// ...其他 capabilities
};启用缓存后的效果
初始化完成后,缓存会被以下功能自动使用:
Better Auth 二级存储
Better Auth 在 src/lib/auth/auth.ts 中读取 capabilities.cache。当其不为 null 时,
会话、API Key 和限流数据将存储在缓存中,而非直接查询数据库:
会话查找:~5-10ms(缓存命中) vs ~50-100ms(数据库查询)无需额外代码,模板中已经接好了。
自定义缓存
import { capabilities } from "@/capabilities";
// 缓存为可选时,先检查 capabilities.cache 是否存在
const cache = capabilities.cache;
if (cache) {
await cache.set("my-key", JSON.stringify(data), 3600); // TTL 单位:秒
}
const raw = cache ? await cache.get("my-key") : null;
const data = raw ? JSON.parse(raw) : null;
if (cache) await cache.delete("my-key");Provider 对比
| Redis | Upstash | Cloudflare KV | |
|---|---|---|---|
| 协议 | TCP | HTTP | HTTP |
| 延迟 | 亚毫秒 | ~50-100ms | ~50-100ms |
| Edge / Workers | ✗ | ✓ | ✓ |
| Serverless | 有限 | ✓ | ✓ |
| 适合场景 | 传统服务器 | Vercel / Netlify | Cloudflare 部署 |
Provider 配置指南
Redis — 本地开发
docker run -d -p 6379:6379 redis:7-alpine
# REDIS_URL=redis://localhost:6379Upstash
- 在 console.upstash.com 创建数据库
- 从数据库详情页复制 REST URL 和 REST Token
- 设置
UPSTASH_REDIS_REST_URL和UPSTASH_REDIS_REST_TOKEN
Cloudflare KV
- 在 Cloudflare 控制台 Workers & Pages → KV 创建 KV 命名空间
- 创建具有 Workers KV Storage: Edit 权限的 API Token
- 设置
CLOUDFLARE_ACCOUNT_ID、CLOUDFLARE_KV_NAMESPACE_ID、CLOUDFLARE_API_TOKEN
自定义 Provider
如果内置 Provider 不满足需求(如 Valkey、Momento、DynamoDB),
正确做法是新建一个 cache-xxx 包,与内置 Provider 包保持相同结构。
1. 新建包
packages/capabilities/cache-xxx/
├── package.json
├── tsconfig.json
└── src/
├── keys.ts ← 环境变量校验(有环境变量时添加)
├── provider.ts ← CacheProvider 实现
└── index.ts ← 公开导出package.json
{
"name": "@launchsaas/cache-xxx",
"version": "0.1.0",
"private": true,
"main": "./src/index.ts",
"exports": {
".": "./src/index.ts"
},
"dependencies": {
"@launchsaas/cache": "workspace:*",
"@launchsaas/errors": "workspace:*",
"server-only": "^0.0.1"
}
}src/provider.ts
import "server-only";
import type { CacheProvider } from "@launchsaas/cache";
export class XxxCacheProvider implements CacheProvider {
readonly name = "xxx";
async get(key: string): Promise<string | null> {
// 返回值,找不到则返回 null
}
async set(key: string, value: string, ttl?: number): Promise<void> {
// 存储值;如提供 ttl(单位秒),需按时间过期
}
async delete(key: string): Promise<void> {
// 删除 key
}
static create(): XxxCacheProvider {
// 校验配置 / 初始化客户端
return new XxxCacheProvider();
}
}src/index.ts
export { XxxCacheProvider } from "./provider";
export { keys } from "./keys"; // 无环境变量时可省略CacheProvider 接口只有三个方法,设计极简。ttl 为可选参数,
后端不支持过期时间时可直接忽略。
2. 添加到你的应用
在应用的 package.json 中添加依赖:
"@launchsaas/cache-xxx": "workspace:*"如果 Provider 有环境变量,在 src/env.ts 中注册 keys:
import { keys as cacheKeys } from "@launchsaas/cache-xxx";
export const env = createEnv({
extends: [cacheKeys /* ... */],
});3. 在 src/capabilities.ts 中注册
// src/capabilities.ts (apps/launchsaas/src/capabilities.ts)
import { XxxCacheProvider } from "@launchsaas/cache-xxx";
export const capabilities = {
cache: XxxCacheProvider.create(),
// ...其他 capabilities
};常见问题
"Cache not initialized" 报错
在 capabilities.cache 配置之前就尝试使用缓存。确认 src/capabilities.ts 中的 Provider create() 未抛出错误,且环境变量已正确配置。
Redis 连接被拒绝
TCP 连接是懒加载的(首次使用时才建立)。检查 REDIS_URL 以及 Redis 服务是否可达。
连接错误会以 Redis Client Error: 为前缀输出到 stderr。
Cloudflare KV 404
键不存在时 Provider 会返回 null,这是正常行为。请核实 CLOUDFLARE_KV_NAMESPACE_ID
是否与实际命名空间 ID 一致。