暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

[译] Postgres 中的微服务

原创 王语嫣 2025-07-14
126

大型单片数据库曾经被认为是一件好事,它汇集了公司的所有数据。很久以前,我在 Digital Equipment 担任技术总监时,我们的业务目标是将所有数据整合到一个庞大的数据库实例中,以便我们能够掌控不同的业务,并清晰地了解当前的状况。我们梦想着在一个地方,我们可以看到哪些组件在哪里使用,哪些产品的利润更高,以及哪些业务部分可以评估和优化。

发生了什么变化?为什么我们现在认为单体架构是阻碍进步的“恐龙”,应该用新的微服务架构来取代它?

本文首先回顾了大型单体数据库的优缺点,然后深入探讨模块化数据库(微)服务。我们将回顾其优势与挑战,结合我们的咨询经验,描述一个实际问题,并概述其设计原则。最后,我们将讨论 Postgres 微服务的构建块。

我们为什么需要大型单片数据库?

我认识的每一家企业都在为统一的定义而苦苦挣扎,例如包含历史价格的统一价目表,或者单一事实来源,例如明确的客户及其购买记录。试图将所有数据迁移到一个具有引用完整性的庞大系统中非常诱人,而且一旦成功,回报将非常丰厚。

集中式方法还有其他运营优势,例如单一维护窗口、一套操作说明、单一供应商和单一变更管理流程。
然而,随着数据库规模的扩大,这种集中式方法开始显现其局限性,导致性能瓶颈和灵活性不足。

处理整体架构时的挑战

单体系统面临着巨大的挑战,许多架构师认为这些挑战大于其带来的好处。数据量不断增长,需要访问数据的用户和应用程序数量也在增长。这种趋势源于对提升用户体验和服务体验的需求,促使人们从根本上重新思考系统设计。

让我们从最重要的运营挑战开始:

  • 备份和恢复可能非常缓慢且繁琐,因为将数据缓存到磁盘并将副本移出站点需要大量时间。尝试恢复数据库时也是如此。业界已经开发了一些变通方法,例如数据库快照、增量备份和延迟副本——但这些变通方法增加了复杂性,而没有解决单个庞大恢复域的根本问题。
  • 升级需要花费大量时间,原因有二:(1)实际的软件升级过程可能需要大量时间;(2)测试所有使用单一事实点来解决功能性和非功能性问题的业务应用程序是一个漫长的过程,通常会冻结企业部署其他关键功能的数周或数月的时间。
  • 单一的单体数据库的扩展选项有限,因为 CPU、IO 和内存往往成为瓶颈。有一些方法可以缓解这个问题,例如 Oracle RAC 或 Postgres 多主复制,但它们需要专有基础架构(例如 Oracle RAC)或可扩展性潜力有限(例如 Postgres 多主复制)。NoSQL 供应商已经采用了新的一致性范式,例如最终一致性,但这种方法并不适用于许多必须支持 ACID 范式并需要即时一致性的事务系统。
  • 大型数据库往往变化无常,需要格外小心地维护。只有一小队“数据库大祭司”知道如何维护它们的正常运行。它们绝对是宠物——有时非常喜怒无常且难以管理——而不是牲畜。

创新也面临重大挑战:

  • 单体架构无法跟上收购、资产剥离和业务流程变化的步伐。将数据集成并整合到单一系统中耗时过长。
  • 当任何变更都可能影响公司所有职能时,变更管理流程就会变得极其复杂。例如,当竞争对手的新定价出现时,我们根本无法快速调整折扣模式以应对,因为要花数周甚至数月的时间才能了解其连锁反应。

几乎每家与我们合作过的公司都放弃了或计划放弃整体式方法——因为它太过繁琐和缓慢。

数据库微服务

将单体应用拆分成更小的数据库,使其能够相对独立地开发、管理和运维,是数据库微服务的目标。挑战在于如何在实现这一目标的同时,保持符合 ACID 的读写操作,实现高可用性,并避免读写放大(详见https://momjian.us/main/writings/pgsql/microservices.pdf )。

正如我们在与一位客户合作时所认识到的,将微服务理念推向极致并不总是明智之举。出于保密原因,我将他们描述为一家摩托车租赁公司。他们创建了包含独立微数据库的微服务,这些微数据库并未在数据库级别进行集成:

  1. 踏板车时间表:什么时候可以使用哪款踏板车?
  2. 踏板车维护:哪辆踏板车行驶了多少里程、需要哪些服务,以及何时安排维修?
  3. 滑板车位置:哪辆滑板车现在在哪里,以及它在一段时间内去过哪里?
  4. 踏板车模型:不同踏板车模型的特性是什么?

有效地回答简单的请求几乎变得不可能:“我可以在下午 2:00 在地点 X 租一辆 Model 5 踏板车吗?”,因为他们的应用程序必须:

  1. 询问数据服务 A(滑板车时间表)下午 2:00 是否有 Model 5 滑板车可用
  2. 与 B(踏板车维护)联系,移除那些今天需要维护的踏板车
  3. 通过询问 C(滑板车位置)检查位置 X 中是否有可用的滑板车。

由于数据服务未集成,他们不得不编写大量代码来在微服务应用程序中运行这三个查询、维护数据集、创建执行计划并查找可用设备。他们的项目失败了。

所有这些问题都可以通过在数据库 (A) 中创建一个单一视图来避免,该视图使用 FDW(外部数据包装器)对 (B) 和 © 执行单一查询。这样一来,摩托车库存查询的代码量就会非常小,性能也会非常出色,项目也更有可能成功。

在数据库单体架构中如何实现这一点显而易见。本文将探讨如何使用数据库微服务来实现这一点。

根据我们的经验,我们确定了使用 Postgres(或任何其他关系数据库)创建数据库微服务需要解决的四个关键问题。

  1. 实现有效的可扩展性
  2. 定义清晰的模块化 API,使团队能够快速行动
  3. 支持高效的跨服务数据共享
  4. 跨服务聚合信息

所有这些都同时保持 ACID 合规性!

实现有效的可扩展性
符合 ACID 标准的数据库在水平扩展方面表现不佳。Oracle RAC 等专有技术有助于实现可扩展性,但仅限于具有共享存储(可能存在单点故障)的专有平台,而且成本极其高昂。Postgres 中的双向复制功能有助于实现有限的可扩展性,但它主要侧重于高可用性、接近零停机维护和地理分布。最终一致性方法(例如 MongoDB 和其他 NoSQL 解决方案中使用的方法)虽然可扩展,但并不总是能满足事务型业务应用程序的需求。

在关系架构中,我们区分两种扩展方法:

  1. 模块化服务可分布在多台服务器上。例如,Scooter Schedule 服务在服务器 A 上运行,Scooter Maintenance 服务在服务器 B 上运行。
  2. 同一服务的多个副本并行工作。在我们的示例中,这意味着我们定义 Scooter Schedule 服务的多个实例,并将负载分配到这些实例上。

这两种方法都允许在服务器之间灵活地分配工作负载。在 Postgres 中,我们可以使用数据库服务器、数据库或模式作为模块化和扩展的构建块。

image.png

我们建议使用“数据库”作为模块化的基础,因为它允许我们使用“模式”在数据库级模块内部定义命名空间和 API(参见下一节)。这也意味着当模块迁移到其他服务器或专用服务器时,模块之间的通信协议(逻辑复制、FDW 和 DBLink)不会改变。

通过将每个数据域实现为独立的数据库,该域可以与其他域共置在同一台服务器上,也可以将其迁移到单独的服务器,以避免邻居干扰问题并实现独立扩展。逻辑复制提供了一种几乎零停机时间的方式,可以将数据库迁移到另一台服务器。

image.png

在上面提到的摩托车租赁示例中,我们可以从同一台服务器上的三个数据库开始。当调度流量增加时,我们会将“摩托车调度”服务迁移到专用实例。

image.png

当业务起飞时,我们为 Scooter Schedule 服务创建一个东海岸实例和一个西海岸实例。

image.png

使用数据库作为模块化和扩展的基础在容器化和虚拟化环境中也能很好地发挥作用,我们已经看到这种环境中越来越多地采用一个数据库/一个服务器架构。

定义模块化 API

关系数据库(例如 Postgres)提供了有限的方法来分离公共 API 与其内部实现。在https://momjian.us/main/writings/pgsql/microservices.pdf中,Bruce Momjian 概述了如何使用模式通过视图和函数提供公共 API,而视图和函数的实际实现以及表定义则发生在对公众不可见的私有模式中。

image.png

支持高效的跨服务数据共享

在上述示例中,我们客户的实施失败了,因为他们不允许数据服务跨域共享数据——所有数据集成和跨域查询都必须通过应用程序处理。这导致了巨大的复杂性,并导致了 Bruce Momjian 所说的“呼叫放大”。

Postgres 和其他数据库提供了强大的方法来允许数据库共享数据和请求。

我们区分了两种关键的架构模式:

  • 支持跨服务查询:“显示下午 2:00 在地点 X 可用的所有 Model 5 踏板车”
  • 分享参考数据,例如产品定义。例如:“踏板车 Model 5 配有篮子,后行李架最多可承载 20 磅的重量”。

跨服务请求

在 Postgres 中,跨数据服务的查询可以通过 FDW 处理,这使得定义和执行影响多个数据域的请求变得更容易。此类请求可以通过扩展某个服务的 API 来实现——例如,通过在 Scooter Schedule 服务中定义的视图来集成来自其他服务的数据;或者,创建一个单独的聚合器服务,专注于定义和执行跨多个数据域的请求。FDW 是 Postgres 对 SQL/MED 标准的实现。

FDW 看到了很多创新,并提供了一种定义模块化数据库的未来方法,其下推功能使其非常高效。

Postgres 还提供了 DBLink 技术,用于将请求转发到另一个数据库。虽然 DBLink 功能非常强大,但最近并没有引起太多关注。DBLink 允许一个数据库调用另一个数据库上的函数或存储过程,例如,Scooter Maintenance 服务可以调用 Scooter Schedule 服务中的 scooter_commit 函数来更新计划。通常,我们建议直接从应用程序调用此类更新事务,以避免“意大利面式集成”。

我们认为 FDW 是数据库服务器相互交互的主要方式,在微服务架构中,我们建议将这些交互限制为只读请求

共享参考数据

虽然可以使用 FDW 远程访问参考数据(例如 Scooter 模型定义),但这会产生大量的网络流量,并导致查询性能不佳。我们建议使用逻辑复制来共享此类参考数据,以便每个数据服务内的本地查询都可以直接访问参考数据。

image.png

跨服务聚合数据以进行分析

上述架构提供了定义模块化和可扩展服务的方法。最后一个挑战是如何聚合数据以实现单一事实来源。在我们上面的示例中,这将包括将东海岸和西海岸的班次汇总到一个集中式分析服务中。

Postgres 提供了两个选项:

我们可以实现一个物化视图,利用两个 FDW 将东海岸和西海岸服务器的数据拉入集中式分析服务。物化视图会聚合数据,并对其进行优化以方便分析。
我们可以使用逻辑复制来复制来自东海岸和西海岸服务的数据,然后使用视图或物化视图在本地聚合它。
我们推荐选项 (2),因为它更高效,并且可以提供几乎实时的当前数据视图。它对高延迟网络的容忍度也更高。选项 (1) 每次刷新物化视图时都会复制数据,这会给源系统和目标系统带来巨大的网络流量和开销。选项 (1) 仅复制更改的数据,效率更高。选项 (1) 可以与 pg_ivm 等自动更新物化视图的扩展程序结合使用。

整合所有

指南:

微服务通过 libpq(Postgres 的标准 API)连接到数据服务,可能由连接池介导。它们连接到每个数据服务公开的公共 API 模式。对于读取请求,我们使用视图(或物化视图)。创建/更新/删除请求通过公共模式中公开的函数或存储过程处理。这封装了实现细节,并支持敏捷开发。
每个数据域都通过单独的数据库进行处理,这允许独立的维护和部署计划,处理嘈杂邻居综合症,并允许独立扩展。
数据域可以复制(或分片),以扩展单个域,超越单个数据库服务器的限制,并使数据更接近用户
一个特殊的聚合服务处理跨多个域的查询。它使用 FDW 发出多数据库请求。
参考数据(例如模型定义或价格表)被复制到不同的域,以实现高效查询。这也使得维护引用完整性变得更加容易。
事实和参考数据被复制到集中式分析服务,以实现高效的跨域分析查询。

image.png

注意事项

逻辑复制是 Postgres 中一个强大的工具。然而,开发人员必须意识到它的局限性:

逻辑复制无法复制视图或物化视图中的数据,因此从领域服务到中央分析的发布将基于私有模式中的表。表、行和列可以被过滤掉,但发布定义会显示(并依赖)私有模式中定义的表。
逻辑复制目前无法重命名表。对于逻辑复制,表名是包含架构名称的完全限定表名。文档指出:

发布服务器和订阅服务器使用完全限定表名匹配表。不支持在订阅服务器上复制到不同名称的表( https://www.postgresql.org/docs/18/logical-replication-subscription.html )。

这意味着,为了将来自同一服务的多个实例的数据组合到一个分析服务中,源服务中的模式名称必须是唯一的。例如,在东海岸调度服务中,模式名称可以是 east_coast_schedule,而在西海岸调度服务中,模式名称可以是 west_coast_schedule。这两个模式名称都必须在分析服务的数据库中逐字定义。在分析服务中,分区表可以使用来自这些不同模式的表作为其分区,从而提供单一、统一的数据视图。此要求会影响本地 API 的实现,因为源数据库中的私有模式必须具有这些唯一的名称。

总结

Postgres 提供了一套强大的工具集,用于定义支持微服务架构的模块化数据库。通过将服务器、数据库和模式与 FDW 和逻辑复制相结合,我们可以实现可扩展、模块化且敏捷的数据管理解决方案,这些解决方案符合 ACID 标准,保持引用性,并且可以部署在任何地方。

原文地址:https://vibhorkumar.wordpress.com/2025/07/12/microservices-in-postgres/
原文作者:Vibhor Kumar and Marc Linster

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论