2025年2月5日

Cloudflare、Unikernels 与裸金属:Prisma Postgres 查询的生命周期

Prisma Postgres 是市场上最具创新性的 PostgreSQL 数据库。在本文中,我们将深入探讨其技术栈,它实现了闪电般快速的查询、全局缓存、连接池等功能。

Cloudflare, Unikernels & Bare Metal: Life of a Prisma Postgres Query

回顾:什么是 Prisma Postgres?

如果您还没听说:Prisma Postgres 是第一个基于 unikernel 构建的数据库。如果您错过了,这里有一个100秒的快速摘要

基于下一代基础设施构建

Prisma Postgres 不仅仅是另一个 AWS 封装!其架构从基本原理出发精心设计,并构建在 unikernelUnikraft CloudCloudflare Workers 等下一代基础设施之上。

这些技术的结合提供了独特的优势和强大的功能集。

无冷启动、全局缓存、连接池及更多

开发人员将 Prisma Postgres 用作无服务器数据库时可获得以下优势:

  • 零冷启动:即时访问数据库,无延迟。
  • 慷慨的免费套餐:每月10万次操作,1GiB存储空间和10个数据库。
  • 全局缓存层:查询响应可轻松在边缘缓存。
  • 内置连接池:扩展您的应用,无需担心 TCP 连接。
  • 性能提示:AI 驱动的建议,助您加快查询速度。
  • 简单的按用量付费定价:基于操作和存储的成本可预测。

尝试 Prisma Postgres

Prisma Postgres 查询的生命周期

在简短回顾之后,让我们深入了解 Prisma Postgres 用于实现这些优势的技术栈。剧透:这是 Prisma Postgres 查询生命周期中涉及的所有组件的完整概述

Future architecture diagram of Prisma Postgres

在接下来的部分中,我们将仔细研究每个阶段,并解释幕后发生的事情。

阶段1:一切始于 Prisma ORM

Prisma ORM 是 Prisma Postgres 查询自然开始的地方。

在应用服务器上使用 Prisma Postgres 无需查询引擎

如果您过去使用过 Prisma ORM,您可能知道它使用一个用 Rust 实现的查询引擎(Query Engine),它作为二进制文件在您的应用服务器上运行。

请注意,虽然我们在此语境中仍在谈论用 Rust 编写的查询引擎,但它目前正在用 TypeScript 进行重写。点击此处了解更多 here

查询引擎的核心职责是:

  • 根据高级 ORM 查询(用 JS/TS 编写)生成高效的 SQL 查询
  • 管理数据库连接池

然而,使用 Prisma ORM 搭配 Prisma Postgres 的妙处在于,您无需在应用服务器上运行查询引擎。相反,您将使用一个不带查询引擎的超轻量级 Prisma ORM 版本。生成 SQL 查询和管理 TCP 连接的繁重工作被进一步下推到 Prisma Postgres 之上的连接池中。

将连接池托管在 Prisma Postgres 基础设施上的这种方法具有主要优势:将应用开发人员从管理连接池的任务中解放出来,让他们能够专注于自己的数据需求和查询。这在无服务器和边缘函数等短生命周期环境中也特别有用,因为在这些环境中反复重新创建连接池会导致主要的性能开销。

使用缓存策略定义 Prisma ORM 查询

出于本文的目的,我们使用以下 Prisma ORM 查询

此查询从数据库中获取所有已发布的文章,并额外指定了两个与 Prisma Postgres 缓存相关的参数

  • 存活时间 (ttl):决定缓存数据被认为是新鲜的时长。当您设置 TTL 值时,Prisma Postgres 将在此持续时间内提供缓存数据,而无需查询数据库。
  • 过期再验证 (swr):允许 Prisma Postgres 在后台获取新数据时提供陈旧的缓存数据。当您设置 SWR 值时,Prisma Postgres 将在该持续时间内继续提供缓存数据,即使已超出 TTL,同时从数据库更新缓存中的新数据。

在此示例中,数据将被视为新鲜 30 秒 (TTL)。之后,在接下来的 60 秒 (SWR) 内,Prisma Postgres 的缓存将提供陈旧数据,同时在后台获取新鲜数据。

Prisma Postgres 从靠近您应用的边缘位置提供缓存数据。如果您将应用部署到多个位置,这个全局缓存可以显著提高您应用的性能!

通过 HTTP 执行查询

那么,当上述查询在应用中执行时,接下来会发生什么?由于查询引擎已被下推到技术栈的更深层,在此阶段发生的一切都只是一个 HTTP 请求,发送到 Prisma Postgres 基础设施的第一个认证和路由层。此 HTTP 请求承载着查询的轻量级 JSON 表示。它看起来像这样

请注意,selection 参数指定了应从数据库中获取的字段。由于我们未在查询中使用 selectinclude 选项,因此其值简单地为 "$scalars": true,这意味着目标模型的所有标量字段都将从数据库返回。

请求的下一步将由 Prisma Postgres 的认证和缓存层进行评估。

阶段2:认证请求

在命中缓存以检查查询结果是否可以从那里提供之前,查询需要进行认证。Prisma Postgres URL 始终包含一个编码用户凭据的 apiKey 参数

认证层使用 Cloudflare Workers 实现,因此与查询的来源物理距离很近。它使用 apiKey 值来识别用户、验证访问权限并将请求路由到下一阶段。

阶段3:缓存与否

认证后,HTTP 请求将到达 Prisma Postgres 基础设施的下一层,该层也通过 Cloudflare Workers 实现

Blog image

此路由层的主要目的是确定是否需要激活 Prisma Postgres 缓存

  • 如果查询设置了 swr 和/或 ttl 选项,查询将进入 Prisma Postgres 缓存路径。
  • 如果查询没有这些缓存选项中的任何一个,它将直接进入下一阶段。

那么,让我们来探究通过 Prisma Postgres 缓存层的路径。

Prisma Postgres 缓存基于 Cloudflare Workers 构建,充分利用了官方的 Cloudflare Cache API

作为缓存键,它使用基于整个 Prisma ORM 查询(包括查询参数的值,例如上述情况中的 published: true)计算出的哈希值。这种方法倾向于缓存未命中,并且仅在100%确定该精确查询已发送到数据库并且其结果之前已被缓存时,才从缓存返回数据。

您可以在 Prisma Postgres 控制台中查看缓存行为的统计数据

Blog image

现在我们假设我们之前的查询继续向下传输到 Prisma Postgres 技术栈,并且未由缓存提供服务。接下来会发生什么?

阶段4:命中连接池

如果查询结果尚未被缓存,之前的 HTTP 请求将转发到下一站:Prisma Postgres 的连接池(它部署在与数据库实例物理距离很近的虚拟机上)。

在我们最近的文章中了解更多关于连接池的重要性:《通过连接池挽救黑色星期五》

请注意,这实际上是请求可能传播更长距离的第一次(也是唯一一次),因为它现在离开了 Cloudflare 区域的地理范围。

这些虚拟机托管着从应用服务器中移出的查询引擎(如阶段1所述)。因此,在此阶段,Prisma Postgres 的连接池不仅会找到一个空闲连接来实际执行查询,还会生成将发送到 Prisma Postgres 的 SQL 语句。这现在通过与数据库建立的“老式” TCP 连接完成。

阶段5:进入 unikernel 数据库

Prisma Postgres 基于 unikernel (可理解为“超专业操作系统”)运行,它们作为超轻量级微虚拟机运行在我们自己的裸金属服务器上。

查看《抢先体验公告》了解该架构的详细信息、我们与 Unikraft 的合作,以及实现 Prisma Postgres 性能优势的毫秒级云栈。

以下是 Unikraft Cloud 的 核心组件的概述,这些组件实现了 Prisma Postgres 实例的闪电般启动速度

Blog image

这些组件协同工作方式如下:

  • 定制控制器和代理:一个定制的平台控制器,提供一流的、响应式的、毫秒级语义和可伸缩性。为了加快网络处理速度,Unikraft Cloud 将此控制器与一个定制代理耦合,该代理负责负载均衡并能够非常快速地响应传入请求。此代理是 Prisma Postgres 与连接池的 TCP 连接被管理的地方。
  • 基于 Firecracker 和 unikernel 的快速虚拟机监视器 (VMM):Unikraft Cloud 的 unikernel 使用仅包含 Prisma Postgres 的精简镜像——别无他物。与 Firecracker VMM 的修改版本搭配使用,这些 Prisma Postgres 镜像启动速度极快。
  • 快照:Unikraft Cloud 在将 Prisma Postgres 实例缩容到零之前,会对其进行内存快照。当它们被唤醒时,它们会从快照恢复,这意味着虚拟机已经“预热”并且甚至包含已经活跃的 TCP 连接!

得益于这种高效的技术栈,数据库实例仅在您实际使用时才会产生费用。这使我们能够提供慷慨的免费套餐,您可以根据需要启动任意数量的免费 Prisma Postgres 实例(与其他提供商不同,在其他提供商处,如果您创建多个数据库实例,通常需要支付固定的月费用)。

回到我们的查询:在查询的初始 JSON 表示转换为高效的 SQL 语句后,查询最终通过 TCP 到达数据库层。PostgreSQL 实例使用 Unikraft 的毫秒级云栈部署在我们自己的裸金属服务器上,与连接池距离很近。

这里的第一站是 Unikraft 代理,它负责维护与连接池的 TCP 连接。

代理现在与 Unikraft 控制器通信,该控制器负责管理实际的 Prisma Postgres 实例。此时,有两种可能的状态:

  • 目标 Prisma Postgres 实例已在运行;在这种情况下,代理将直接继续转发查询到它。
  • Prisma Postgres 实例当前处于“暂停”状态;在这种情况下,代理将联系 Unikraft 控制器,后者负责识别目标 Prisma Postgres 实例,“唤醒”它并告知代理当前实例状态。

不要被这里的“暂停”和“唤醒”术语混淆。得益于超快速的虚拟机快照(发生在内存中)和 unikernel 的轻量级特性,每个实例都可以在几毫秒内再次唤醒(这就是 Prisma Postgres 实例不受冷启动影响的秘密)。

Prisma Postgres 架构的下一步是什么?

尽管我们已经看到当前技术栈及其为开发人员带来的诸多优势引起了广泛的兴奋,但我们不会止步于此!

我们认为 Prisma Postgres 未来的迭代中可能进行一些额外的优化,最值得注意的是:我们将把连接池移动到运行 Prisma Postgres 实例的同一台机器上

Prisma Postgres components

TCP 连接是整个技术栈中最昂贵的部分,因为每次建立连接都需要进行三次握手。通过将这种 TCP 连接减少为同一台机器上两个进程之间发生的本地连接,连接池和数据库实例之间的物理距离所造成的延迟将变得完全可以忽略不计。

这是 Prisma Postgres 相较于其他基于 AWS(或其他云提供商)基础设施的提供商的核心优势:在使用云提供商时,无法保证连接池和数据库实例运行在同一主机上,但始终会存在网络跳跃。

总结

在本文中,我们深入探讨了 Prisma Postgres 及其所构建的下一代技术栈。

如果您已经在使用 Prisma ORM,可以尝试通过 导入现有数据库中的数据来体验 Prisma Postgres。否则,请在您的终端中运行此命令,从头开始试用 Prisma Postgres

不要错过下一篇文章!

订阅 Prisma 新闻通讯

© . All rights reserved.