IT博文
MySQL 事务隔离级别详解
使用 docker compose 安装 tidb
架构师日记-如何写的一手好代码
生产事故-记一次特殊的OOM排查
Docker安装RabbitMQ——基于docker-compose工具
使用 docker-compose 部署单机 RabbitMQ
只需3步,即刻体验Oracle Database 23c
长达 1.7 万字的 explain 关键字指南!
Redis为什么能抗住10万并发?揭秘性能优越的背后原因
深度剖析Redis九种数据结构实现原理
【绩效季】遇到一个好领导有多重要,从被打差绩效到收获成长
为什么Redis不直接使用C语言的字符串?
Java阻塞队列中的异类,SynchronousQueue底层实现原理剖析
如何调整和优化 Go 程序的内存管理方式?
应用部署引起上游服务抖动问题分析及优化实践方案
Java 并发工具合集 JUC 大爆发!!!
卷起来!!这才是 MySQL 事务 & MVCC 的真相。
JDK8 到 JDK17 有哪些吸引人的新特性?
告别StringUtil:使用Java 11的全新String API优化你的代码
从JDK8飞升到JDK17,再到未来的JDK21
Java JMH Benchmark Tutorial
linux和macOS下top命令区别
Windows10关闭Hyper-V的三种方法
为什么应该选择 POSTGRES?
阿里云对象存储 OSS 限流超过阈值自动关闭【防破产,保平安】
Java高并发革命!JDK19新特性——虚拟线程(Virtual Threads)
“请不要在虚拟机中运行此程序”的解决方案
Spring中的循环依赖及解决
浅谈复杂业务系统的架构设计 | 京东云技术团队
面试题:聊聊TCP的粘包、拆包以及解决方案
操作日志记录实现方式
字节跳动技术团队-慢 SQL 分析与优化
Spring Boot 使用 AOP 防止重复提交
Controller层代码就该这么写,简洁又优雅!
SpringBoot 项目 + JWT 完成用户登录、注册、鉴权
重复提交不再是问题!SpringBoot自定义注解+AOP巧妙解决
SpringBoot 整合 ES 实现 CRUD 操作
SpringBoot 整合 ES 进行各种高级查询搜索
SpringBoot操作ES进行各种高级查询
SpringBoot整合ES查询
如何做架构设计? | 京东云技术团队
最值得推荐的五个VPN软件(便宜+好用+稳定),靠谱的V2ray梯子工具
我说MySQL每张表最好不超过2000万数据,面试官让我回去等通知?
vivo 自研鲁班分布式 ID 服务实践
使用自带zookeeper超简单安装kafka
推荐 6 个很牛的 IDEA 插件
喜马拉雅 Redis 与 Pika 缓存使用军规
「程序员转型技术管理」必修的 10 个能力提升方向
jdk17 下 netty 导致堆内存疯涨原因排查 | 京东云技术团队
如何优雅做好项目管理?
MySQL 到 TiDB:Hive Metastore 横向扩展之路
聊聊即将到来的 MySQL5.7 停服事件
Linux终端环境配置
微软 Edge 浏览器隐藏功能一览:多线程下载、IE 模式、阻止视频自动播放等
Hutool 中那些常用的工具类和实用方法
clash 内核删库?汇总目前常用的内核仓库和客户端
JDK11 升级 JDK17 最全实践干货来了 | 京东云技术团队
我是如何写一篇技术文的?
虚拟线程原理及性能分析
Java线程池实现原理及其在美团业务中的实践
Editplus和EmEditor配置一键编译java运行环境
用Spring Boot 3.2虚拟线程搭建静态文件服务器有多快?
SpringBoot中使用LocalDateTime踩坑记录 - 程序员偏安 - 博客园
程序员必备!10款实用便捷的Git可视化管理工具 - 追逐时光者 - 博客园
基于Netty开发轻量级RPC框架
开发Java应用时如何用好Log
复杂SQL治理实践 | 京东物流技术团队
火山引擎ByteHouse:分析型数据库如何设计并发控制?
多次崩了之后,阿里云终于改了
推荐程序员必知的四大神级学习网站
初探分布式链路追踪
新项目为什么决定用 JDK 17了
Java上进了,JDK21 要来了,并发编程再也不是噩梦了
mapstruct这么用,同事也开始模仿
再见RestTemplate,Spring 6.1新特性:RestClient 了解一下!
【MySQL】MySQL表设计的经验(建议收藏)
如何正确地理解应用架构并开发
解读工行专利CN112905176B
工商银行取得「基于 Spring Boot 的 web 系统后端实现方法及装置」专利
IDEA 2024.1:Spring支持增强、GitHub Action支持增强、更新HTTP Client等
TIOBE 2 月:Go 首次进入前十、“上古语言” COBOL 和 Fortran 排名飙升
Java 21 虚拟线程如何限流控制吞吐量
🎉 通用、灵活、高性能分布式 ID 生成器 | CosId 2.6.6 发布
20年编程,AI编程6个月,关于Copliot辅助编码工具,你想知道的都在这里
Java 8 内存管理原理解析及内存故障排查实践
消息队列选型之 Kafka vs RabbitMQ
从 MongoDB 到 PostgreSQL 的大迁移
腾讯云4月8日故障复盘及情况说明
PHP 在 2024 年还值得学习吗?
AMD集显安装显卡驱动之后出现黑屏,建议这样解决
使用 Docker 部署 moments 微信朋友圈 - 谱次· - 博客园
Java 17 是最常用的 Java LTS 版本
盘点Lombok的几个骚操作
Llama 3 + Ollama + Open WebUI打造本机强大GPT
如何优雅地编写缓存代码
Gmeek快速上手
笔记软件思源远程和本地接入大语言模型服务Ollama实现AI辅助写作(Windows篇)
Git Subtree:简单粗暴的多项目管理神器
这款轻量级规则引擎,真香!!
Ollama教程:本地LLM管理、WebUI对话、Python/Java客户端API应用
GLM-4-9B支持 Ollama 部署
智谱AI开源代码生成大模型第四代版本:CodeGeeX4-ALL-9B
美团二面:如何保证Redis与Mysql双写一致性?连续两个面试问到了!
免费开源好用,Obsidian和Omnivore真正实现一键联动剪藏文章,手把手教程!
得物 Redis 设计与实践
架构图怎么画?手把手教您,以生鲜电商为例剖析业务/应用/数据/技术架构图
使用Hutool要注意了!升级到6.0后你调用的所有方法都将报错 - 掘金
别再用雪花算法生成ID了!试试这个吧
无敌的Arthas!
Navicat Premium v16、v17 破解激活
🎉 分布式接口文档聚合,Solon 是怎么做的?
深入体验全新 Cursor AI IDE 后,说杀疯了真不为过!
Nacos 3.0 架构全景解读,AI 时代服务注册中心的演进
本文档使用 MrDoc 发布
-
+
从 MongoDB 到 PostgreSQL 的大迁移
[国产数据库圈,为啥那么多水货?” ](https://my.oschina.net/u/6852546/blog/11049760) 原文[链接](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Finfisical.com%2Fblog%2Fpostgresql-migration-technical),文章来自 Infisical,一家做密钥管理的开源商业公司,主要对标的是 HashiCorp Vault。  Infisical 在过去一年里迅速发展,平台现在每天处理超过 5000 万个密钥,将应用程序配置和私密数据发送给需要的团队、CI/CD 流水线以及服务器/应用程序。 随着使用量的持续增长,我们不得不不断升级我们的技术栈。最近,Infisical 进行了一次全面的数据库迁移,从MongoDB 迁移到 PostgreSQL。这涉及到对此项计划的深思熟虑、采用新技术、创建新的数据库 schema、重构逻辑、重写查询语句,以及将数百万(如果不是数十亿)的数据库记录迁移到 PostgreSQL。这是一个复杂的过程,但无论如何都是必要且有利于平台改善的步骤。 以下是我们决定从 MongoDB 转向 PostgreSQL,并说明了我们如何做到这一点背后所作出决策的故事。希望这篇文章能够引人入胜,并对那些可能某天会考虑进行类似数据库迁移操作的人有所帮助。 ## 我们从何开始? 当我们首次构建 Infisical 时,我们选择了团队最熟悉的技术栈来构建。作为这个技术栈的一部分,我们选择了 MongoDB + Mongoose ORM,因为这种组合带来的额外负担最小,并且允许我们快速地发布高质量的功能。正如 Tony Hoare 爵士所说, > 过早优化是万恶之源 当时确实没有进一步优化的需要。我们更专注于构建 Infisical Cloud,我们的托管 SaaS 服务。并且鉴于这个方向,我们并未预料到会有那么多用户自行托管 (self-host) 产品,因此我们并未针对该用例进行设计。 ## 为何抛弃 MongoDB? 虽然 MongoDB 在早期为 Infisical 提供了良好的服务,但当我们的产品场景不单单是托管服务时,它开始显示出不足之处。随着时间的推移,我们发现许多组织,特别是那些在合规和安全交叉点运营的组织,更喜欢自托管 Infisical 而非使用 Infisical Cloud;其他的有一些本地需求需要满足。 随着对自托管 Infisical 的需求增长,我们发现自己正在开发许多功能以减少学习如何自我托管 Infisical 所需的曲线,并且作为其中一部分,我们最终放弃了 MongoDB 转而支持 PostgreSQL。 实际上,在能力和可用性方面,我们和客户经常遇到 MongoDB 带来的限制问题,比如缺乏对事务、清理、云托管产品中版本一致性的支持,更不同提与 schema-less 数据库设计结构相关联的问题了。 以下是我对其中一些挑战的详细解释: - **配置数据库事务困难**:使用MongoDB,设置事务并不简单,因为它需要在集群模式下运行 MongoDB,并有各种配置开销;这使得客户要运行一个简单的 Infisical POC 变得极其困难,因为它需要生产环境下的 MongoDB 设置。对于处理高度敏感数据且数据完整性必须保证的产品来说,这是无法接受的。 - **缺少关系型特性**:使用 MongoDB 后,我们失去了许多来自关系型世界的好功能,比如 CASCADE,当目标资源被删除时,可以删除其他表中所有被引用资源;这尤其令人痛苦,因为我们的数据非常依赖关系型。结果是,在我们旧代码库中采用了大量删除函数却从未能完全完成任务,并在 MongoDB 数据库中留下悬空资源。 - **云提供商支持不足**:在 MongoDB 将许可更改为 SSPL 后,许多云提供商选择提供较老版本的 MongoDB。结果是,我们发现很难确保 Infisical 的功能可用性, 除非是运行最新稳定版 MongoDB 的客户。 - **缺乏操作 MongoDB 的经验**:由于更多人熟悉部署基于 SQL 的数据库, 他们经常在扩展和正确配置 MongoDB 上遇到困难;这导致我们需要为客户提供的支持量不成比例地增加,特别是因为他们对 MongoDB 不熟悉。 出于以上以及其他更多原因,我们意识到使 Infisical 能够被世界各地的团队和组织更广泛接受所需的最重要功能,其实是需要全面迁移至更加通用的数据库。 ## 为何钟情 PostgreSQL? 在寻找新的数据库时,我们首先列出了对我们最重要的几个方面:管理便利性(即包括配置、部署和扩展),内置事务支持,以及关系型功能。在讨论过程中,我们还考虑了是否应该构建自己的集成存储或寻求外部存储解决方案。 以下是每个选项的意义: - **集成存储**:我们可以将像 SQLite 这样的数据库系统直接打包到 Infisical 中,并采用水平复制策略来通过避免额外的网络跳转来减少延迟。在这个模型中,扩展系统意味着部署多个 Infisical 实例,并让它们通过某种共识算法(如Raft)进行相互通信。虽然这看起来是一个极好的解决方案,因为客户不需要连接任何依赖项就能运行Infisical,但执行此愿景所需的工具生态系统感觉还不够成熟,而且所需的工程努力也太强人所难了。 - **外部存储**:我们可以简单地用 PostgreSQL 或 MySQL 等其他数据库替换 MongoDB,并使用其内置的扩展功能。尽管这个解决方案并没有完全消除使用 Infisical 时需要外部依赖项带来的摩擦,但我们认为它已经通过不再是MongoDB,而带来了显著的优点。当涉及到支持一个或多个数据库时,我们认为支持多个会错过每种解决方案各自独特的优点;同时也会增加我们的工程开销。 经过慎重考虑,我们选择了 PostgreSQL。除了拥有活跃的社区、详尽的文档以及大量可用的解决方案和扩展外,我们最欣赏的是它开源的本质以及绝大多数云服务提供商都提供 PostgreSQL 的托管服务。 首先,这意味着 Infisical 的用户可以更容易地在任何云服务提供商上自行部署我们的平台,并将其与相应的托管 PostgreSQL 服务配对使用。此外,鉴于该数据库已被广泛采用,我们有信心用户在使用 Infisical 时操作起来会更加顺畅。 ## ORM 该怎么办? 在确定使用 PostgreSQL 后,我们需要弄清楚我们的应用程序将如何与数据库进行交互。一开始,我们希望找到一个可以与我们使用 Mongoose ORM 的 MongoDB 体验相媲美的东西。因此,我们开始根据成熟度、可视化和迁移支持以及适当的抽象级别来评估候选者;主要考虑了 Drizzle ORM、Prisma ORM、TypeORM 和 Knex.js(一种查询构建器)。 最后,我们决定使用 Knex.js,一个查询构建器,而不是 ORM 来更好地控制数据库。虽然承认,选择原始 SQL 将具有最多样化的功能和最少的抽象层次,但我们觉得这种方法可能会过于容易出错,并且坦率地说,在没有适当的 TypeScript 支持下维护起来非常麻烦。此外,除了接近裸露的 SQ L之外,Knex.js 还带有自己的 seeding 和 schema 迁移工具包,并拥有成熟的生态系统以及几乎可以回答任何可能查询问题的优秀文档。通过一些自定义 Zod 集成工作,我们设法使其达到对 TypeScript 支持满意度较高水平。 在确定了数据库和 ORM 后, 我们启动了一个流程, 最终的工作量是重写数十个数据结构和应用程序中数百个查询。 ## 我们是如何计划迁移的? 在代码重写的最后阶段,我们开始考虑如何进行迁移操作,将我们的 MongoDB 数据映射到 PostgreSQL,同时对Infisical云平台的干扰降至最低。 鉴于 Infisical 在客户基础设施中的关键作用,我们立即排除了有任何绝对停机时间的可能性。我们不得不做出妥协的部分是,在短暂的迁移窗口期间禁止写入操作(即客户无法创建或更新应用配置),以换取保证数据完整性。这种权衡似乎可以接受,因为客户主要从 Infisical 获取秘密信息。很少他们会每秒钟更新应用配置。 接下来,关于实际迁移操作,我们需要从 MongoDB 导出数据、仔细转换它,并将其重新插入到 PostgreSQL 中。当我们审计迁移序列时,面临着诸如确保各种树形结构从 NoSQL 正确地转化为它们关系型数据库等价物;这对于具有递归考虑因素的文件夹等数据结构特别敏感。我们还发现需要一种持久化方式来存储和映射 MongoDB 中与PostgreSQL 中相同标识符;如果只依赖内存处理,考虑到我们处理的数据量之大,这是行不通的。最后,我们选择使用 LevelDB 键值存储来协助标识符存储和查找操作。有了它,我们可以逐表地将数据移入 PostgreSQL 中。 ## 大迁移 最后,我们准备进行迁移。在此之前,那些没有直接参与代码库重写的人员已经花了一个季度来改进 Infisical 的其他方面,包括进行前端更改、打维护补丁、扩展客户端功能,并编写更好的文档。现在我们所有人都重新聚集起来为迁移本身做准备,即用新的替换应用程序代码库,并将数据从 MongoDB 转移到 PostgreSQL。 作为准备工作的一部分,我们制定了一份详细的迁移清单和预期时间表。 整体来看,计划大致如下: - 在迁移的几周前,我们会通过电子邮件和应用内横幅提前通知用户即将进行的数据库升级。我们将对平台上的每个功能流程进行彻底测试,并为迁移进行试运行。 - 迁移本身将在一个六小时的窗口期内发生,在此期间只允许对平台进行读取操作。在这个窗口期,我们会运行迁移脚本,把数据从 MongoDB 转移到 PostgreSQL,检查是否有数据丢失,并且如果成功就把 DNS 切换到新实例。当然,如果事情出现问题,我们已经备好了应急方案。 - 最后,在迁移之后,我们会解决任何残留问题,并开始推出 Infisical 和 PostgreSQL一起工作的新文档。 计划在手,我们开干了。 ## 结果 幸运的是,迁移执行过程非常顺利,没有数据丢失,只有少数非关键功能出现故障;我们在接下来的 36 小时内解决了这些问题,并将对客户的影响降到最低。 在迁移之后,我们观察到了许多好处: - 平台的性能大幅提升,主要归因于对连接查询的优化。使用MongoDB时,平台经常需要进行效率低下的聚合查询和多次网络跳转以实现所需功能。例如,由于我们核心数据的关系特性,我们经常需要执行许多 $lookup 操作来模拟 SQL 中的连接;这些操作效率低下,并且通常需要我们相应地扩展数据库和应用实例。迁移到PostgreSQL 后,我们避免了这些效率低下的操作,也使得数据库账单上的成本减少了50%。 - 现在的平台采用更好的数据验证方式,在数据库层面而不是应用层面进行根源处理。由于 MongoDB 设计上没有 schema 约束, 它依赖 Mongoose 框架定义数据类型、必填字段和验证规则。有了 PostgreSQL, 我们再也不会面临如果数据库被绕过 Mongoose 范围访问或修改时可能出现的数据不一致问题。 - 最后并且最重要的是, 我们认为 Infisical 现在更容易自我托管, 客户可以无需额外配置开销 (如处理 MongoDB 中启用事务功能所需的 replica sets) 就能进行 POC 测试. 总体来说, 考虑到手头目标、任务范围及其执行结果, 我们认为这项举措非常成功。一旦我们有更多数据,我们计划在未来发布更具体的结果。 总的来说,考虑到手头的目标、任务的范围以及最终执行情况,我们认为这次的迁移非常成功。一旦我们有了更多的数据,我们打算在未来发布更具体的结果。 ## 结论 从 MongoDB 迁移到 PostgreSQL 的决定一开始就不是件容易的事。总的来说,这个计划我们花了 3-4 个月时间去执行,期间进行了仔细的规划和讨论,包括我们为何需要执行此项任务、我们将如何去做;然后小心翼翼地执行所有步骤。对于任何阅读此文的人,我强烈建议在尝试这样大规模的工作之前深思其用例和实施方案。总体而言,我非常高兴一切都按计划进行,这将对 Infisical 用户产生巨大影响。 > 译者后记,Bytebase 和 Infisical 在部署形态上也有相似之处。因为要访问用户数据库,企业出于数据安全的原因,往往需要私有化部署。Bytebase 的一大优势就是部署简单。POC 时,运行一个 Go 的二进制文件,就能把前端,后端以及数据库一起跑起来(利用了 Go 1.16 引入的 embed 功能)。如果是生产部署,就也只需要外接一个 PostgreSQL 数据库就行了。 💡 更多资讯,请关注 Bytebase 公号:Bytebase
admin
2024年4月3日 21:57
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档(打印)
分享
链接
类型
密码
更新密码