CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
Cloudflare 实战入门/课时/Workers KV
RawBlame
课时目录12 节

Cloudflare 实战入门

  1. 01边缘计算概览
  2. 02Wrangler 与本地开发
  3. 03Workers 核心
  4. 04Workers KV
  5. 05R2 对象存储
  6. 06D1 数据库
  7. 07Queues 消息队列
  8. 08Durable Objects
  9. 09Workers AI
  10. 10Stream 与媒体
  11. 11安全与防护
  12. 12运维与集成

Workers KV

KV 读写与缓存模式。

30 分钟

Workers KV

这一课你将能做到

  1. 创建 KV Namespace 并在 Worker 中完成读、写、列、删操作
  2. 根据业务场景选择正确的 KV 缓存模式(TTL、元数据、列表前缀)
  3. 理解 KV 的「最终一致性」语义,并能判断它和 Redis 的适用边界

为什么要学

你的 Next.js 前端需要一份「全站配置」来控制导航栏、Banner 文案、全局开关。如果每次请求都去读数据库,中心机房延迟 80ms,用户体验就崩了。如果放进 Redis,运维又要多维护一套集群。KV 就是专为这种「读多写少、边缘就近」的场景设计的。

人话:KV 是一个全球分布的键值存储。你写一次,Cloudflare 会自动把数据同步到全球所有边缘节点。下次用户在北京请求,直接从北京的节点读到值——不是去中心机房,不是去 Redis,而是从本地缓存读。

先建立图像

写入: [Worker] ── PUT ──> [KV 中心存储]
                              │
                     异步复制到全球节点
                              │
        ┌─────────────────────┼─────────────────────┐
        ▼                     ▼                     ▼
   [北京节点]             [纽约节点]            [伦敦节点]
        │                     │                     │
   读取: 5ms               读取: 8ms             读取: 6ms

这就是 KV 的核心特点:写入后最终一致,但读取极快。

跟着做

步骤 1:创建 Namespace

npx wrangler kv namespace create "MY_KV"

成功后你会得到一段 toml 配置,把它复制到 wrangler.toml:

[[kv_namespaces]]
binding = "MY_KV"
id = "0xxxxxxxxxxxxxxxxxxxxxxxxx"

步骤 2:在 Worker 中读写

export interface Env {
  MY_KV: KVNamespace;
}

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const url = new URL(request.url);
    const key = url.searchParams.get('key') ?? 'default';
    
    if (request.method === 'GET') {
      const value = await env.MY_KV.get(key);
      return value ? Response.json({ key, value }) : new Response('Not Found', { status: 404 });
    }
    
    if (request.method === 'PUT') {
      const body = await request.text();
      await env.MY_KV.put(key, body, { expirationTtl: 3600 }); // 1 小时 TTL
      return new Response('OK', { status: 201 });
    }
    
    if (request.method === 'DELETE') {
      await env.MY_KV.delete(key);
      return new Response('Deleted');
    }
    
    return new Response('Method Not Allowed', { status: 405 });
  },
} satisfies ExportedHandler<Env>;

步骤 3:带元数据的写入

await env.MY_KV.put(key, body, {
  expirationTtl: 86400,           // 24 小时后过期
  metadata: { updatedBy: 'admin', version: '2' },
});

步骤 4:列表(前缀扫描)

const list = await env.MY_KV.list({ prefix: 'config:' });
for (const key of list.keys) {
  const value = await env.MY_KV.get(key.name);
  console.log(key.name, value, key.metadata);
}

步骤 5:通过 CLI 操作 KV

# 写入
npx wrangler kv key put --binding=MY_KV "hello" "world"

# 读取
npx wrangler kv key get --binding=MY_KV "hello"

# 列出前缀为 config: 的键
npx wrangler kv key list --binding=MY_KV --prefix="config:"

# 批量删除
npx wrangler kv key delete --binding=MY_KV "hello"

讲清楚要点

  1. KV 不是 Redis:KV 不支持原子操作、事务、计数器递增、列表类型。它就是一个「带全球 CDN 的字符串键值存储」。
  2. 写入是最终一致:你刚写了一个 key,马上读可能读到旧值( propagation delay 通常在秒级)。如果你需要强一致,用 D1 或 Durable Objects。
  3. TTL 以秒为单位:支持 expiration(绝对时间戳)和 expirationTtl(相对秒数)。过期后 key 自动删除,不收费。
  4. value 最大 25MB:超过的话用 R2 存大文件,KV 里只存引用 URL 或元数据。
  5. 列表有分页:list() 默认返回 1000 条,有 cursor 分页机制。大规模扫描时要注意 API 限流。

你可能会懵的地方

  • 刚 PUT 的数据 GET 不到? 正常。KV 的写入是先写中心,再异步复制到全球节点。刚写完立刻读,可能打到还没同步的节点。需要强一致就用 D1。

  • KV 支持 JSON 吗? value 只能是字符串。存 JSON 时 JSON.stringify() 写入,JSON.parse() 读出。

  • 怎么统计某个前缀有多少 key? KV 没有 count API。只能 list() 遍历,但要注意分页。如果 key 很多,考虑用 D1 存计数器。

  • 免费额度够吗? 免费套餐:每天 100,000 次读取、1,000 次写入、1,000 次删除。个人项目通常够用,高并发写场景需要付费。

  • KV 和 Cache API 有什么区别? Cache API 是 HTTP 缓存,按 URL 存储 Response 对象,适合 HTTP 响应缓存。KV 是键值存储,适合配置、状态、小数据。两者可以配合使用。

错法对照

错法问题正解
把 KV 当 Redis 做 INCR 计数器KV 没有原子递增操作计数器用 D1 或 Durable Objects
写完后立刻读,期望强一致KV 是最终一致对一致性有要求的用 D1
value 直接存对象 put(key, obj)value 必须是字符串先 JSON.stringify(obj)
列表时不处理 cursor 分页超过 1000 条时丢数据while (list.cursor) { list = await kv.list({ cursor: list.cursor }) }
key 名没有命名空间前缀容易冲突,难以扫描用 user:123:profile 这类结构化 key

卡点急救

  1. env.MY_KV is undefined:检查 wrangler.toml 的 binding 名和代码里是否一致;检查 wrangler dev 是否重启(修改 toml 后要重启)。
  2. list() 返回空但 key 存在:确认 prefix 参数是否匹配;确认 list 的是同一个 namespace ID。
  3. 写入 413 Payload Too Large:单个 value 超过 25MB。拆分数据或改用 R2。

面试常问

  • KV 和 Redis 怎么选? KV 适合「全球边缘、读多写少、最终一致」的配置和缓存场景;Redis 适合「复杂数据结构、强一致、高并发写、Lua 脚本」的场景。如果应用需要原子计数、Pub/Sub、Sorted Set,用 Redis 或 Cloudflare Queues。

  • KV 的一致性模型是什么? 最终一致性(Eventual Consistency)。写入后会在秒级内传播到全球节点,但在此期间不同节点可能读到不同值。读取总是从最近的边缘节点进行。

  • KV 的计费模式? 按请求次数 + 存储量。读取比写入便宜得多(约 10:1),设计时尽量多读少写,批量写比多次单写更划算。

自测三问

  1. KV 的写入和读取延迟分别是多少?为什么写入后不能立刻读到?
  2. 如果要在 KV 里存一个 30MB 的 JSON 文件,应该怎么处理?
  3. KV 的 list() 有什么限制?怎么遍历超过 1000 条的数据?

小结一句话

Workers KV 是边缘场景的「最终一致」键值存储:全球就近读取极快,适合配置、缓存、小数据,但不适合强一致写和复杂数据结构。

延伸

  • Workers KV 官方文档
  • KV Pricing & Limits
  • 下一课:R2 对象存储,学习 S3 兼容的边缘存储与生命周期管理。
加载本节练习…
← 上一课Workers 核心下一课 →R2 对象存储