跳到主要内容

KV 存储

Cloudflare KV 是一个全球分布的键值存储服务,专为读多写少的场景设计。它非常适合存储配置数据、缓存、会话信息等。

KV 简介

什么是 KV?

KV(Key-Value)是一个分布式键值存储,数据存储在边缘节点,读取速度极快。

KV 的特点

全球分布:数据自动复制到全球边缘节点。

读取极快:毫秒级读取延迟。

最终一致性:写入后可能需要几秒才能在全球生效。

适合读多写少:读取免费,写入有费用。

免费额度

资源免费额度
存储空间1GB
读取操作10 万次/天
写入操作1000 次/天
列出操作1000 次/天

适用场景

  • 配置中心
  • 功能开关(Feature Flag)
  • A/B 测试
  • 缓存
  • 白名单/黑名单
  • 会话存储

快速开始

创建命名空间

npx wrangler kv:namespace create MY_KV

输出会显示命名空间 ID,保存用于配置。

配置绑定

wrangler.toml 中添加:

[[kv_namespaces]]
binding = "MY_KV"
id = "your-namespace-id"

基本操作

写入数据

// 简单写入
await env.MY_KV.put('key', 'value');

// 写入 JSON
await env.MY_KV.put('user:1', JSON.stringify({
name: 'John',
email: '[email protected]'
}));

// 设置过期时间(秒)
await env.MY_KV.put('session:abc', 'data', { expirationTtl: 3600 });

// 设置过期时间戳
await env.MY_KV.put('key', 'value', { expiration: Date.now() / 1000 + 3600 });

// 写入元数据
await env.MY_KV.put('file:1', fileContent, {
metadata: { filename: 'image.jpg', type: 'image/jpeg' }
});

读取数据

// 简单读取
const value = await env.MY_KV.get('key');

// 读取 JSON
const user = await env.MY_KV.get('user:1', 'json');

// 读取为 ArrayBuffer
const buffer = await env.MY_KV.get('file:1', 'arrayBuffer');

// 读取为 ReadableStream
const stream = await env.MY_KV.get('file:1', 'stream');

// 读取带元数据
const { value, metadata } = await env.MY_KV.getWithMetadata('file:1');

删除数据

await env.MY_KV.delete('key');

检查键是否存在

const value = await env.MY_KV.get('key');
if (value === null) {
// 键不存在
}

列出键

基本列出

const result = await env.MY_KV.list();
console.log(result.keys); // 键列表
console.log(result.list_complete); // 是否完整
console.log(result.cursor); // 分页游标

前缀过滤

const result = await env.MY_KV.list({ prefix: 'user:' });

分页

let cursor = null;
let allKeys = [];

do {
const result = await env.MY_KV.list({ cursor, limit: 100 });
allKeys = allKeys.concat(result.keys);
cursor = result.list_complete ? null : result.cursor;
} while (cursor);

批量操作

批量写入

await env.MY_KV.put([
{ key: 'key1', value: 'value1' },
{ key: 'key2', value: 'value2' },
{ key: 'key3', value: 'value3' },
]);

实战示例

配置中心

export default {
async fetch(request, env, ctx) {
const url = new URL(request.url);
const configKey = url.searchParams.get('key');

if (request.method === 'GET') {
const config = await env.MY_KV.get(`config:${configKey}`, 'json');
return Response.json(config || {});
}

if (request.method === 'POST') {
const body = await request.json();
await env.MY_KV.put(`config:${configKey}`, JSON.stringify(body));
return Response.json({ success: true });
}

return new Response('Method Not Allowed', { status: 405 });
},
};

功能开关

export default {
async fetch(request, env, ctx) {
const features = await env.MY_KV.get('features', 'json') || {};

const featureName = 'new_ui';
const enabled = features[featureName] === true;

return Response.json({
feature: featureName,
enabled,
});
},
};

会话存储

export default {
async fetch(request, env, ctx) {
const sessionId = request.headers.get('X-Session-ID');

if (!sessionId) {
return new Response('Unauthorized', { status: 401 });
}

const session = await env.MY_KV.get(`session:${sessionId}`, 'json');

if (!session) {
return new Response('Session expired', { status: 401 });
}

// 刷新会话过期时间
await env.MY_KV.put(`session:${sessionId}`, JSON.stringify(session), {
expirationTtl: 3600 // 1 小时
});

return Response.json(session);
},
};

缓存层

export default {
async fetch(request, env, ctx) {
const url = new URL(request.url);
const cacheKey = `cache:${url.pathname}`;

// 尝试从 KV 获取缓存
const cached = await env.MY_KV.get(cacheKey, 'json');
if (cached) {
return Response.json(cached);
}

// 从源获取数据
const data = await fetchDataFromSource(url);

// 存入 KV,缓存 5 分钟
await env.MY_KV.put(cacheKey, JSON.stringify(data), {
expirationTtl: 300
});

return Response.json(data);
},
};

使用 CLI 管理

写入数据

npx wrangler kv:key put --binding=MY_KV "key" "value"

读取数据

npx wrangler kv:key get --binding=MY_KV "key"

删除数据

npx wrangler kv:key delete --binding=MY_KV "key"

列出键

npx wrangler kv:key list --binding=MY_KV

KV vs D1 vs R2

特性KVD1R2
数据模型键值对关系型对象存储
查询能力键查找SQL键查找
一致性最终一致强一致强一致
适合场景缓存、配置结构化数据文件存储
读取性能最快

最佳实践

键命名规范

使用有意义的键前缀:

user:1
user:2
session:abc123
config:theme
cache:api:users

处理大值

KV 单个值最大 25MB,但建议:

  • 大于 1MB 的数据使用 R2
  • 使用压缩减小体积

过期策略

合理设置过期时间:

  • 会话数据:1-24 小时
  • 缓存数据:几分钟到几小时
  • 配置数据:不设置过期

常见问题

写入后读取不到?

KV 是最终一致性的,写入后可能需要几秒才能在全球生效。

如何清空命名空间?

没有批量删除 API,需要逐个删除或删除整个命名空间重新创建。

KV 适合存储什么?

适合存储:

  • 配置数据
  • 缓存
  • 会话信息
  • 功能开关

不适合存储:

  • 大文件(用 R2)
  • 需要查询的结构化数据(用 D1)
  • 频繁更新的数据

参考链接

下一步

完成 KV 学习后,接下来学习 Tunnel,了解如何实现内网穿透。