数据集成架构

数据集成架构 intelligentx

【事件处理】全面了解Kafka和RabbitMQ选型(1) -两种不同的消息传递方式

QQ群

视频号

微信

微信公众号

知识星球

Chinese, Simplified

超级架构师

架构师的宝库,每天一篇,开拓你的视野和深度。分享企业架构,业务架构,应用架构,数据架构,技术架构,安全架构等。讨论架构框架,规划,治理,标准,落地。交流新兴的架构风格和模型。如微服务,事件驱动,微前端,大数据,数仓,物联网,人工智能架构。

公众号

在这一部分中,我们将探讨RabbitMQ和Apache Kafka以及它们的消息传递方法。每种技术在设计的每个方面都做出了截然不同的决定,每种方面都有优点和缺点。我们不会在这一部分得出任何有力的结论,而是将其视为技术的入门,以便我们可以深入探讨该系列的后续部分。

RabbitMQ

RabbitMQ是一个分布式消息队列系统。分布式,因为它通常作为节点集群运行,其中队列分布在节点上,并可选择复制以实现容错和高可用性。它原生地实现了AMQP 0.9.1,并通过插件提供其他协议,如STOMP,MQTT和HTTP。

RabbitMQ同时采用经典和新颖方式。从某种意义上来说,它是面向消息队列的经典,并且具有高度灵活的路由功能。正是这种路由功能才是其杀手级功能。构建快速,可扩展,可靠的分布式消息传递系统本身就是一项成就,但消息路由功能使其在众多消息传递技术中脱颖而出。

交换机(exchanges)和队列

超简化概述:

  • 发布者向交换机(exchanges)发送消息

  • 将消息路由到队列和其他交换机(exchanges)

  • RabbitMQ在收到消息时向发布者发送确认

  • 消费者与RabbitMQ保持持久的TCP连接,并声明他们使用哪个队列

  • RabbitMQ将消息推送给消费者

  • 消费者发送成功/失败的确认

  • 成功使用后,消息将从队列中删除

隐藏在该列表中的是开发人员和管理员应该采取的大量决策,以获得他们想要的交付保证,性能特征等,我们将在本系列的后续部分中介绍所有这些决策。

我们来看看单个发布者,交换机(exchanges),队列和消费者:

Fig 1 - Single publisher and single consumer

如果您有多个同一消息的发布者怎么办?如果我们有多个消费者每个人都希望消费每条消息呢?

Fig 2 - Multiple publishers, multiple independent

如您所见,发布者将其消息发送到同一个交换机(exchanges),该交换机(exchanges)将每条消息路由到三个队列,每个队列都有一个消费者。使用RabbitMQ,队列使不同的消费者能够使用每条消息。与下图对比:

Fig 3 - Multiple publishers, one queue with multip

在图3中,我们有三个消费者都在单个队列中消费。这些是竞争的消费者,即他们竞争消费单个队列的消息。人们可以预期,平均而言,每个消费者将消耗该队列消息的三分之一。我们使用竞争消费者来扩展我们的消息处理,使用RabbitMQ它非常简单,只需按需添加或删除消费者。无论您拥有多少竞争消费者,RabbitMQ都将确保消息仅传递给单个消费者。

我们可以将图2和图3组合在一起,使多组竞争消费者,每组消费每条消息。

Fig 4 - Multiple publishers, multiple queues with

交换和队列之间的箭头称为绑定,我们将仔细研究本系列第2部分中的箭头。

担保

RabbitMQ提供“最多一次交付”和“至少一次交付”但不提供“完全一次交付”保证。我们将在本系列的第4部分中深入研究消息传递保证。

消息按照到达队列的顺序传递(毕竟是队列的定义)。当您拥有竞争消费者时,这并不能保证完成与完全相同顺序的消息处理匹配。这不是RabbitMQ的错,而是并行处理有序消息集的基本现实。通过使用Consistent Hashing Exchange可以解决此问题,您将在下一部分中看到模式和拓扑。

推和消费者预选

RabbitMQ将消息推送到流中的消费者。有一个Pull API,但它的性能很糟糕,因为每条消息需要一个请求/响应往返(注意,由于Shiva Kumar的评论,我更新了这一段)。

如果消息到达队列的速度快于消费者可以处理的速度,那么基于推送的系统可能会使消费者感到压力。因此,为了避免这种情况,每个消费者都可以配置预取限制(也称为QoS限制)。这基本上是消费者在任何时候都可以拥有的未确认消息的数量。当消费者开始落后时,这可以作为安全切断开关。

为什么推而不拉?首先,它对于低延迟非常有用。其次,理想情况下,当我们拥有单个队列的竞争消费者时,我们希望在它们之间均匀分配负载。如果每个消费者都会收到消息,那么根据他们拉动工作分布的数量,可能会变得非常不平衡。消息分布越不均匀,延迟越多,处理时消息顺序的丢失越多。因此,RabbitMQ的Pull API只允许一次提取一条消息,但这会严重影响性能。这些因素使RabbitMQ倾向于推动机制。这是RabbitMQ的缩放限制之一。通过将确认组合在一起可以改善它。

路由

交换基本上是到队列和/或其他交换的消息的路由器。为了使消息从交换机传送到队列或其他交换机,需要绑定。不同的交换需要不同的绑定。有四种类型的交换和相关绑定:

  • 扇出(Fanout)。路由到具有绑定到交换的所有队列和交换。标准的pub子模型。

  • 直接。根据发布者设置的消息随附的路由密钥路由消息。路由键是一个短字符串。直接交换将消息路由到具有与路由密钥完全匹配的绑定密钥的队列/交换机。

  • 话题。根据路由密钥路由消息,但允许通配符匹配。

  • 头。RabbitMQ允许将自定义标头添加到消息中。标头根据这些标头值交换路由消息。每个绑定包括完全匹配标头值。可以将多个值添加到具有匹配所需的ANY或ALL值的绑定。

  • 一致的哈希。这是一个哈希路由密钥或邮件头并仅路由到一个队列的交换。当您需要使用扩展的消费者处理订单保证时,这非常有用。

Fig 5. Topic exchange example

我们将在第2部分中更仔细地研究路由,但上面是主题交换的示例。发布者使用路由密钥格式LEVEL.AppName发布错误日志。

  • 队列1将使用多字#通配符接收所有消息。

  • 队列2将接收ECommerce.WebUI应用程序的任何日志级别。它使用覆盖日志级别的单字*通配符。

  • 队列3将查看来自任何应用程序的所有ERROR级别消息。它使用多字#通配符来覆盖所有应用程序。

通过四种路由消息的方式,以及允许交换路由到其他交换,RabbitMQ提供了一组功能强大且灵活的消息传递模式。接下来我们将讨论死信交换,短暂交换和队列,您将开始看到RabbitMQ的强大功能。

死信交换机(Dead Letter Exchanges)

我们可以配置队列在以下条件下向交换机发送消息:

  • 队列超过配置的消息数。

  • 队列超出配置的字节数。

  • 消息生存时间(TTL)已过期。发布者可以设置消息的生命周期,队列也可以有消息TTL。哪个更短适用。

我们创建一个绑定到死信交换的队列,这些消息将存储在那里直到采取行动。在另一篇文章中,我描述了我已经实现的拓扑,其中所有死信的消息都发送到中央清算所,支持团队可以在此决定采取何种措施。

与许多RabbitMQ功能一样,死信交换提供了最初未考虑的额外模式。我们可以使用消息TTL和死信交换来实现延迟队列和重试队列,包括指数退避。请参阅我之前的帖子。

短暂的交流和队列(Ephemeral Exchanges and Queues)

可以动态创建交换和队列,并赋予自动删除特征。经过一段时间后,他们可以自我毁灭。这允许诸如用于基于消息的RPC的ephermal回复队列之类的模式。

插件

您要安装的第一个插件是Management Plug-In,它提供HTTP服务器,Web UI和REST API。它非常易于安装,并为您提供易于使用的UI,以帮助您启动和运行。通过REST API进行脚本部署也非常简单。

其他一些插件包括:

  • 一致的哈希交换,Sharding Exchange等

  • 像STOMP和MQTT这样的协议

  • 网络钩子

  • 额外的交换类型

  • SMTP集成

RabbitMQ还有很多东西,但这是一本很好的入门书,让您了解RabbitMQ可以做些什么。现在我们来看看Kafka,它采用了完全不同的消息传递方法,并且具有惊人的功能。

Apache Kafka

Kafka是一个分布式复制的提交日志。Kafka没有队列的概念,因为它主要用作消息系统,所以最初可能看起来很奇怪。长期以来,队列一直是消息传递系统的代名词。让我们分解一下“分布式,复制的提交日志”:

  • 分布式,因为Kafka被部署为节点集群,用于容错和扩展

  • 复制,因为消息通常跨多个节点(服务器)复制。

  • 提交日志因为消息存储在分区中,所以只追加称为主题的日志。这种日志概念是Kafka的主要杀手特征。

了解日志(主题)及其分区是理解Kafka的关键。那么分区日志与一组队列有什么不同呢?让我们想象一下吧。

Fig 6 One producer, one partition, one consumer

Kafka不是将消息放入FIFO队列并跟踪像RabbitMQ那样在队列中跟踪该消息的状态,而是将其附加到日志中,就是这样。无论消耗一次还是一千次,该消息都会保留。它根据数据保留策略(通常是窗口时间段)删除。那么主题如何被消费?每个消费者跟踪它在日志中的位置,它有一个指向消耗的最后消息的指针,该指针称为偏移量。消费者通过客户端库维护此偏移量,并且根据Kafka的版本,偏移量存储在ZooKeeper或Kafka本身中。ZooKeeper是一种分布式共识技术,被许多分布式系统用于领导者选举等领域。Kafka依靠ZooKeeper来管理集群的状态。

这个日志模型的惊人之处在于它立即消除了消息传递状态的大量复杂性,更重要的是消费者,它允许它们倒回并返回并消耗先前偏移量的消息。例如,假设您部署了一个计算发票的服务,该发票消耗了客户预订。该服务有一个错误,并在24小时内错误地计算所有发票。最好使用RabbitMQ,您需要以某种方式重新发布这些预订,并仅发送给发票服务。但是对于Kafka,您只需将该消费者的偏移量移回24小时。

因此,让我们看一下具有单个分区和两个消费者的主题的情况,每个消费者都需要消费每条消息。从现在开始,我已经开始为消费者贴上标签,因为它不是那么清晰(如RabbitMQ图),它们是独立的,也是竞争对手的消费者。

Fig 7 One producer, one partition, two independent

从图中可以看出,两个独立的消费者都使用相同的分区,但他们正在从不同的偏移中读取。也许发票服务处理消息所需的时间比推送通知服务要长,或者发票服务可能会停机一段时间并且赶上,或者可能存在错误并且其偏移量必须移回几个小时。

现在让我们说发票服务需要扩展到三个实例,因为它无法跟上消息速度。使用RabbitMQ,我们只需部署两个发票服务应用程序,这些应用程序将使用预订发票服务队列。但是Kafka不支持单个分区上的竞争消费者,Kafka的并行单元就是分区本身。因此,如果我们需要三个发票消费者,我们至少需要三个分区。所以现在我们有:

Fig 8 Three partitions and two sets of three consu

因此,这意味着您至少需要与最大规模的消费者一样多的分区。我们来谈谈分区。

分区和消费者组

每个分区都是一个单独的数据文件,可保证消息排序。这一点很重要:消息排序只能保证在一个分区内。这可能会在消息排序需求和性能需求之间引入一些紧张,因为并行单元也是分区。一个分区不能支持竞争消费者,因此我们的发票应用程序只能有一个实例消耗每个分区。

消息可以循环方式或通过散列函数路由到分区:散列(消息密钥)%分区数。使用散列函数有一些好处,因为我们可以设计消息密钥,使得同一实体的消息(例如预订)始终转到同一分区。这可以实现许多模式和消息排序保证。

消费者群体就像RabbitMQ的竞争消费者。组中的每个使用者都是同一应用程序的实例,并将处理主题中所有消息的子集。尽管RabbitMQ的竞争消费者都使用相同的队列,但消费者群体中的每个消费者都使用同一主题的不同分区。因此,在上面的示例中,发票服务的三个实例都属于同一个使用者组。

在这一点上,RabbitMQ看起来更加灵活,它保证了队列中的消息顺序,以及它应对不断变化的竞争消费者数量的无缝能力。使用Kafka,如何对日志进行分区非常重要。

Kafka从一开始就有一个微妙而重要的优势,即RabbitMQ后来添加的关于消息顺序和并行性的优点。RabbitMQ维护整个队列的全局顺序,但在并行处理该队列期间无法维护该顺序。Kafka无法提供该主题的全局排序,但它确实提供了分区级别的排序。因此,如果您只需要订购相关消息,那么Kafka提供有序消息传递和有序消息处理。想象一下,您有消息显示客户预订的最新状态,因此您希望始终按顺序(按时间顺序)处理该预订的消息。如果您按预订ID进行分区,那么给定预订的所有消息都将到达单个分区,我们会在其中进行消息排序。因此,您可以创建大量分区,使您的处理高度并行化,并获得消息排序所需的保证。

RabbitMQ中也存在此功能,它通过Consistent Hashing交换机以相同的方式在队列上分发消息。虽然Kafka强制执行此有序处理,因为每个使用者组只有一个使用者可以使用单个分区,并且当协调器节点为您完成所有工作以确保遵守此规则时,可以轻松实现。而在RabbitMQ中,您仍然可以让竞争消费者从一个“分区”队列中消费,并且您必须完成工作以确保不会发生这种情况。

这里还有一个问题,当你改变分区数量时,订单Id 1000的那些消息现在转到另一个分区,因此订单Id 1000的消息存在于两个分区中。根据您处理邮件的方式,这会引起头疼。现在存在消息不按顺序处理的情况。

我们将在本系列的第4部分“消息传递语义和保证”部分中更详细地介绍此主题。

PUSH VS PULL

RabbitMQ使用推送模型,并通过消费者配置的预取限制来防止压倒性的消费者。这对于低延迟消息传递非常有用,并且适用于RabbitMQ基于队列的架构。另一方面,Kafka使用拉模型,消费者从给定的偏移量请求批量消息。当没有超出当前偏移量的消息时,为了避免紧密循环,Kafka允许进行长轮询。

由于其分区,拉模型对Kafka有意义。由于Kafka在没有竞争消费者的分区中保证消息顺序,我们可以利用消息批处理来实现更高效的消息传递,从而为我们提供更高的吞吐量。这对RabbitMQ没有多大意义,因为理想情况下我们希望尽可能快地分配一个消息,以确保工作均匀并行处理,并且消息处理接近它们到达队列的顺序。但是对于Kafka来说,分区是并行和消息排序的单位,所以这两个因素都不是我们关注的问题。

发布订阅

Kafka支持基本的pub sub,其中包含一些与日志相关的额外模式,它是一个日志并具有分区。生成器将消息附加到日志分区的末尾,并且消费者可以在分区中的任何位置放置它们的偏移量。

Fig 9. Consumers with different offsets

当存在多个分区和使用者组时,这种风格的图表不容易快速解释,因此对于Kafka的其余图表,我将使用以下样式:

Fig 10. One producer, three partitions and one con

我们的消费者群体中没有与分区相同数量的消费者:

Fig 11. Sone consumers read from more than one par

一个消费者组中的消费者将协调分区的消耗,确保一个分区不被同一个消费者组的多个消费者使用。

同样,如果我们拥有的消费者多于分区,那么额外的消费者将保持闲置状态。

Fig 12. One idle consumer

添加和删除消费者后,消费者群体可能会变得不平衡。重新平衡会在分区中尽可能均匀地重新分配使用者。

Fig 13. Addition of new consumers requires rebalan

在以下情况之后自动触发重新平衡:

  • 消费者加入消费者群体

  • 消费者离开消费者群体(它关闭或被视为死亡)

  • 添加了新分区

重新平衡将导致短时间的额外延迟,同时消费者停止阅读批量消息并分配到不同的分区。消费者维护的任何内存状态现在都可能无效。Kafka的消费模式之一是能够将给定实体的所有消息(如给定的预订)指向同一个分区,从而导致同一个消费者。这称为数据局部性。在重新平衡任何内存中有关该数据的数据将是无用的,除非将消费者分配回同一分区。因此,维持国家的消费者需要在外部坚持下去。

日志压缩

标准数据保留策略是基于时间和空间的策略。存储到最后一周的消息或最多50GB,例如。但是存在另一种类型的数据保留策略 - 日志压缩。压缩日志时,结果是仅保留每个消息密钥的最新消息,其余消息将被删除。

让我们假设我们收到一条消息,其中包含用户预订的当前状态。每次更改预订时,都会根据预订的当前状态生成新事件。该主题可能包含一些预订的消息,这些消息表示自创建以来预订的状态。在主题被压缩之后,将仅保留与该预订相关的最新消息。

根据预订量和每次预订的大小,理论上可以将所有预订永久存储在主题中。通过定期压缩主题,我们确保每个预订只存储一条消息。

日志压缩可以实现一些不同的模式,我们将在第3部分中探讨。

有关消息排序的更多信息

我们已经讨论过,RabbitMQ和Kafka都可以扩展和维护消息排序,但是Kafka使它变得容易多了。使用RabbitMQ,我们必须使用Consistent Hashing Exchange并使用像ZooKeeper或Consul这样的分布式共识服务自己手动实现使用者组逻辑。

但RabbitMQ有一个有趣的功能,卡夫卡没有。RabbitMQ本身并不特别,但任何基于发布 - 订阅队列的消息传递系统。能力是这样的:基于队列的消息系统允许订户订购任意事件组。

让我们再深入了解一下。不同的应用程序无法共享队列,因为它们会竞争使用消息。他们需要自己的队列。这使应用程序可以自由地配置他们认为合适的队列。他们可以将多个主题中的多个事件类型路由到其队列中。这允许应用程序维护相关事件的顺序。它想要组合的事件可以针对每个应用程序进行不同的配置。

使用像Kafka这样的基于日志的消息传递系统是不可能的,因为日志是共享资源。多个应用程序从同一日志中读取。因此,将相关事件分组到单个主题中是在更广泛的系统架构级别做出的决策。

所以这里没有胜利者。RabbitMQ允许您维护任意事件集的相对排序,Kafka提供了一种维持大规模排序的简单方法。

更新:我已经构建了一个名为Rebalanser的库,它为RabbitMQ for .NET应用程序提供了使用者组逻辑。查看它上面的帖子和GitHub repo。如果人们表现出任何兴趣,那么我就会用其他语言制作版本。让我知道。

结论

RabbitMQ由于其提供的各种功能,提供了瑞士军刀的消息模式。凭借其强大的路由功能,它可以消除消费者在只需要一个子集时检索,反序列化和检查每条消息的需要。它易于使用,通过简单地添加和删除消费者来完成扩展和缩小。它的插件架构允许它支持其他协议并添加新功能,例如Consistent散列交换,这是一个重要的补充。

卡夫卡的分布式日志与消费者抵消使得时间旅行成为可能。它能够将相同密钥的消息按顺序路由到同一个消费者,从而实现高度并行化的有序处理。Kafka的日志压缩和数据保留允许RabbitMQ无法提供的新模式。最后是的,Kafka可以比RabbitMQ进一步扩展,但是我们大多数人都处理一个可以轻松处理的消息量。

在下一部分中,我们将使用RabbitMQ仔细研究消息传递模式和拓扑。

超级架构师

架构师的宝库,每天一篇,开拓你的视野和深度。分享企业架构,业务架构,应用架构,数据架构,技术架构,安全架构等。讨论架构框架,规划,治理,标准,落地。交流新兴的架构风格和模型。如微服务,事件驱动,微前端,大数据,数仓,物联网,人工智能架构。

公众号

超级工程师

前端后端一锅端,数据物联区块链,AI AR 和VR,分析 安全 元宇宙。全栈开发Java,Python,Go,Groovy,Kotlin,C#,Node,TypeScript,JavaScript,Rust, Swift,R,Ruby。

公众号

CIO和CTO

作为企业高管CIO,CDO,CTO的助手,介绍科技趋势,资讯,商业案例,技术实现。 如数字化转型,5G,量子,物联网,云计算,生物科技,隐私计算,虚拟现实,区块链,移动,人工智能,智能设备,机器人,大数据,数据分析,数据智能等.

公众号

首席数字化转型官

交流企业的数字化转型,创新和整合。帮助CIO,CDO,CDTO成长。关注企业数字化方法,流程,框架,案例以及趋势。探讨企业的业务架构规划设计,企业的IT建设和数字化推进。

公众号

 

本文 :https://architect.pub
讨论:知识星球【首席架构师圈】或者加微信小号【ca_cto】或者加QQ群【792862318】
公众号
 
【jiagoushipro】
【架构师酒馆】
精彩图文详解架构方法论,架构实践,技术原理,技术趋势。
我们在等你,赶快扫描关注吧。
微信小号
 
【ca_cea】
50000人社区,讨论:企业架构,云计算,大数据,数据科学,物联网,人工智能,安全,全栈开发,DevOps,数字化.
 

QQ群
 
【285069459】深度交流企业架构,业务架构,应用架构,数据架构,技术架构,集成架构,安全架构。以及大数据,云计算,物联网,人工智能等各种新兴技术。
加QQ群,有珍贵的报告和干货资料分享。

 

视频号 【架构师酒馆】
1分钟快速了解架构相关的基本概念,模型,方法,经验。
每天1分钟,架构心中熟。

知识星球 【首席架构师圈】向大咖提问,近距离接触,或者获得私密资料分享。  

喜马拉雅 【超级架构师】路上或者车上了解最新黑科技资讯,架构心得。 【智能时刻,架构君和你聊黑科技】
知识星球 认识更多朋友,职场和技术闲聊。 知识星球【职场和技术】
微博 【架构师酒馆】 智能时刻
哔哩哔哩 【架构师酒馆】

抖音 【cea_cio】架构师酒馆

快手 【cea_cio_cto】架构师酒馆

 

小红书 【cea_csa_cto】架构师酒馆  

网站 CIO(首席信息官) https://cio.ceo
网站 CIO,CTO和CDO https://cioctocdo.com
网站 架构师实战分享 https://architect.pub   
网站 程序员云开发分享 https://pgmr.cloud
官网 行天智能科技咨询公司 https://xingtian.ai
网站 开发者闲谈 https://blog.developer.chat
网站 首席隐私官内参 https://cpo.work
网站 首席安全官内参 https://cso.pub    
网站 CIO内参 https://cio.cool
网站 CDO内参 https://cdo.fyi
网站 CXO内参 https://cxo.pub
网站 首席架构师社区 https://jiagoushi.pro
谢谢大家关注,转发,点赞和点在看。

 

本文地址
https://architect.pub
SEO Title
Comprehensive understanding of Kafka and RabbitMQ selection (1) - two different messaging methods

【数据集成】如何在Web应用程序中集成多个数据库

QQ群

视频号

微信

微信公众号

知识星球

Chinese, Simplified

在许多情况下,您可能需要集成多个数据库。这可能是特定应用程序项目所必需的。提供更加集中和高效的信息访问本身也是一个目标。

然而,实现这一点可能是一个挑战,尤其是对缺乏经验的开发人员来说。

今天,我们将研究两种方法—集成数据库的关键方法,以及Budibase如何让生活更轻松。

不过,首先,我们将从基础知识开始。

什么是数据库集成?

数据库集成意味着从多个不同的源获取数据,并创建一个可在整个组织中共享和管理的权威版本。这可以包括现有数据库,以及其他来源,如web服务或其他输入。

通常,这意味着将多个现有数据库合并为一个单一的统一资源。其他时候,这可能意味着保留单独的数据库,并创建一个查看、访问和管理信息的平台。

稍后我们将更详细地研究这些问题。

在这两种情况下,目标都是提高整个组织的信息共享、效率和决策能力。集成还有助于保护数据的有效性、完整性和安全性,以及基于此的任何工具的性能。

为什么要集成多个数据库?

现代企业收集和存储大量数据。集成在帮助您使用这些信息方面发挥着至关重要的作用,而不是被它淹没。

当你创造了一个真实的来源时,你就可以让你的团队做出更快、更好的决定。这也消除了在多个位置存储类似信息的需要,从而避免了重复和不一致问题。

此外,集成可用于提供更方便的数据管理过程。例如,通过使您的团队能够从一个工具在多个数据库上执行管理任务。

整合数据库还可以提高性能。例如,通过允许您通过查询单个集中数据库来访问相同的信息。

除此之外,在某些情况下,集成多个数据库是不可避免的。也就是说,这可能是应用程序满足其功能要求的要求。

考虑到这一点,让我们看看在实践中集成数据库的一些不同方法。

Query multiple databases with a single web app

整合数据 vs 连接到多个数据库

如前所述,我们将研究两种不同的集成数据库的方法。每个都有自己的优点和缺点。一些应用程序项目将更适合其中之一。

第一个选项是将数据库整合到单个源中。即,获取现有数据,并将其迁移到单个新数据库。您可能需要这样做的原因有很多,例如,当将数据集移动到云时。

事实上,这种迁移通常是指数据库集成,尽管它不是唯一的方法。

当然,这里也有缺点。

首先,迁移总是会带来风险,包括服务中断、数据丢失或损坏。至少可以说,缓解这些问题是一项艰巨的任务。在某些情况下,这根本不值得,特别是对于小型内部工具。

在其他情况下,迁移根本不可行。

您经常受到软件堆栈中其他平台需求的限制。

例如,您可能需要从使用自己内部数据库的CRM工具中集成数据。如果一个工具会破坏您需要的其他平台,那么迁移数据来构建一个工具是没有意义的。

那么,如何在不进行大规模迁移的情况下集成多个数据源?

解决方案是创建专用工具来管理来自不同来源的数据。换句话说,创建接口、定义业务流程或创建虚拟表以实现无缝数据集成。

这里的目标是能够无缝地查询不同的数据库,就像它们是一个数据库一样。其中一个要素是保持存储在多个数据库中的类似属性之间的一致性。

例如,CRM和发票平台都存储客户的联系信息。

您可以将其视为一种事实上的集成,因为实际的数据库彼此保持独立和不同。

考虑到这一点,让我们深入探讨每种集成方法的实用性。

整合多个数据库

如前所述,集成通常是指将多个数据库合并到一个源中的做法。

然而,这在实践中可能意味着许多不同的事情。首先,这在很大程度上与所讨论的数据库的不同有关。

让我们来看看几个不同的场景,以及它们的区别。

将数据库与单个模式集成

如果您在不同的位置有多个数据库,但它们共享一个模式,那么整合相对简单。例如,如果不同的用户都具有相同数据集的本地版本。

查看我们关于数据库模式的文章以了解更多信息。

本质上,在这种情况下,我们需要做的就是创建一个与现有模式匹配的主数据库,并从本地版本导入所有值。

根据您用于新数据库的DBMS,这可以通过直接文件上载、自动查询甚至手动数据输入来完成。您选择哪种方法在很大程度上取决于您使用的数据集的规模和复杂性。

例如,如果您有由一个或两个表组成的多个数据库,那么手动上载数据可能是最简单的选择。使用Budibase,您可以使用CSV文件将数据批量导入我们的内部数据库或任何其他连接的源。

举一个简单的例子,假设您的每个销售团队都将他们的销售线索存储在各自的Postgres数据库中。每个人只有一张桌子。您决定将它们以MySQL表的形式集成到一个新的主列表中。

您的目标是构建一个应用程序,帮助销售同事共享信息,避免反复联系同一位同事。

我们可以在Budibase中将每个Postgres数据库添加为单独的数据源,自动获取表,并将所有值导出到CSV文件,而无需编写单个查询。然后,我们可以连接到新的MySQL表,并在Budibase生成器中导入值。

这会将所有现有值移动到主列表中。然后,我们可以创建一个简单的自动化,这样,每当单个销售同事添加新潜在客户时,它也会添加到主列表中。

How to integrate multiple databases with similar entities

从不同的数据库模式集成数据

自然,当您使用多个不共享公共模式的数据库时,事情会变得更加复杂。例如,如果要将多个完全不同的数据集移动到单个主源中。

在很大程度上,这有时也称为数据仓库。

事实上,这本身就是一门高度专业化的学科,因此建议我们可以在本指南中全面概述如何开展这项工作是有误导性的。

相反,让我们探讨在进行这种集成时必须记住的一些关键考虑因素。

评估您对新数据库的需求

您将在这里做出的许多决定将取决于存储实体之间的相似性或差异程度。这在创建新数据库模式时尤为重要。

因此,您可能有多个数据库存储关于同一实体的不同类型的信息。或者,您可能有几个处理完全不同的实体集的数据库。

例如,集成与客户相关的两组数据可能比集成两个完全不同的数据集要小得多。

在第一个场景中,我们只需要从DBMS中查询每个现有数据库,并为所需的每个实体创建新的主版本。

正如我们稍后将看到的,这在实践中可能会稍微复杂一些。

无论哪种情况,关键都是为主数据库定义一个满足信息需求的模式,同时保留原始源的内容。

保持一致性和完整性

在集成数据库时保持一致性和完整性可能是一项重大挑战。其中一部分与现有数据的类型和格式有关。当不同的数据库已经以不同的方式存储相似的属性时,这是一个特别值得关注的问题。

这可能源于原始数据库所有者做出的决定,或者源于底层DBMS的约定。

例如,不同的数据库可能会以不同的方式处理字符串或数字数据。这将在尝试操作值时造成困难。

这里的关键是有效地转换现有数据以满足新的数据库模式。这里的细节将因项目而异。查看我们的应用程序数据源终极指南,了解有关转换的更多信息。

处理重复和差异

数据库之间的重复值和差异是集成过程中的另一个主要问题。这里,重复意味着相同的值存储两次。当给定对象的相同属性存储两次,但值不同时,就会出现差异。

假设您正在集成两个数据库,每个数据库存储客户电话号码的值。如果在多个数据库中的不同表上保留此属性,则会发生重复。

如果您为同一客户存储了不同的电话号码,则会出现差异。这可以是值本身的级别,也可以是它的格式。

当然,在某些情况下,您可能希望在数据模型中构建冗余,但在单个数据库中实现这一点并不常见。

在集成项目中,这意味着您需要决定对任何重复属性优先考虑哪个源。

管理关系

当您为新的主数据库开发模式时,您可能必须彻底重新考虑不同实体之间的关系。这同样适用,无论您的原始数据库是否处理类似的实体。

在其他情况下,事情可能会简单一点。一些集成项目可能意味着将一个单独的附加表附加到一个更大的数据库中,并将其存储在一个新的模型和模式中。

这将相对简单,因为您可能不需要实质性地改变大多数实体的关系。

在其他情况下,定义实体之间的关系将更加复杂。我们已经创建了一个关于如何创建数据模型的专门指南,您可以查看该指南以了解更多信息。

存储、托管和访问

还有一个问题是如何物理存储和托管新数据库。例如,在云主机或本地存储之间进行选择。

您还需要考虑用于管理迁移数据的实际DMBS。

例如,我们前面提到了一个场景,我们可以将两个Postgres数据库集成到一个MySQL实例中。

显然,您将在这里做出的具体选择高度依赖于特定项目的需求。例如,您可能会选择Postgres、MySQL、MSSQL、SQL Server、Airtable、CouchDB、MongoDB、Oracle、S3或大量其他数据库工具。

移植风险

对于大型数据库整合项目,减轻不同的迁移风险也至关重要。

事实上,任何类型的数据迁移都有无数巨大的风险。

其中最明显的是数据丢失、损坏和服务中断时间延长。因此,彻底审查您在迁移过程中使用的任何集成工具和合作伙伴非常重要。

除此之外,大型集成项目还会对更广泛的软件堆栈产生影响。更具体地说,不同的工具在数据移动后查询数据时可能会遇到问题。它们也可能不支持新的数据存储或DBMS。

例如,当属性名称更改时,可能会出现语义问题,但自动查询没有更新以反映这一点。

如何在web应用程序中集成来自不同来源的数据

如前所述,存在批发整合的替代方案。这包括从一个工具查询多个数据源,实现集成的许多好处,而无需迁移数据。

这是跨不同数据集创建单一、可访问的真实来源的有效方法。我们还可以使用简单的web应用程序,通过定义的工作流提高效率并减轻管理多个数据库的管理负担。

这也消除了与其他类型集成相关的一些风险。

然而,在一个应用程序中使用多个数据库也会带来严重的挑战。例如,查询错误、源之间的不一致性,以及使用单个数据源的所有常见挑战。

因此,这种策略通常更适合于相对简单的工具和数据集。

本质上,这样的网络应用程序必须实现两件事:

  • 为用户提供与查询单个主数据库相同的体验。
  • 当通过其他现有工具进行更改时,保持连接数据库之间的一致性。

例如,您可能有单独的平台,内部数据库存储不同类型的客户信息。您可以构建一个工具,为您的服务团队提供单一的真实来源,并使其更易于管理和维护客户详细信息。

让我们看看你如何在Budibase建造这座建筑。

1.连接数据

第一步是将数据库连接到Budibase生成器。当然,您可能有几个数据源,但为了简单起见,我们将在示例中使用两个。假设我们有一个来自CRM的MySQL数据库和一个来自开票工具的Postgres数据库。

每个都有多个表,其中一个用于客户详细信息。这些通用表存储了一系列不同的属性,但每个数据库都包含每个客户的联系信息字段。

我们希望构建一个工具,内部用户和客户自己可以通过一个界面在两个数据库中更新他们的联系信息。

Budibase为外部数据提供了一系列直观的连接器。在生成器中,转到“数据”选项卡,然后选择加号图标以添加新源:

How to integrate multiple databases

首先,我们将通过选择Postgres并输入凭据,连接到发票平台的数据库:

Connect Postgres

然后,我们可以对CRM的MySQL数据库执行同样的操作:

Connect MySQL

当我们保存其中的每一个并获取表时,我们将拥有在两个数据库上执行CRUD查询的完整连接。

每个数据库有两个表。我们的CRM为客户和用户存储实体:

Fetch tables to integrate multiple databases

开票工具为客户和发票提供了单独的表格:

Fetch Tables

在我们的示例中,我们只关注每个数据库中的customers表。我们可以单独处理这些表和其他内部表之间的关系。

2.创建组合数据表

请记住,我们的数据库共享每个客户的某些属性,但它们也存储一些独特的信息。具体来说,每个存储联系人详细信息以及其他独特属性。

我们的下一个任务是为用户提供一个单独的资源,在那里他们可以看到每个客户存储的所有详细信息。

换句话说,我们需要创建一个表,其中包含两个数据库的客户记录中的所有属性。我们可以用几种不同的方式来实现这一点,例如创建一个虚拟表。

出于我们的目的,我们将创建一个新的物理表。我们可以在现有数据库中使用BudibaseDB或在一个全新的数据库中执行此操作。为了简单起见,我们将在CRM的现有MySQL主机中创建一个新表。

我们将首先编写一个查询来复制CRM的客户表:

Duplicate table query

您可以在DMBS中执行此操作,也可以在Budibase中作为自定义查询执行,如上所示。

然后,我们可以使用Budibase将发票工具中所需的任何其他属性添加到新的组合表中。在我们的案例中,我们只有一个-客户的计费周期。

然后,我们将构建一个简单的自动化,将相关的计费周期值添加到新表中。有许多不同的方式可以触发此操作,包括用户操作或设置时间段。

然而,由于我们在发票客户数据集中只有相对较少的条目,我们将使用更新的行触发器,因此我们可以逐个传递每个值。

稍后我们将介绍更多的自动化。目前,我们所需要做的就是将初始值设置到位。首先,我们将在更新crm_business_information表中的行时设置触发器。

接下来,我们需要查询invoice_customers_table,并使用过滤器查找与触发器具有相同业务名称的行。

Bindings

最后,我们将使用触发器行和invoice_customers表中的值的组合来更新combined_customers_table中的相关行。

Configure attributes

有了这一点,我们就可以手动更新crm_business_infromation表中的任何行,以从发票数据库中携带账单周期值。

如果我们想批量执行此操作,我们可以使用不同的触发器(如用户操作),并更改自动化以遍历两个表中的每一行,并将新值添加到正确的行。

3.构建CRUD屏幕

现在我们有了一个组合表,我们可以开始构建CRUD屏幕来查询我们的两个数据库。记住,我们的目标是拥有一个用于管理两个数据库共享属性的单一接口。

因此,基本上,我们需要创建一个表单,在那里我们可以编辑客户的联系信息,并将这些新信息传递给我们的CRM和发票平台。

显然,最好的用户体验是允许用户通过一个表单完成这一操作。

我们希望这可以更新客户的联系信息,同时将任何唯一属性单独保留在任一数据库中。

首先,我们将自动为组合的customers__table生成CRUD屏幕。

Generate CRUD screens

为了简单起见,我们将通过将编辑表单UI设置为以模态打开,使其成为一个单屏幕应用程序。当您在Budibase中自动生成CRUD屏幕时,您还可以创建行表单,但我们不需要这些表单。

现在,我们将开始处理编辑表单。

How to integrate multiple databses

我们需要做的第一件事是删除不希望用户通过表单编辑的属性的任何字段。因此,在本例中,非接触式详细信息是ID、类别、描述和billing_cycle。

Form

我们现在有了一个工作表单。但是,如果用户完成了这一操作,它只会更改组合表中的条目详细信息,而不会更改两个源表。

接下来,我们需要创建自动操作,以在合并表中的行发生更改时更新源数据库。

4.自动查询

记得前面我们创建了一个自动化,这样当crm_business_information表中的一行被更新时,invoice_customers中的相关客户将被查询,而他们的详细信息将在combined_customers_table中更新。

我们的应用程序要求如下:

  • 用户可以使用单个表单界面更新两个源数据库中的客户联系信息。
  • 当手动更新其中一个源数据库时,另一个数据库中的联系人详细信息应保持最新。

因此,我们实际上需要三种类似的自动化:

  • 表单完成后,两个源数据库都会更新新的联系人详细信息。
  • 在外部更新crm_business_information表时,应更新组合列表和invoice_customers表以反映这一点。
  • 如果invoice_customers表已更新,则组合列表和crm_business_information也应如此。

首先,我们将在用户完成表单时更新源数据库。因此,我们将再次使用更新的行触发器。然后,我们希望遵循与前面相同的步骤。因此,对于每个源数据库,我们将执行以下操作:

添加一个查询行块,并设置一个过滤器以隔离与触发器具有相同业务名称的行。

添加一个更新行块,使用我们的表单数据更新联系人详细信息。

Build an automation

我们使用查询行块输出的ID和原始表单触发器提供的信息来更新相关行:

Configure Fields

我们使用JavaScript绑定将每个单独的属性传递给我们的自动化:

Integrate multiple databses javascript binding

现在,我们可以通过为invoice_customers表添加相同的块来重复这个过程。

Update two DBs from form

我们可以测试我们的自动化,以确保它在现实生活中工作。我们将使用我们的表单将一个客户的电话号码更新为000-000-000:

Integrate Multiple Databases form

然后,我们将在源DMBS中运行查询,以确保其正常工作。MySQL数据库中的第一个

MYSQL Query

然后在我们的Postgres表中:

Postgres SQL Query

现在,我们可以使用一个表单UI在多个数据库中更新客户的联系信息。

最后一步是创建自动化流程,以便每当在各自的外部平台中更新其中一个数据库时,这一变化都会反映在另一个数据库中。

对于大部分自动化,我们可以使用与上述完全相同的步骤。我们只需要为每个表组合修改它。

我们可以通过几种不同的方式来触发这一点。

一种选择是,当出现差异时,决定我们的哪个表优先。然后,我们可以使用按时间顺序的触发器周期性地遍历两个表中的每一行,并相应地更新它们。

或者,当任何数据库发生更改时,我们可以使用更新行触发器来自动更新所有相关条目,这与我们使用combind_customers_table中的触发器的方式大致相同。

如何确保来自多个源的数据兼容?

最后,请注意在集成多个数据库时保持一致。到目前为止,在我们的所有示例中,我们都使用了具有相对基本模式的小型数据集。当然,情况并不总是这样。

实际上,在许多情况下,不同数据库中类似属性的值不兼容。

在这些情况下,您需要使用转换来确保数据兼容。

例如,如果我们的一个现有数据源将某个特定属性存储为字符串,而另一个数据源将数值存储为同一变量,则需要执行此操作。这可能发生在不同平台上的客户电话号码上。

我们不一定要改变现有数据库的模式。毕竟,我们可能有其他工具依赖这些数据,我们不想打破这些。相反,我们可以在数据库之间传递值时使用JavaScipt表达式来转换值。

在Budibase中,您可以创建自定义查询来执行转换,也可以在创建自动化时绑定任何值时使用自定义JavaScript。

查看我们的web应用程序数据源终极指南,了解有关转换的更多信息,以及如何在使用多个数据库时使用这些数据源。

本文地址
https://architect.pub/how-integrate-multiple-databases-web-app
SEO Title
How to Integrate Multiple Databases in a Web App