六维教程

EdgeOne Makers KV 存储

KV 存储是 EdgeOne Makers 提供的高性能键值存储服务,专门用来存配置、缓存、会话这类小体积高频访问的数据。全球边缘节点缓存,读取延迟极低,是后端开发最常用的存储之一。这篇讲清楚 KV 的概念、读写操作、数据管理最佳实践。

KV 存储概念与特点

KV 的全称是 Key-Value,就是一个超级大的 Map,通过键存取值。

"user:1"  ->  {"name": "Alice", "age": 20}
"config:theme"  ->  "dark"
"counter:visits"  ->  "1234"

它的核心特性:

特性 说明
全球分布 数据自动复制到全球所有边缘节点
读写极快 读取由就近节点直接响应,延迟几毫秒
最终一致性 写入后几秒内传播到全球
支持过期时间 键可以设置 TTL,到期自动删除
单值上限 最大 10MB

KV 最适合读多写少的场景。配置项、功能开关、用户资料缓存、静态内容,这些都是典型用途。

适用场景与注意点

KV 的最终一致性是新手最容易踩的坑。你在某个节点写入数据后,其他地区的节点可能要过几秒才能读到新值。所以它不适合需要强一致性的业务,比如库存扣减、计数器、订单状态。

适合 KV 不适合 KV
站点配置 计数累加
用户资料缓存 库存扣减
静态内容 交易记录
功能开关 需要立刻读到最新值的场景

创建命名空间

KV 的数据存放在”命名空间”里,每个命名空间是一个独立的数据集合。一个函数可以绑定多个命名空间。

在 EdgeOne Makers 控制台创建:

  1. 进入”存储” -> “KV”页面
  2. 点击”创建命名空间”
  3. 输入名称,比如 my_kv
  4. 确认创建

记下命名空间的 ID,后面绑定要用。

绑定到函数

在函数配置文件里添加 KV 绑定。以 Edge Functions 为例,在 edgeone.json 中配置:

{
  "name": "my-function",
  "bindings": {
    "kv": [
      {
        "name": "MY_KV",
        "namespace_id": "ns_abc123"
      }
    ]
  }
}

字段说明:

字段 作用
name 代码里访问 KV 的变量名,这里叫 MY_KV
namespace_id 刚创建的命名空间 ID

配置后,代码里就能通过 env.MY_KV 访问 KV 服务。

基础读写删操作

export default {
  async fetch(request, env) {
    // 写入一个键值对
    await env.MY_KV.put("user:1", JSON.stringify({ name: "Alice", age: 20 }));

    // 读取一个键值对
    const raw = await env.MY_KV.get("user:1");
    const user = raw ? JSON.parse(raw) : null;

    // 删除一个键值对
    await env.MY_KV.delete("user:1");

    return Response.json({ user });
  },
};

常用方法一览:

方法 说明
get(key) 读取值,不存在时返回 null
put(key, value) 写入或覆盖
delete(key) 删除
list(options) 按前缀等条件列出键

KV 的值只能是字符串。存对象时用 JSON.stringify 序列化,读取时用 JSON.parse 反序列化。

数据过期设置

写入时可以设置过期时间,让 KV 自动清理数据。

// 10 分钟(600 秒)后过期
await env.MY_KV.put("captcha:123", "abcd", { expirationTtl: 600 });

// 指定绝对过期时间戳(秒级)
await env.MY_KV.put("promo", "summer", { expiration: 1790000000 });

expirationTtl 的单位是秒,从写入时刻开始计算。注意 TTL 有最小值限制,具体看官方文档。

按前缀列出键

KV 支持按前缀列出所有键,方便批量管理。

// 列出所有以 "user:" 开头的键
const list = await env.MY_KV.list({ prefix: "user:" });

console.log(list.keys);
// [{ name: "user:1" }, { name: "user:2" }, ...]

常用选项:

选项 说明
prefix 按前缀过滤
limit 最多返回多少条
cursor 分页游标,从上次结果继续

数据管理最佳实践

键命名规范

建议用前缀加分隔符,例如 user:1config:theme,方便用 list({ prefix: "user:" }) 按类型管理。

好的命名 不好的命名
user:1001 u1001
config:site:theme theme
session:abc123 abc123

序列化策略

存对象时统一用 JSON 序列化,读取时反序列化。如果对象很大或结构复杂,考虑用 MessagePack 等二进制格式,体积更小。

缓存失效策略

对于缓存数据,设置合理的 TTL 避免脏数据长期存在。热点数据 TTL 短一些,冷数据 TTL 长一些。

批量操作

KV 没有原子的批量写入接口,需要批量操作时只能循环调用 put。如果要写入大量数据,考虑用 Cloud Functions 在后台处理,避免阻塞边缘请求。

一个完整的 CRUD 示例

把前面讲的组合起来,写一个用户管理的 KV 接口。

export default {
  async fetch(request, env) {
    const url = new URL(request.url);
    const parts = url.pathname.split("/").filter(Boolean);

    if (!(parts[0] === "api" && parts[1] === "users")) {
      return new Response("页面不存在", { status: 404 });
    }

    const id = parts[2];
    const method = request.method;

    // 读取单个用户
    if (method === "GET" && id) {
      const raw = await env.MY_KV.get(`user:${id}`);
      if (!raw) return Response.json({ error: "用户不存在" }, { status: 404 });
      return Response.json(JSON.parse(raw));
    }

    // 新增用户
    if (method === "POST") {
      const body = await request.json();
      const newId = String(Date.now());
      await env.MY_KV.put(`user:${newId}`, JSON.stringify(body));
      return Response.json({ id: newId, ...body }, { status: 201 });
    }

    // 删除用户
    if (method === "DELETE" && id) {
      await env.MY_KV.delete(`user:${id}`);
      return Response.json({ ok: true });
    }

    return Response.json({ error: "请求方式不支持" }, { status: 405 });
  },
};

速查卡片

要点 说明
KV 是什么 全球分布式键值存储,读多写少场景
核心特性 极快读取、最终一致性、单值最大 10MB
适合存什么 配置、缓存、功能开关、会话
不适合存什么 需要强一致性的计数、库存、交易
值类型 只能是字符串,对象需要 JSON 序列化
过期时间 支持 TTL 和绝对时间戳
键命名建议 用前缀加分隔符,如 user:1、config:theme
批量操作 没有原子批量接口,需要循环调用
上一篇
EdgeOne Makers 存储概览
下一篇
EdgeOne Makers Blob 存储