跳至主要内容
Deno KV is in open beta

Deno KV 现已开放 Beta 测试

Deno KV 是向您的应用程序添加强一致性数据库的最快、最简单的方式。它内置于运行时环境中,因此您可以跳过配置,直接投入编码

const kv = await Deno.openKv();
只需一行代码即可添加状态 — 无需配置数据库或复制/粘贴环境变量。

今天,我们激动地宣布 Deno Deploy 上的 Deno KV 现已开放 Beta 测试。不再需要等待列表,只需注册 Deno Deploy 即可访问 Deno KV。对于已经使用 Deno Deploy 的用户,您的项目已自动更新为具有 KV 访问权限。

您还可以观看我们 2 分钟的视频公告,其中总结了这篇文章。

除了我们的公告之外,以下是关于 Deno Deploy 上的 Deno KV 的其他一些激动人心的更新

从 Deno Deploy 外部连接到 KV

为了更轻松地探索、导入、迁移和更新 Deno Deploy 上的 KV 数据,您现在可以直接从命令行连接到您的 KV 实例。只需将 Deno Deploy 个人访问令牌 设置为本地环境变量 DENO_KV_ACCESS_TOKEN,并将您的数据库 URL 传递给 Deno.openKv()

const kv = await Deno.openKv(
  "https://api.deno.com/databases/<database-id>/connect",
);

您可以在 Deno Deploy 项目页面上找到您的数据库 ID、URL 以及有关如何连接到托管 KV 数据库的更多信息

Connecting to your Deno KV locally

现在,将数据导入生产环境、处理数据迁移、手动检查/修改/探索数据以及在具有全局 Deno KV 用于存储的不同平台上托管 Deno 应用程序将变得更加容易

// This script updates the format of the `createdAt` field of all entries under the prefix
// `["items"]` from UNIX millisecond timestamps to ISO date strings.
import { Semaphore } from "https://deno.land/x/[email protected]/semaphore.ts";

const kv = await Deno.openKv(
  "https://api.deno.com/databases/<database-id>/connect",
);
const concurrencyLimit = 20;
const sem = new Semaphore(concurrencyLimit);

for await (
  const { key, value, versionstamp } of kv.list<any>({ prefix: ["items"] })
) {
  if (typeof value?.createdAt === "number") {
    value.createdAt = new Date(value.createdAt).toISOString();
    const release = await sem.acquire();
    (async () => {
      await kv.atomic().check({ key, versionstamp }).set(key, value).commit();
      release();
    })();
  }
}

for (let i = 0; i < concurrencyLimit; i++) {
  await sem.acquire();
}

console.log("Migration completed!");

了解更多关于从命令行连接到您的全局 Deno KV 的信息 →

想要在 Deno Deploy 上使用 Deno KV,但应用程序托管在 Fly.io 上?这是一个关于如何使用 Deno KV connect 执行此操作的快速指南

定价

我们很高兴宣布透明的 Deno KV 定价,该定价可根据您的需求进行扩展。Deno KV 的计费维度包括三个方面:存储、读取单元和写入单元。

存储是您在一个月中存储在 Deno KV 数据库中的数据量,以千兆字节为单位。读取和写入单元是您从 Deno KV 数据库读取和写入数据的次数,分别以 4 KiB 读取单元和 1 KiB 写入单元为单位进行计量。如果您执行 3 次每次 1 KiB 的读取事务,您将被收取 3 个读取单元的费用。如果您执行 1 次 4 KiB 的写入事务,您将被收取 4 个写入单元的费用。

写入单元的使用量还会乘以您为数据库启用的区域数量。如果您启用了主区域和两个读取副本,则对于每 1 KiB 的写入,您将被收取 3 个写入单元的费用。

对于每位用户,Deno Deploy 的免费套餐包括 1 GiB 存储空间,每天 15k 读取单元和每天 10k 写入单元。每日使用量在 UTC 时间 00:00 重置。

对于那些使用 Deno KV 和 Deno Deploy 进行扩展的用户,我们的 Pro 套餐提供

  • 每月 5 GiB 的存储空间,超出部分每 GiB 收费 0.75 美元
  • 每天 45k 读取单元,超出部分每百万次读取收费 1 美元
  • 每天 30k 写入单元,超出部分每百万次写入收费 2.5 美元

这是完整的定价表,其中包含更多详细信息

免费 专业版 自定义
KV 存储 1 GB 5GB(超出部分 $0.50/GB) 自定义
KV 读取单元/天 (4kb) 15,000 45,000 (超出部分 $1/M) 自定义
KV 写入单元/天 (1kb) 10,000 30,000 (超出部分 $2.50/M) 自定义
数据库区域数量 1 自定义 自定义
选择您的写入区域
每月最大使用量 免费 $250 N/A
您的应用程序或业务是否具有独特的扩展或全球数据存储需求? 我们很乐意了解更多信息

提醒一下,在本地使用 Deno KV 而不使用 Deno Deploy 是免费的。

了解更多关于我们的 Deno Deploy 和 Deno KV 定价计划的信息 →

更多读取区域以降低延迟

默认情况下,每个 Deno KV 数据库都带有一个写入区域和一个读取区域。如果您的用户遍布世界各地,则有些人可能会因单个读取区域而遇到较长的延迟。

现在,您可以启用更多读取区域以在全球范围内扩展您的数据库,从而获得更低的延迟

Screenshot of selecting read regions

通过单击启用多个读取区域,在全球范围内扩展您的数据库。

更强大的原子操作

原子操作是 Deno KV 的一项强大功能,允许您在单个事务中执行多个操作。如果任何操作失败,则整个事务将回滚,从而确保您的数据始终保持一致。

以前,您在单个事务中最多只能执行 10 个 mutation 操作。许多用户告诉我们,此限制太低,尤其是在处理需要许多辅助索引的复杂数据时。

我们听取了您的意见!每个原子操作的 mutation 限制已增加到 1000 个,或者总原子操作大小为 800 KiB,以先达到者为准。

OAuth 变得简单

用户身份验证是任何现代 Web 应用程序的基本要求。为了尽可能简化在 Deno Deploy 项目中实施身份验证,我们构建了 Deno KV OAuth,这是一个高级 OAuth 2.0 包装器,以 Deno KV 为后端,并预配置了大量常见的 OAuth 2.0 提供商,例如 GitHub、Google、Facebook、Slack、Discord 等。

您可以使用 新的插件 将 OAuth 功能添加到您的 Fresh 项目中

// main.ts
import { start } from "$fresh/server.ts";
import { createGitHubOAuth2Client } from "https://deno.land/x/deno_kv_oauth/mod.ts";
import { kvOAuthPlugin } from "https://deno.land/x/deno_kv_oauth/fresh.ts";
import manifest from "./fresh.gen.ts";

await start(manifest, {
  plugins: [
    kvOAuthPlugin(createGitHubOAuth2Client()),
  ],
});

或者,如果使用其他框架,则可以使用 Web API

// Sign-in, callback and sign-out handlers
import {
  createGitHubOAuth2Client,
  handleCallback,
  signIn,
  signOut,
} from "https://deno.land/x/deno_kv_oauth/mod.ts";

const oauth2Client = createGitHubOAuth2Client();

async function handleSignIn(request: Request) {
  return await signIn(request, oauth2Client);
}

async function handleOAuth2Callback(request: Request) {
  return await handleCallback(request, oauth2Client);
}

async function handleSignOut(request: Request) {
  return await signOut(request);
}
这个高级包装器提供了许多辅助函数,可以轻松地向您的应用程序添加身份验证、登录等功能。

已有项目正在使用 Deno KV OAuth 进行身份验证,例如 SaaSKitKV Sketchbook更多

即将推出

我们收到了您的反馈,并正在努力添加有用的功能,使 Deno Deploy 上的 Deno KV 成为向您的全球托管项目添加状态的最简单、最快的方式。

这是一个即将推出的功能预览的不完整列表。

带有 expireIn 的 Key TTL

Key time-to-live 过期是 Redis 中的一项重要功能,它允许您轻松管理用户会话或创建自己的缓存系统。很快,您可以使用 expireIn 选项在 Deno KV 中执行相同的操作,该选项接受毫秒为单位的数字

const db = await Deno.openKv();

await db.set(["a"], 1, { expireIn: 1000 });

密钥将在 expireIn 中指定的毫秒数过去后从数据库中删除。如果未指定 expireIn,则密钥将不会过期。

请注意,此功能 已在 Deno 运行时中提供

S3 备份

每个生产应用程序都需要数据备份,以防出现问题。很快,您将能够启用将 Deno KV 数据备份到您自己的 S3 存储桶的功能

Enabling S3 backups for your Deno KV data

备份是实时的,支持数据的点时间恢复。最初,您将能够将备份恢复到本地 Deno KV 数据库,随后将很快支持恢复到托管的 Deno KV 数据库。

主区域选择

Deno KV 使用单个主区域来处理写入,并使用多个读取区域来处理读取。当发送 write 事务时,它首先在主区域处理,然后复制到所有读取区域,从而在所有区域提供最终数据一致性。因此,您的 write 延迟受到您的用户与主区域距离的影响,而当使用 consistency: "eventual" 时,read 延迟受到您的用户与任何读取区域距离的影响。

很快,您将能够通过选择您的主区域来优化用户的延迟和性能

Selecting your primary region in Deno KV

由于并非每个应用程序或业务都有一种万能的配置,因此完全控制数据的存储和检索方式和位置对于优化用户的性能至关重要。

主区域切换生效时间不到 5 秒,并且不会导致应用程序停机。我们将在未来几周内向 Deno Deploy 用户推出此功能。

下一步是什么?

我们对 Deno Deploy 的愿景是使其成为托管 JavaScript 的最简单平台,通过内置的云原生基元(例如 Deno KV 和更多功能 — 敬请期待!)。当我们朝着 Deno KV 和 Deno Deploy 的正式发布版本努力时,我们将继续添加功能,以尽可能简化构建和托管生产就绪的 JavaScript 应用程序。

我们始终乐于接受反馈和功能请求!欢迎加入我们不断壮大的 Discord 社区在此处创建 issue

立即将项目部署到 Deno Deploy — 只需不到 5 分钟。