Cloudflare Workers 入门 (2):数据存储实战——KV 与 D1 数据库
1. 引言:边缘计算的“数据重力”问题
在上一篇中,我们成功让 "Hello World" 在毫秒间响应。但现实世界的应用都需要存储数据:用户配置、购物车、文章内容等。
传统的架构是:计算在边缘,数据在中心。
这就好比你在家门口(边缘)开了个快递点,但每次取货都要去市中心的总仓库(中心数据库)跑一趟。这显然不合理。
Cloudflare 的解决方案是构建边缘原生 (Edge Native) 的存储。今天我们重点介绍最常用的两个:Workers KV 和 D1。
2. Workers KV:极速读,最终一致
什么是 KV?
全称 Key-Value Storage。你可以把它理解为一个分布在全球的、超级巨大的 Redis。
它的特性:
- 读极快 (Low Latency Reads): 比如你在纽约写入一条数据,它会并在后台默默同步到全球节点。之后伦敦的用户读取时,是直接从伦敦节点读取缓存,速度极快。
- 写稍慢 (Eventual Consistency): 数据同步到全球需要时间(通常在 60秒内)。所以它不适合存“银行余额”这种需要强一致性的数据,但非常适合存配置、网页缓存、以及我们今天要做的——短链接重定向。
3. D1:边缘上的 SQL 数据库
什么是 D1?
KV 只能通过 Key 查 Value,如果你需要 SELECT * FROM users WHERE age > 18 这种复杂查询怎么办?
D1 就是建立在 SQLite 基础上的边缘数据库。
它的特性:
- 支持 SQL: 以前在 Serverless 上用 SQL 很痛苦(连接池耗尽问题),D1 完美解决了这个问题。
- 低成本: 基于 SQLite,极其轻量。
- 适用场景: 用户表、订单表、内容管理系统 (CMS)。
4. 实战:构建一个“短链接生成器”
我们将使用 Workers KV 来构建这个项目。因为短链接系统的特点是:创建一次 (写),读取无数次 (读),且不需要复杂的 SQL 查询,完美契合 KV 的特性。
目标功能:
- 用户访问
POST /create带上长链接,返回一个短 ID。 - 用户访问
GET /:id,Worker 从 KV 读取长链接,并重定向。
第一步:创建 KV 命名空间
在终端运行:
npx wrangler kv:namespace create "LINKS"
你会看到输出里有一个 id,把它复制下来。
第二步:配置 wrangler.toml
打开项目根目录的配置文件,告诉 Worker 它有权访问这个 KV:
name = "my-short-url"
main = "src/index.ts"
compatibility_date = "2023-10-02"
# 绑定 KV
[[kv_namespaces]]
binding = "LINKS" # 代码里用这个名字调用
id = "这里填你刚才复制的ID"
第三步:编写代码 (src/index.ts)
这里我们需要用到 TypeScript 的 Env 接口来获得智能提示。
// 定义环境变量接口,告诉 TS 我们有一个叫 LINKS 的 KV
interface Env {
LINKS: KVNamespace;
}
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
const url = new URL(request.url);
const { pathname } = url;
// === 功能 1: 创建短链接 (POST /create) ===
if (request.method === "POST" && pathname === "/create") {
const body = await request.json() as { url?: string };
if (!body.url) {
return new Response("Missing URL", { status: 400 });
}
// 生成一个随机短 ID (这里简单用随机字符串,实际可用更优算法)
const shortId = Math.random().toString(36).substring(2, 8);
// 写入 KV!
// 第一个参数是 Key,第二个是 Value
await env.LINKS.put(shortId, body.url);
return new Response(JSON.stringify({
shortId,
shortUrl: `${url.origin}/${shortId}`
}), {
headers: { "content-type": "application/json" }
});
}
// === 功能 2: 重定向访问 (GET /:id) ===
// 如果路径不是 /create 且不是根目录,假设它是 shortId
const shortId = pathname.slice(1); // 去掉开头的 /
if (shortId) {
// 从 KV 读取!
const longUrl = await env.LINKS.get(shortId);
if (longUrl) {
// 302 重定向到长链接
return Response.redirect(longUrl, 302);
} else {
return new Response("Link not found", { status: 404 });
}
}
return new Response("Welcome to Edge Shortener!");
},
};
第四步:本地测试与部署
# 本地测试 (Wrangler 会模拟一个本地 KV)
npx wrangler dev
# 部署上线
npx wrangler deploy
部署成功后,你用 Postman 或 curl 发送一个 POST 请求,瞬间就能获得一个短链接。当你访问这个短链接时,Worker 会在毫秒级时间内从 KV 查到数据并将你重定向。
5. 什么时候用 KV,什么时候用 D1?
为了方便大家记忆,我总结了一个对比表:
| 特性 | Workers KV | D1 (SQLite) |
| 数据模型 | Key-Value (键值对) | Relational (关系型表格) |
| 查询能力 | 只能通过 Key 查 | 支持复杂的 SQL (Join, Where, Group By) |
| 一致性 | 最终一致 (写之后可能需要几十秒全球同步) | 强一致 (基于单写节点) |
| 最佳场景 | 缓存、配置、Session、重定向 | 用户数据、电商库存、博客文章 |
| 典型项目 | 短链接、个人主页配置 | 留言板、任务管理系统 |
6. 总结
今天我们给 Worker 加上了“记忆”。通过 Workers KV,我们实现了一个无需维护服务器、无需运维 Redis 的短链接系统。
到现在为止,我们已经学会了:
- 写 API (Request/Response)。
- 存取简单数据 (KV)。