2024 年 5 月 28 日

Prisma Pulse:数据库变更事件交付保障

Prisma Pulse 让您轻松构建事件驱动型应用程序,让您可以对数据库中的更改做出反应。 借助其新的事件持久化功能,现在保证所有数据库变更事件都将 至少一次按正确顺序 交付!

如果您想亲自试用 Prisma Pulse,直接跳转到示例项目实时聊天实时排行榜、一个发送 新用户入职邮件 的服务器,以及一个将数据同步到搜索索引的 无服务器 cron 作业

事件驱动型架构实现可扩展性和实时性

构建具有诸如 聊天通知实时协作投票测验 等实时功能的强大且可扩展的应用程序可能很复杂。轮询数据库以查找更改不仅资源密集型,而且在构建更高级的场景时也会变得非常复杂。

我们希望通过 Prisma Pulse 让您轻松地将数据库集成到事件驱动型架构中!

什么是事件驱动型架构?

事件驱动型架构有助于以 强大可扩展 的方式构建您的实时应用程序! 与轮询等其他方法相比,它们还可以节省资源。 轮询会消耗大量的数据库连接和 CPU,无论是在您的应用程序服务器还是数据库服务器上。

另一方面,在事件驱动型架构中,事件会在发生时立即传递给消费者。

在事件驱动型架构中,您通常至少有两个组件:

  • 事件生产者 负责 发布 事件并将事件传递给消费者。
  • 事件消费者 订阅 事件并在生产者发布事件后接收它们。

在上图中,数据库 是事件生产者,而 应用程序服务器 是事件消费者。

使用 Prisma Pulse 轻松地从数据库流式传输变更事件

Prisma Pulse 通过让您轻松地将数据库中发生的所有更改流式传输到应用程序中,从而实现事件驱动型架构。

Pulse 使用 变更数据捕获 (CDC) 来捕获数据库中发生的 写入 事件(意味着任何 创建更新删除 操作),方法是监控数据库的事务日志,例如 PostgreSQL 中的 预写日志

具有 至少一次 语义的交付保障 🎉

假设您正在构建一个健康监控应用程序,并且您使用事件驱动型架构在紧急情况下向用户发送通知。 在这些以及许多其他场景中,您的应用程序无法承受丢失任何事件的风险,因为这可能会对您的业务产生严重影响——甚至更糟糕的是,对人身健康产生严重影响!

注意: Prisma Pulse 需要启用 逻辑复制 的 PostreSQL 数据库(> v12)。 如果您希望看到对其他数据库的支持,请告知我们

什么是事件驱动型架构中的交付保障?

为了确保您的事件实际上到达消费者端,您需要了解事件驱动型架构的 交付语义。 交付语义定义了您的系统可以为事件交付提供的 保证

  • 最多一次:事件被交付一次或根本不交付。
  • 至少一次:事件被交付一次或多次,确保它永远不会未交付。
  • 恰好一次:事件被恰好交付一次,避免重复。

交付保障的另一个维度是事件到达消费者的 顺序。 一般来说,这有两种不同的选择:

  • 事件以与生产者发出事件的 相同顺序 交付。
  • 事件可能以与生产者发出事件的顺序相同或 不同顺序 交付。

Prisma Pulse 中的 至少一次相同顺序 交付

截至今天,Prisma Pulse 支持至少一次交付且顺序相同,因此可以保证您永远不会丢失任何数据库事件。

在底层,Pulse 现在能够 持久化数据库生成的事件,这实现了新的交付保障。

注意: 事件持久化在我们的所有计划中都可用,并且包含免费限额,让您可以试用 stream()。 访问定价页面以找到适合您的计划,并了解有关数据库事件、事件读取和事件存储成本的更多信息。

要将新的交付保障与 Prisma Pulse 一起使用,您需要:

  1. 在控制台中设置 Pulse 时,确保启用 事件持久化

  2. 使用 Pulse 扩展提供的新的 .stream() API

    stream() 方法返回一个 异步可迭代对象,该对象将为数据库中发生的每次写入操作接收一个事件。 您可以按如下方式使用它:

    每当 User 表发生更改时,console.log 语句都会运行。 以下是更新记录时将打印的示例终端输出:

注意: 之前的 .subscribe() API 仍然存在,但不与事件持久化兼容,因此不提供任何交付保障。 如果您今天正在使用 .subscribe(),但想要利用交付保障,则需要在 Platform 项目中重新启用 Prisma Pulse,更新 Pulse 的客户端扩展以使用最新版本,并调整您的代码以使用 .stream()

Prisma Pulse 中的 恰好一次 交付

虽然 Pulse 默认提供“至少一次”语义,但它也为您提供了 原语,让您可以自己实现“恰好一次”交付保障!

Prisma Pulse 生成的每个事件都携带一个标识符/幂等键(您可以通过 id 字段访问)。 此键可用于在事件的下游处理期间进行去重。 最好的实现方法是将 id 传递给支持 幂等性 的外部服务,或者在使用数据库时使用诸如 upsert 之类的概念。

永不丢失任何事件——即使您的服务器宕机

如果您使用新的 .stream() API,Pulse 保证所有数据库事件都将至少一次按正确顺序到达您的应用程序。

但是,如果您的服务器宕机了会发生什么? 您会丢失在此期间数据库中发生的事件吗?

您不必丢失:新的 .stream() API 使您可以通过为其提供 name 参数来“从上次中断的地方继续”。

每当您提供 name 时,Pulse 都会将 游标 与该特定流相关联,以跟踪哪些事件已到达消费者端。

如果您的服务器(在本场景中是消费者)宕机,则在此期间数据库中发生的任何事件都不会被消费者确认,并且游标不会移动。

一旦您的服务器恢复在线,流将再次启动并交付在此期间错过的所有事件。 流将从其断开的地方 恢复

如果您省略 name 选项,则您的流将不会“重播”服务器宕机期间丢失的任何事件。

Prisma Pulse 在无服务器环境中的应用

Prisma Pulse 的一个主要用例是构建 实时 应用程序。 如果您希望数据库事件实时交付到您的应用程序,您将需要一个 长时间运行的服务器,Prisma Client 在该服务器上调用 .stream() API。

但是,借助新的交付保障,Prisma Pulse 可以在 无服务器环境 中用于某些用例。 如果事件 何时 到达并不重要,重要的是它 最终 会到达(最终),那么具有交付保障的 Prisma Pulse 将满足您的需求。

假设您正在构建一个电子商务应用程序,并且需要将您的产品数据同步到辅助数据存储(例如搜索索引):您可以设置一个无服务器函数中的 cron 作业,该作业每小时运行一次,而不是使用不断运行(从而消耗您需要付费的资源)的长时间运行的服务器。 如果您将新的 .stream() API 与 name 参数一起使用,则在 cron 作业下次运行之前一小时内发生的所有事件都将被 Pulse“重播”。

查看用例和示例项目

为了让您轻松试用 Prisma Pulse,我们为您创建了几个 示例项目

实时排行榜

实时排行榜 示例演示了如何使用 Prisma Pulse 构建一个全栈应用程序,其中前端在数据库发生更改时实时更新。 它使用以下技术栈:

您可以按照以下步骤使用该示例:

  1. 运行以下命令:

  2. 按照 README 中的步骤操作。 请注意,您需要使用 支持 Pulse 的数据库 并在 Platform Console 中生成 Pulse API 密钥才能使其工作。

更多示例

查看 prisma-examples 仓库,了解有关 Prisma Pulse 的更多示例,例如:

试用并分享您的反馈 💚

我们对 Prisma Pulse 中的新交付保障感到非常兴奋! 它们不仅让您确信您永远不会丢失数据库中发生的任何事件,而且还支持全新的用例,例如在无服务器环境中使用 Pulse(因为事件可以在函数生成时随时“恢复”)。

试用一下,让我们知道您对 Prisma Pulse 的新功能有何看法。 如果您遇到困难或不确定从哪里开始,您可以随时在 XDiscord 上与我们联系。

不要错过下一篇文章!

注册 Prisma 新闻通讯