ActiveMQ是用于消息传递的开源消息中间件。它提供了可靠的异步通信机制,用于在分布式系统中传递消息。ActiveMQ支持多种协议和编程语言,并具有高度可扩展性和可靠性。它可以用于构建可靠的消息传递系统,实现应用程序之间的解耦和异步通信。 关于使用数据库来应用消息传递的概念,实际上是可以的。数据库可以用作消息传递的持久化存储,以确保消息在传递过程中不会丢失。通过将消息存储在数据库中,可以实现消息的持久化和可靠性。然而,需要注意的是,使用数据库作为消息传递的存储介质可能会引入一定的延迟和性能开销。因此,在设计和实施时需要权衡利弊,并根据具体需求选择合适的方案。

117
我查了一下,它过去是用来在两个系统之间发送消息的。但是为什么呢?为什么不直接使用数据库呢?
肯定是ActiveMQ有一些数据库没有的特性吧?

1
类似的问题:https://dev59.com/uXE85IYBdhLWcg3wPBF8 - EMBarbosa
8个回答

182

它被用于可靠地在两个分布式进程之间通信。

是的,你可以将消息存储在数据库中以在两个进程之间通信,但是,一旦消息被接收,您需要DELETE该消息,这意味着对于每条消息都需要进行INSERTDELETE操作。
当您尝试扩展以每秒传输数千条消息时,数据库往往会崩溃

反之,像ActiveMQ这样的消息中间件[MOM]则是为处理这些用例而构建的。
它们假设健康系统中的消息将会被非常快速地删除,并且可以进行优化来避免开销

它还可以将消息推送给消费者,而不是消费者必须执行SQL查询来轮询新消息。
这进一步减少了处理新发送到系统中的消息所涉及的延迟。


很好的解释!这两个分布式进程必须是同一个进程吗?我的意思是同一个应用程序的两个实例? - Maverick
1
不,任意应用程序都可以通过ActiveMQ相互通信。例如,应用程序A和B可以创建队列A.B和B.A(即:从B到A的消息和反之亦然),并将彼此的消息发送到匹配的队列中。 - Alex
我有一个特定的用例,需要存储对象状态信息(例如具有GPS、燃料和发动机油信息的汽车),以便其他客户端软件可以在连接到服务器时立即接收此信息,即使信息已经推送了几个小时并且没有更新。就像缓存一样,这样我就不需要多次查询数据库。同时,当信息确实发生更改时,它会被推送到客户端。针对这种情况,我该寻找什么? - gouderadrian

68

ActiveMQ,或者一般所有面向消息的中间件(MOM)的实现都被设计用于在两个应用程序或一个应用程序内的两个组件之间发送消息

本质上,MOM和数据库共享一个共同基础,即它们提供事务性和持久性数据存储以供读写。
最大的区别在于使用模式-数据库非常通用且优化用于跨多个表进行复杂搜索,而MOM则针对读取消息进行了优化,以FIFO方式(队列)逐个读取。

JMS是ActiveMQ实现的API,在Java企业应用程序中是一个重要的基石。这使得消息共享相当普遍的格式和语义,从而使不同应用程序之间的集成更加容易。

当然,还有许多仅在ActiveMQ中具有的更详细的功能,如OpenWireSTOMPMQTT的线路协议、JMSEIP与Apache Camel、"请求/回复"和"发布/订阅"消息模式、JMS桥接、群集化("经纪人网络")等,这些功能实现了可扩展性和分布式处理,等等。
如果您有兴趣,可以稍微了解一下这些主题,因为它们非常庞大。


很好的解释,先生。您能推荐一些关于ActiveMQ的详细教程/网络资源吗? - Saswata Mishra
1
@SaswataMishra 这是一个10年前的答案。世界已经发生了一些变化,可能会有其他更好的方法。无论如何,如果你至少在使用Java,这个教程涵盖了所有基础知识。https://www.devglan.com/spring-boot/spring-boot-jms-activemq-example - Petter Nordlander

25

ActiveMQ拥有出色的调度程序支持,这意味着您可以安排发送消息以在特定时间交付

我们已经在医疗保健场景中使用此功能向上传药品详细信息的患者发送用药提醒。


4
挺不错的。我们曾经使用过Quartz调度库来实现类似的提醒功能。 - Siddhartha
我们已经使用了Oracle数据库的“计划作业”来实现相同的目的。 - Ahmed Nabil

15

使用关系型数据库管理系统(RDBMS),在处理一行数据时,您通常会更新一个标志以指示该行已被处理,以便不会重复进行处理。

但是,在消息队列中,您只需要确认一条消息,下一个消费者将处理下一条消息。

区别在于,与 RDBMS 中的 UPDATE 语句相比,activemq 中的 acknowledge 操作非常快速。


8

来自维基百科

Apache ActiveMQ是一个开源的消息代理,使用Java编写,拥有完整的Java消息服务(JMS)客户端。它提供了“企业级功能”,这意味着可以促进来自多个客户端或服务器的通信。

关于你的问题:

为什么不使用数据库?

应该将数据库用于持久数据而不是临时数据。假设你需要向接收方发送一条消息,当接收方接收到消息后,会执行一个操作(接收、处理和遗忘)。在处理完该消息后,你就不再需要那条消息了。在这种情况下,将消息存储在持久数据库中并不是一个正确的解决方案。

我完全同意@Hiram Chirino的回答,他对于如果使用数据库而不是消息系统进行插入和删除消息的回答也非常认同。

从这篇文章和这篇文章中可以获得更多好处。

  1. 企业集成:允许使用不同编程语言和操作系统构建的应用相互集成。
  2. 位置透明性:客户端应用程序无需知道服务应用程序的位置。
  3. 可靠通信:消息的生产者/消费者无需同时在线。
  4. 可伸缩性:通过添加更多服务进行水平扩展。
  5. 异步通信:客户端可以发送消息并继续其他处理,而不必阻塞,直到服务发送响应。
  6. 减少耦合:由于前面提到的5个优点,客户端和服务所做的假设大大降低了。服务可以更改其自身的详细信息,包括其位置、协议和可用性,而不会影响或中断客户端。

ActiveMQ 有哪些数据库没有的功能?

有很多。请查看文档页面获得更多详细信息。也可以查看用例

请查看此演示文稿,了解ActiveMQ的内部情况。


8
我想强调以下几点:

解耦:系统能够在无连接状态下通信。队列位于系统之间,一个系统的故障不会影响其他系统,因为通过队列进行通信。当系统处于开启状态时,它们将继续工作。

恢复支持:队列中的消息本身被保留。如果队列出现故障,可以稍后恢复消息。

可靠的通信:考虑一个处理客户请求的系统。在正常情况下,该系统每分钟接收100个请求。当请求数量超过平均值时,该系统是不可靠的。在这种情况下,队列可以管理请求,并根据系统吞吐量定期推送消息而不会破坏它。

异步:客户端服务器通信是非阻塞的。一旦客户端向服务器发送请求,它可以在等待响应的同时执行其他操作。当收到响应后,客户端可以随时处理。


2

假设您有一个应用程序,同时在多个位置使用。 此外,假设您的应用程序每分钟必须处理数千个请求或类似操作,因此普通的数据库操作无法处理这样的操作,ActiveMQ作为消息处理,将所有消息进入队列,因此即使其中一个应用程序在某个位置崩溃,其他位置也不会受到影响。


1
考虑以下通用用户场景:
用户上传文本文档 您的应用程序将文本文档转换为PDF 您的应用程序通过电子邮件将PDF发送回客户
基于队列的系统的数据库 在这种情况下,您可以考虑为PDF作业行使用数据库。通常,您会创建一个包含一行记录PDF请求的数据库表。然后,您将在表中放置一个标志,表示任务所处的状态以及任务是否已完成。
INSERT INTO pdf_job_queue (name, status, email) VALUES ("White paper", "NEW", "myemail@example.com");

SELECT * FROM pdf_job_queue WHERE queue = 'resize_queue' AND handled = false ORDER BY date_recived limit 1;

你需要编写代码将新请求插入到数据库中。代码从数据库中获取输入,可能更改状态列,值为“NEW”和“PROCESSING”,处理请求的代码,再次更新数据库状态字段为“FINISHED”,以及删除队列中的请求所需的更多代码。
update pdf_job_queue set Status="FINISHED" where Id = 'SomeId';

为了有效运作,您可能需要快速而频繁地轮询数据库。当然,这会给数据库和应用程序增加重要负载。
消息队列 当您尝试使用消息队列来实现相同的功能时。
实时推送 消息行中的消息是实时推送的,而不是偶尔从数据库中调查。使用消息行可以有效地维护更高数量的并发消息。在收到消息后,消息队列会自动清理消息行中的消息。
确认 工作者向消息队列发送确认,告知其已接收和处理特定消息,并且消息队列可以删除该消息。如果工作者在没有发送确认的情况下死亡,则消息队列将了解到消息未被完全处理,并将其重新传递给队列和另一个工作者。通过这种方式,您可以确保没有消息丢失。
对于消息队列系统,我始终建议使用ActiveMQ,因为它易于安装、配置和扩展。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接