从 MongoDB 到 PostgreSQL 的大迁移

 Infisical,一家做密钥管理的开源商业公司,主要对标的是 HashiCorp Vault

        Infisical 在过去一年里迅速发展,平台现在每天处理超过 5000 万个密钥,将应用程序配置和私密数据发送给需要的团队、CI/CD 流水线以及服务器 / 应用程序。

        随着使用量的持续增长,我们不得不不断升级我们的技术栈。最近,Infisical 进行了一次全面的数据库迁移,从 MongoDB 迁移到 PostgreSQL。这涉及到对此项计划的深思熟虑、采用新技术、创建新的数据库 schema、重构逻辑、重写查询语句,以及将数百万(如果不是数十亿)的数据库记录迁移到 PostgreSQL。这是一个复杂的过程,但无论如何都是必要且有利于平台改善的步骤。

一、为何抛弃 MongoDB

在能力和可用性方面,我们和客户经常遇到 MongoDB 带来的限制问题,比如缺乏对事务、清理、云托管产品中版本一致性的支持,更不同提与 schema-less 数据库设计结构相关联的问题了

挑战的详细解释:

  • 配置数据库事务困难:使用 MongoDB,设置事务并不简单,因为它需要在集群模式下运行 MongoDB,并有各种配置开销;这使得客户要运行一个简单的 Infisical POC 变得极其困难,因为它需要生产环境下的 MongoDB 设置。对于处理高度敏感数据且数据完整性必须保证的产品来说,这是无法接受的。
  • 缺少关系型特性:使用 MongoDB 后,我们失去了许多来自关系型世界的好功能,比如 CASCADE,当目标资源被删除时,可以删除其他表中所有被引用资源;这尤其令人痛苦,因为我们的数据非常依赖关系型。结果是,在我们旧代码库中采用了大量删除函数却从未能完全完成任务,并在 MongoDB 数据库中留下悬空资源。
  • 云提供商支持不足:在 MongoDB 将许可更改为 SSPL 后,许多云提供商选择提供较老版本的 MongoDB。结果是,我们发现很难确保 Infisical 的功能可用性,除非是运行最新稳定版 MongoDB 的客户。
  • 缺乏操作 MongoDB 的经验:由于更多人熟悉部署基于 SQL 的数据库,他们经常在扩展和正确配置 MongoDB 上遇到困难;这导致我们需要为客户提供的支持量不成比例地增加,特别是因为他们对 MongoDB 不熟悉。

为何钟情 PostgreSQL

在寻找新的数据库时,我们首先列出了对我们最重要的几个方面:管理便利性(即包括配置、部署和扩展),内置事务支持,以及关系型功能。在讨论过程中,我们还考虑了是否应该构建自己的集成存储或寻求外部存储解决方案

选项的意义:

  • 集成存储:我们可以将像 SQLite 这样的数据库系统直接打包到 Infisical 中,并采用水平复制策略来通过避免额外的网络跳转来减少延迟。在这个模型中,扩展系统意味着部署多个 Infisical 实例,并让它们通过某种共识算法(如 Raft)进行相互通信。虽然这看起来是一个极好的解决方案,因为客户不需要连接任何依赖项就能运行 Infisical,但执行此愿景所需的工具生态系统感觉还不够成熟,而且所需的工程努力也太强人所难了。
  • 外部存储:我们可以简单地用 PostgreSQL 或 MySQL 等其他数据库替换 MongoDB,并使用其内置的扩展功能。尽管这个解决方案并没有完全消除使用 Infisical 时需要外部依赖项带来的摩擦,但我们认为它已经通过不再是 MongoDB,而带来了显著的优点。当涉及到支持一个或多个数据库时,我们认为支持多个会错过每种解决方案各自独特的优点;同时也会增加我们的工程开销。

        经过慎重考虑,我们选择了 PostgreSQL。除了拥有活跃的社区、详尽的文档以及大量可用的解决方案和扩展外,我们最欣赏的是它开源的本质以及绝大多数云服务提供商都提供 PostgreSQL 的托管服务

ORM 新的替代

        在确定使用 PostgreSQL 后,我们需要弄清楚我们的应用程序将如何与数据库进行交互。一开始,我们希望找到一个可以与我们使用 Mongoose ORM 的 MongoDB 体验相媲美的东西。因此,我们开始根据成熟度、可视化和迁移支持以及适当的抽象级别来评估候选者;主要考虑了 Drizzle ORM、Prisma ORM、TypeORM 和 Knex.js(一种查询构建器)。

        Knex.js 还带有自己的 seeding 和 schema 迁移工具包,并拥有成熟的生态系统以及几乎可以回答任何可能查询问题的优秀文档。通过一些自定义 Zod 集成工作,我们设法使其达到对 TypeScript 支持满意度较高水平。

        在确定了数据库和 ORM 后,我们启动了一个流程,最终的工作量是重写数十个数据结构和应用程序中数百个查询。

Bytebase 和 Infisical 在部署形态上也有相似之处。因为要访问用户数据库,企业出于数据安全的原因,往往需要私有化部署。Bytebase 的一大优势就是部署简单。POC 时,运行一个 Go 的二进制文件,就能把前端,后端以及数据库一起跑起来(利用了 Go 1.16 引入的 embed 功能)。如果是生产部署,就也只需要外接一个 PostgreSQL 数据库就行了。

来源:

Infisical | Open Source Secret Management

上一篇:Scala第十六章节(泛型方法, 类, 特质的用法、泛型上下界、协变, 逆变, 非变的用法以及Scala列表去重排序案例)


下一篇:考研经验与科目学习建议-各科学习建议