基于消息的集成相对于共享数据库的优势很难说清楚,但这里将尝试:
不可避免的争论是,DBA 想要对实体之间的所有关系进行建模,以便数据始终100% 一致。另一方面,您让开发人员警告 DBA 有关从单体架构中出现的紧耦合以及无法轻易更改绑定到主表的应用程序。
我认为这两个论点都有些肤浅,无论您如何进行集成,构建一个易于更改的系统都是具有挑战性的。我想提出另一种关于 SOA 和基于消息的集成的论点。
归根结底是这样的:
- 共享数据库集成通常由“大系统”的世界观驱动。
- 基于消息的集成通常由“小系统”世界观驱动。
您有多少次遇到具有数百名用户的大型系统,这些系统执行许多不同的工作,支持多种不同的业务功能?我经常遇到他们。目前看来,它们是企业软件的主要内容。
所有这些系统似乎都有一个共同点,那就是它们的更改成本非常高。正如 Joe R 在他的回答中所说,其中一个原因是紧耦合。
然而,耦合是一个负载术语,我认为我们需要考虑两种截然不同的耦合类型。
第一个可以被认为是技术耦合,这意味着技术堆栈内部的垂直耦合,通常是 n 层,在一层和另一层之间。
所以我们有一个应用程序的数据库和数据访问层之间的耦合,数据访问层和业务逻辑层之间的耦合等等。认为这种耦合是坏的或错误的似乎是普遍接受的,但理性思考应该不是我们期望的,甚至欢迎,比如 User DTO、UserRepository 类和 User 数据库表之间的高度耦合?
让我们考虑一下耦合在实现级别的实际含义。当“属于”一件事的概念泄漏到另一件事中时,就会发生耦合。当您有多个层基本上就同一业务实体相互交谈时,这种泄漏是不可避免的。
第二种耦合,也是我要讲的一种,可以认为是业务能力耦合,也称为水平耦合。这就是我们将属于一种业务能力的概念泄漏到另一种业务能力的地方。
我断言,使用数据库作为集成平台会鼓励这种水平耦合。
例如,想象一个支持电子商务网站系统的典型后端系统。您通常会将库存、订购、定价和 CRM 作为您的核心功能。
如果我们在单个数据库中对该域进行建模,我们实际上是将不同的功能耦合在一起。每个外键约束都可能增加这些能力之间的耦合程度。事实上,此时的系统已经可以被认为是跨共享数据库集成的几个不同的“服务”。
这是世界的“大系统”图景,通过使用庞大的 500 多个表数据库将企业的不同领域链接在一起,得到支持和鼓励。
将此与世界的“小系统”图进行对比,在我们的示例中,后端 Web 应用程序库存、订购、定价和 CRM 是完全独立的应用程序,具有自己的技术堆栈、自己的项目团队、自己的发布时间表,以及他们自己的数据库。
每个应用程序或服务都会对给定实体有自己的理解,并且根据它所支持的业务能力,这将符合该实体的定义。
这方面的一个例子是“用户”。CRM 对用户的定义将与订购或履行截然不同。订购只关心用户购买的是什么。CRM 关心客户购买模式等其他内容,而履行则关心姓名、地址等。这在共享数据库中使用单个用户表并不容易实现。
对我来说,这张图片比共享数据库路线更可取,主要原因是生成的系统将更好地模拟它应该支持的实际业务流程。DDD的主要原则之一是系统应该尽可能地类似于拥有它的企业。
在典型的业务中,这些不同的能力不是跨跨企业的大团队实现的,而是由小的垂直团队实现的,通常是完全自主的,他们之间以及与其他垂直团队经常通过发送请求、指令或通过让其他团队知道某个流程或任务已经开始/完成等。
好的,但是没有共享数据库,网站现在依赖来自所有这些不同服务的数据来构建它的 UI。它仍然需要在同一个屏幕上一起显示这些东西。网站“展示”层如何组装所有这些并将其呈现给 UI?
更重要的是,如果 CRM 想知道客户何时订购商品怎么办?如果订购想知道产品的价格何时发生变化,或者库存中的产品何时缺货怎么办?如果这些服务是完全独立的,那么它们如何交换数据?
首先解决 UI 问题,这可以通过复合 UI来完成。有很多技术可以做到这一点,但可以说这是一个相对知名的景观,并不是我们真正关注的重点。
这些服务如何通信的第二个问题是,它们交换消息。什么样的消息?事件。事件由一个系统发布,以便被对该事件感兴趣的任何其他系统使用。
在我们的电子商务示例中,事件类型可能是:
- 订单已下
- 客户升级为金牌
- 产品折扣
- 库存耗尽
这些事件具有商业意义。这意味着我们可以通过小系统方法获得额外的好处,即集成媒体本身具有业务意义,并且可以用业务语言表达,这很适合 Scrum 和敏捷方法。
因此,为了最终回答 OP 的问题,我认为从技术角度来看,共享数据库与消息集成方法之间没有太大区别。两种方法都需要相同的抽象和语义。但我确实认为它们背后的驱动力存在巨大差异,采用更多小系统思维方式的结果总体上提供了更好的商业价值。