mcpField
A
api-database-vercel-kv

api-database-vercel-kv

github.com/agents-inc数据与数据库2657 次安装2 天前更新
代码仓库

关于 api-database-vercel-kv

面向无服务器和边缘应用的 Upstash Redis 模式指南,使用基于 REST 的客户端。内容涵盖初始化、TTL、序列化、批处理、事务、速率限制与会话存储。

主要功能

  1. 01使用 Redis.fromEnv() 初始化客户端
  2. 02JSON 序列化模式
  3. 03TTL 与过期策略
  4. 04哈希操作
  5. 05管道与原子事务
  6. 06速率限制与会话存储

适用场景

  1. 01缓存 API 响应或查询结果
  2. 02实施边缘速率限制
  3. 03存储无服务器会话
  4. 04管理标志与短期计数器

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/agents-inc/skills --skill api-database-vercel-kv

安装后在 Claude Code 中输入/api-database-vercel-kv确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

metadata.yaml
reference.md
examples/
core.md

详细介绍

Vercel KV / Upstash Redis 模式

快速指南: 使用 @upstash/redis(@vercel/kv 的后继产品),通过 REST API 使用适用于无服务器和边缘环境的 Redis。需要注意:与 TCP Redis 相比,REST 每次调用会增加约 5-15ms 的延迟;所有值都会自动序列化为 JSON(对象可透明地往返转换,但 Date 对象会变成字符串);pipeline/multi 会作为单个 HTTP 请求执行,但 pipeline 并非原子操作。使用 Redis.fromEnv() 自动建立连接。务必设置 TTL——无服务器 Redis 按命令计费。


<critical_requirements>

关键要求:使用此技能前

所有代码都必须遵循项目在 CLAUDE.md 中的约定(kebab-case、命名导出、导入顺序、import type、命名常量)

(新项目必须使用 @upstash/redis——@vercel/kv 已于 2024 年 12 月弃用,所有存储都已迁移到 Upstash Redis)

(必须为所有缓存数据设置 TTL——无服务器 Redis 按命令计费,且各套餐有存储限制)

(必须了解这是 REST/HTTP 客户端,而非 TCP Redis 客户端——每条命令都是一个 HTTP 请求,会产生约 5-15ms 的开销,因此应尽可能使用 pipeline 批处理)

</critical_requirements>


示例

  • 核心模式 -- 客户端设置、CRUD 操作、TTL、哈希、pipeline、事务、速率限制、会话

其他资源:

  • reference.md -- 命令快速参考、环境变量、套餐限制

自动检测: Vercel KV、@vercel/kv、@upstash/redis、Upstash Redis、KV_REST_API_URL、KV_REST_API_TOKEN、UPSTASH_REDIS_REST_URL、UPSTASH_REDIS_REST_TOKEN、Redis.fromEnv、kv.set、kv.get、kv.hset、kv.hget、kv.incr、kv.expire、kv.del、createClient、automaticDeserialization、边缘 Redis、无服务器 Redis

适用场景:

  • 在 Vercel 无服务器/边缘函数中缓存 API 响应或数据库查询
  • 在边缘环境进行速率限制(滑动窗口计数器)
  • 无服务器应用的会话存储
  • 功能开关、A/B 测试分组或短期计数器
  • 在 Vercel 上使用 Redis 的任何场景,只要无法使用 TCP 连接(边缘运行时)

涵盖的关键模式:

  • 客户端初始化(Redis.fromEnv()、new Redis())
  • 使用自动 JSON 序列化的基本 CRUD
  • TTL 和过期策略
  • 用于结构化数据的哈希操作
  • pipeline(批量 HTTP 请求)和事务(原子 MULTI/EXEC)
  • 使用有序集合实现速率限制
  • 会话存储模式

不适用场景:

  • 高吞吐量、低延迟的 Redis 工作负载(使用基于 TCP 的 ioredis——REST 会增加每个请求的开销)
  • Pub/Sub 订阅者(REST 是请求-响应模式,不支持持久连接)
  • Redis Streams 消费者(需要 ioredis 等 TCP 客户端)
  • 存储大型值(免费套餐每条记录超过 1 MB,且按命令数量计费)
  • 主数据库(Redis 是缓存/临时存储,而非事实来源)

设计理念

Upstash Redis(原 Vercel KV)是一种基于 REST 的无服务器 Redis,专为无法或不便使用 TCP 连接的边缘和无服务器运行时设计。核心权衡是:在任何地方都能兼容 HTTP,但每个请求都要承担额外延迟。

核心原则:

  1. REST 优先 -- 每条 Redis 命令都是一个 HTTP 请求。它几乎适用于任何环境(边缘、无服务器、浏览器),但每次调用会增加约 5-15ms 的延迟。使用 pipeline 批处理。
  2. 自动序列化 -- 写入时将对象序列化为 JSON,读取时再反序列化。虽然方便,但这意味着 Date 对象、Map、Set 和函数无法被忠实保留。
  3. 为临时存储而设计 -- 为所有数据设置 TTL。无服务器 Redis 按命令计费,且有存储上限。应将其视为缓存,而非数据库。
  4. 无需管理连接 -- 无需连接池、重连逻辑或 error 事件处理程序。每个请求都是无状态 HTTP 请求。

核心模式

包含良好/不良示例对的完整实现:examples/core.md

模式 1:客户端初始化

有两种方式:Redis.fromEnv()(在 Vercel 上优先使用——会自动读取 UPSTASH_REDIS_REST_URL 和 UPSTASH_REDIS_REST_TOKEN)或使用 new Redis({ url, token }) 进行显式配置。切勿将凭据硬编码。

import { Redis } from "@upstash/redis";
const redis = Redis.fromEnv();
export { redis };

模式 2:自动 JSON 序列化

SDK 会在写入时自动将对象序列化为 JSON,并在读取时反序列化。切勿手动调用 JSON.stringify——这会导致重复序列化。使用 get<T>() 获取类型化返回值,使用 satisfies 实现类型安全的写入。Date 对象在往返过程中会变成 ISO 字符串——请改为将时间戳存储为数字。

await redis.set("user:123", data satisfies UserProfile, { ex: TTL_SECONDS });
const user = await redis.get<UserProfile>("user:123"); // UserProfile | null

模式 3:TTL 和过期时间

务必设置 TTL——无服务器 Redis 按命令计费。在 set() 中使用 { ex: seconds } 或 { px: milliseconds }。使用 { nx: true } 创建分布式锁(返回 "OK" 或 null)。不设置 TTL 的键会导致存储无限增长。

await redis.set("cache:key", data, { ex: CACHE_TTL_SECONDS });

模式 4:哈希操作

哈希支持读取或写入部分字段,无需序列化整个对象。使用 hset 写入多个字段,使用 hget/hgetall 读取,使用 hincrby 实现原子计数器。注意:hset 不支持直接设置 TTL——请另行调用 expire()。对于不存在的键,hgetall 返回 null(而不是 {})。


模式 5:管道和事务

管道(redis.pipeline())会将命令批量发送到单个 HTTP 请求中,但不具备原子性。事务(redis.multi())通过 MULTI/EXEC 提供原子性,同样只需发送单个 HTTP 请求。如果多个命令可以批量处理,请避免顺序逐个调用——每次调用都会单独进行一次 HTTP 往返。

const pipe = redis.pipeline();
pipe.set("k1", "v1", { ex: TTL });
pipe.incr("counter");
const results = await pipe.exec<[string, number]>();

**重要:**Upstash REST 事务不支持用于乐观锁的 WATCH。


模式 6:速率限制(滑动窗口)

通过有序集合的分数实现滑动窗口——使用时间戳作为分数执行 zadd,使用 zremrangebyscore 删除过期条目,使用 zcard 计数,并将这些操作全部放入管道中批量执行。对于生产环境中的速率限制,可考虑使用内置算法的 @upstash/ratelimit。


模式 7:缓存旁路辅助函数

通用的 cacheAside<T>(key, fetcher, ttl) 模式:先检查缓存,未命中时再获取数据,并以即发即弃的方式写入缓存,避免缓存故障阻塞响应。


<decision_framework>

决策框架

Upstash Redis 与 ioredis/node-redis 的比较
Which Redis client should I use?
+-- Running in Vercel Edge Runtime? -> @upstash/redis (only option -- no TCP)
+-- Running in Vercel Serverless Functions? -> @upstash/redis (simpler) or ioredis (if you need TCP features)
+-- Need Pub/Sub subscribers? -> ioredis (REST cannot maintain subscriptions)
+-- Need Redis Streams consumers? -> ioredis (requires persistent TCP connection)
+-- Need lowest possible latency (<1ms)? -> ioredis with TCP (REST adds HTTP overhead)
+-- Simple caching/sessions/counters? -> @upstash/redis (zero connection management)
管道、事务还是顺序调用?
How should I batch commands?
+-- Need atomicity (all-or-nothing)? -> redis.multi() (transaction)
+-- Just reducing HTTP round-trips? -> redis.pipeline() (non-atomic batch)
+-- Single independent command? -> Direct call (redis.set, redis.get, etc.)

</decision_framework>


<red_flags>

危险信号

高优先级问题:

  • 在新项目中使用 @vercel/kv——该包已于 2024 年 12 月弃用,请改用 @upstash/redis
  • 缓存键未设置 TTL——会导致存储空间无限增长和账单超出预期
  • 使用 Upstash Redis 时手动调用 JSON.stringify/JSON.parse——SDK 会自动序列化所有值,因此这会导致重复序列化
  • 误以为管道命令具有原子性——管道会批量发送命令以提高 HTTP 效率,但不保证原子性(如需原子执行,请使用 multi())

中优先级问题:

  • 在适合使用管道时仍依次调用 Redis——每次调用都是一次单独的 HTTP 往返(约 5-15 毫秒)
  • 存储大于 1 MB 的值——REST 请求受套餐限制(免费套餐和按量付费套餐上限为 100 MB,但大值会降低性能)
  • 将 Upstash Redis 用作主数据库——它是缓存/临时存储,请始终在其他地方保留可信数据源

常见错误:

  • 误以为缺失键对应的 hgetall 会返回空对象 {}——Upstash 返回 null(而 ioredis 返回 {})
  • 忘记缺失键对应的 get() 会返回 null(而非 undefined)
  • 传入 Date 对象并期待往返后仍为 Date——它们会被序列化为 ISO 字符串,取回时仍是字符串,而非 Date 实例

易踩坑之处与边缘情况:

  • automaticDeserialization: false 会破坏许多 TypeScript 类型——只有在需要原始字符串响应且准备好手动处理类型时,才禁用此选项
  • 使用 ex 选项调用 set 会在覆盖时重置 TTL(这是标准 Redis 行为)——如果对已有 TTL 的键调用 set,新的 ex 值会替换原有值
  • REST 延迟按请求计算,而非按命令计算——包含 10 条命令的管道与单条命令具有相同的 HTTP 开销(一次往返)
  • 免费套餐每月限 500K 条命令,存储空间限 256 MB——请在生产环境中监控用量
  • nx(仅在键不存在时设置)失败时返回 null,成功时返回 "OK"——请显式检查返回值

</red_flags>


<critical_reminders>

重要提醒

所有代码都必须遵循 CLAUDE.md 中的项目规范(kebab-case、命名导出、导入顺序、import type、命名常量)

(新项目必须使用 @upstash/redis——@vercel/kv 已于 2024 年 12 月弃用,且所有存储都已迁移至 Upstash Redis)

(所有缓存数据都必须设置 TTL——无服务器 Redis 按命令计费,并受套餐存储限制)

(必须理解这是 REST/HTTP 客户端,而非 TCP Redis 客户端——每条命令都是一个 HTTP 请求,开销约为 5-15 毫秒,因此应尽可能使用管道批量处理)

不遵守这些规则会导致使用已弃用的包、存储成本无限增长,以及无服务器函数出现不必要的延迟。

</critical_reminders>

评论

支持 Markdown