跳至主要内容
Deno 2 终于来了 🎉️
了解更多

宣布 Deno KV

我们很高兴推出 Deno KV,这是一个强一致性的键值数据库,在全球 35 个区域 中进行复制,以实现低延迟读取。

Deno Deploy 旨在提供最简单、最快速的方式来部署和运行边缘的 JavaScript、TypeScript 和 Wasm。但是,以前在 Deno Deploy 上创建有状态应用程序需要连接到外部云数据库,这涉及额外的配置步骤、本地测试挑战,并且如果数据存储库没有在全球复制,可能会破坏使用边缘的好处。

随着今天的宣布,我们将一个全球集成的数据库带到 Deno,使您能够轻松开发功能齐全的应用程序,同时克服这些障碍。

在这篇文章中,我们将讨论 Deno KV 的关键方面

如果您有兴趣使用 Deno KV,请加入候补名单

注意:Deno KV 目前处于测试阶段,长期数据持久性不能保证。在将 Deno KV 用于生产应用程序时,请牢记这一点。

注意:Deno KV 目前处于公开测试阶段

在本地运行或托管

Deno KV 无缝集成到开源 Deno 运行时中,允许您在本地运行它或将其作为零配置的托管服务部署。

在本地运行时,Deno KV 由 SQLite 支持,为本地开发、测试或单区域生产系统提供轻量级且易于使用的解决方案。

当您将应用程序部署到 Deno Deploy 时,Deno KV 数据库将自动由 FoundationDB 支持。这种托管解决方案由 Deno 公司运营,确保高性能和可靠性,而无需您进行手动配置或维护。

简单但强大

Deno KV 是一个一流的原语,只公开少数几种方法,您可以使用这些方法来存储、检索、删除和枚举数据。Deno KV 专为 JavaScript 设计,可以存储任何 JavaScript 结构化可序列化值,例如对象、数组、BigInt、日期等等。

const kv = await Deno.openKv();

const key = ["users", crypto.randomUUID()];
const value = { name: "Alice", created: new Date() };
await kv.set(key, value);

const result = await kv.get(key);
console.log(result.value);
// { name: "Alice", created: 2023-05-01T09:24:07.620Z }

使用 kv.list() 操作列出与特定选择器匹配的所有键。在下面的示例中,选择了以特定前缀开头的所有键。

await kv.set(["users", "alice"], { birthday: "January 1, 1990" });
await kv.set(["users", "sam"], { birthday: "February 14, 1985" });
await kv.set(["users", "taylor"], { birthday: "December 25, 1970" });

// List out all entries with keys starting with `["users"]`
const iter = kv.list({ prefix: ["users"] });
for await (const entry of iter) {
  console.log(entry.key);
  console.log(entry.value);
}

列表操作以批次从存储库中检索数据,默认值为 500 个键。要实现分页,将 iter.cursor 属性传递回 kv.list() 的后续调用。

在文档中了解有关可用方法的更多信息.

原子事务

对于许多应用程序来说,可靠的数据库事务是必需的。这在 Deno KV 中是可能的,使用 kv.atomic() 创建跨多个键的强一致性事务,默认情况下这些事务是立即持久的

const kv = await Deno.openKv();
const change = 10;

const bob = await kv.get(["balance", "bob"]);
const liz = await kv.get(["balance", "liz"]);
if (bob.value < change) {
  throw "not enough balance";
}

const success = await kv.atomic()
  .check(bob, liz) // balances did not change
  .set(["balance", "bob"], bob.value - change)
  .set(["balance", "liz"], liz.value + change)
  .commit();

了解有关我们如何处理事务的更多信息。

一致性和性能

Deno KV 是一个强一致性数据库,提供外部一致性,包括

  • 可串行化:事务的最高隔离级别,确保并发事务执行的结果与这些事务的顺序执行等效。
  • 线性化:保证操作(如读写)看起来是瞬时发生的并且是实时发生的。一旦写入操作完成,所有后续的读取操作都会返回更新的值,确保强实时排序。

您可以使用 consistency: "eventual" 选项为单个读取操作放宽一致性约束

// Read with eventual consistency from the nearest region
await db.get(["my-key"], { consistency: "eventual" });

// Read with strong consistency from the primary region
await db.get(["my-key"], { consistency: "strong" });

此选项允许系统从全局副本和缓存中提供读取,以实现最小的延迟。

以下是测试版在我们最受欢迎的区域的平均延迟数据。预计公开测试版和 GA 版本将有所改进。

区域 延迟(最终一致性) 延迟(强一致性)
北弗吉尼亚(us-east4) 7 毫秒 7 毫秒
法兰克福(europe-west3) 7 毫秒 94 毫秒
荷兰(europe-west4) 13 毫秒 95 毫秒
加利福尼亚(us-west2) 72 毫秒 72 毫秒
香港(asia-east2) 42 毫秒 194 毫秒

用例和示例

Deno KV 是管理应用程序状态的通用解决方案,使其非常适合各种用例。以下是一些展示 Deno KV 潜力的应用程序示例

  • 实时协作:Deno KV 可以跨多个客户端存储和同步数据,从而实现对任务的无缝协作,例如文档编辑或多人游戏。对于实时应用程序,Deno 的 BroadcastChannel 通常用于帮助同步状态。
  • 用户数据管理:使用 Deno KV 存储和管理用户生成的内容,例如博客文章和评论。通过使用全球复制的数据库,您可以确保快速访问,无论用户身在何处。
  • 身份验证:Deno KV 可以存储用户凭据、角色和权限,从而为您的应用程序提供安全高效的身份验证。

作为一个基本示例,探索 此游乐场,看看使用 Deno KV 创建全局一致的持久计数器是多么简单

import { serve } from "/[email protected]/http/server.ts";

const db = await Deno.openKv();

serve(async (req: Request) => {
  await db.atomic().sum(["views"], 1n).commit();
  const res = await db.get(["views"]);
  const views = res.value.value;
  return new Response(`Views: ${views}`);
});

以下是一些我们构建的更高级的演示应用程序,以说明 Deno KV 的功能

  • 多人井字棋 (源代码演示):一个简单的在线多人游戏。
  • Pixel-page (源代码演示):一个协作绘图应用程序,演示了实时同步和用户数据管理。
  • 共享待办事项列表 (源代码演示):一个任务管理应用程序,说明了 Deno KV 存储和管理用户生成数据的能力。
  • KV 草图本 (源代码演示):一个基于 Web 的草图本,突出了 Deno KV 存储和检索用户创建的草图的能力,展示了用户数据管理。

这些示例提供了一窥使用 Deno KV 可以实现什么。凭借其简单性、可扩展性和全局复制,Deno KV 是开发人员想要轻松构建有状态应用程序的强大工具。

下一步

我们的目标是使 Deno Deploy 成为部署和运行 API 服务器、Web 应用程序和边缘功能的首选平台。提供全球复制的持久数据存储是朝着这一目标迈出的重要一步。在接下来的几个月里,我们将引入功能以进一步简化构建和部署应用程序的过程,只需几行代码。

在测试阶段,用户可以免费享受高达 1 GB 的存储空间。我们很快将公布定价详情。

其他资源

如果您有兴趣使用 Deno KV,请加入候补名单

不要错过任何更新 - 在 Twitter 上关注我们