Upstash 是基于 HTTP 的无服务器 Redis。无需连接池、无需保持端口开放、无需维护空闲实例。缓存热点查询、限制恶意调用方、将后台任务排入队列——仅按请求数计费。
进入控制台,点击 Create database,选择以下配置:
创建完成后,你会看到 UPSTASH_REDIS_REST_URL 和 UPSTASH_REDIS_REST_TOKEN,将两者都添加到 .env 文件中。
安装客户端:
npm install @upstash/redis
将任何耗时查询包裹起来:
import { Redis } from "@upstash/redis";
const redis = Redis.fromEnv();
async function getTopProducts() {
const cached = await redis.get<Product[]>("top-products");
if (cached) return cached;
const fresh = await db.query("SELECT * FROM products ORDER BY sales DESC LIMIT 20");
await redis.set("top-products", fresh, { ex: 60 }); // 60s TTL
return fresh;
}
关键使用模式:
ex 单位为秒)。不设置意味着永久缓存,而过期数据比慢数据更糟糕。user:123:plan 而非 user:123。这样可以只失效某个字段,而不必清除全部缓存。redis.del(key)。不要单靠 TTL 来处理用户可见的数据。完整 API 参考:Upstash TS SDK 文档。命令与 Redis 标准一一对应:get、set、incr、lpush、zadd 等。
安装限流辅助库:
npm install @upstash/ratelimit
以下中间件将每个 IP 限制为每 10 秒最多 10 次请求(滑动窗口):
import { Ratelimit } from "@upstash/ratelimit";
import { Redis } from "@upstash/redis";
const ratelimit = new Ratelimit({
redis: Redis.fromEnv(),
limiter: Ratelimit.slidingWindow(10, "10 s"),
analytics: true, // dashboard graphs
});
// Express
app.use(async (req, res, next) => {
const ip = req.headers["x-forwarded-for"] || req.socket.remoteAddress;
const { success, limit, remaining, reset } = await ratelimit.limit(ip);
res.setHeader("X-RateLimit-Limit", limit);
res.setHeader("X-RateLimit-Remaining", remaining);
res.setHeader("X-RateLimit-Reset", reset);
if (!success) {
return res.status(429).json({ error: "Too many requests" });
}
next();
});
限流器选项:
fixedWindow(n, "1 m") — 按固定分钟计数,开销最低,但在窗口边界容易出现流量突发。slidingWindow(n, "10 s") — 平滑限流,可防止边界突发。默认推荐。tokenBucket(n, "1 s", capacity) — 允许最多 capacity 的突发流量,以指定速率匀速补充。适用于允许短时突发的 API。标识符选择:
两个 SDK 在边缘运行时中均可直接使用——基于 HTTP/REST 意味着无需 TCP socket。在你的平台中配置环境变量:
wrangler secret put UPSTASH_REDIS_REST_URL + wrangler secret put UPSTASH_REDIS_REST_TOKEN。fly secrets set UPSTASH_REDIS_REST_URL=…。如果你还需要延迟或定时任务,QStash 就在同一个控制台中提供消息队列功能。它是一个基于 HTTP 的任务执行器:你发送一个任务,QStash 会持续重试,直到你的端点返回 200。
import { Client } from "@upstash/qstash";
const qstash = new Client({ token: process.env.QSTASH_TOKEN });
// Send "welcome email" 5 min after signup
await qstash.publishJSON({
url: "https://yourapp.com/api/jobs/welcome-email",
body: { userId: user.id },
delay: 300, // seconds
});
替代方案:Inngest(更面向工作流,调试体验更好)、Trigger.dev、Temporal(企业级)。QStash 是其中最简单的选择。
redis.del(cacheKey),而不是单靠 TTL。UPSTASH_REDIS_REST_TOKEN 具有管理员级别权限,绝不能暴露给浏览器。如需客户端限流,请使用服务端代理或 Upstash 的只读 Token。价格详情:upstash.com/pricing。