消息中间件

JMS

JMS 是Java Message Service 的缩写,它是Java EE 中的一个关于消息的规范。而Hornetq,ActiceMq 等产品都是对这个规范的实现。如果是企业内部或者一些小型的系统,直接使用JMS 的实现产品是一个经济的选择,而在大型系统中有一些场景不适合使用JMS。

在大型互联网中,采用消息中间件可以进行应用之间的解耦以及操作的异步。这是消息中间件的两个最基本的特点,也正是我们需要的。在此基础上,更多考虑的是消息的顺序保证,扩展性,可靠性,业务操作与消息发送一致性。以及多集群订阅等方面的问题。

什么是中间件

非底层操作系统软件,非业务应用软件,不是直接给最终用户使用的,不能直接给客户带来价值的软件都统称为中间件

如何解决消息发送一致性

首先 ,消息发送一致性是指产生消息的业务动作与消息发送的一致,也就是说,如果业务操作成功了,那么由这个操作产生的消息一定要发送出去。否则就丢失消息了,另一方面,如果这个业务行为没有发生或者失败,那么久不应该把消息发送出去。

JMS 是否有方案?

主要是用XA开头的接口来实现,XA系列的接口支持了分布式事务的支持,(即发送消息和业务操作用事务包住)

但是此做法有相应的问题:

  • 引入了分布式事务,这会带来一些开销并增加复杂性
  • 对于业务操作有限制,要求业务操作的资源必须支持XA协议,才能够与发送消息一起来做分布式事务。这会成为一个限制,因为并不是所有需要与发送消息一起做成分布式事务的业务操作都支持XA协议。

XA是一个分布式事务协议,由Tuxedo提出。XA中大致分为两部分:事务管理器和本地资源管理器。其中本地资源管理器往往由数据库实现,比如Oracle、DB2这些商业数据库都实现了XA接口,而事务管理器作为全局的调度者,负责各个本地资源的提交和回滚。

总的来说,XA协议比较简单,而且一旦商业数据库实现了XA协议,使用分布式事务的成本也比较低。但是,XA也有致命的缺点,那就是性能不理想,特别是在交易下单链路,往往并发量很高,XA无法满足高并发场景。XA目前在商业数据库支持的比较理想,在mysql数据库中支持的不太理想,mysql的XA实现,没有记录prepare阶段日志,主备切换回导致主库与备库数据不一致。许多nosql也没有支持XA,这让XA的应用场景变得非常狭隘。

另外的方案

1 业务处理应用首先把消息发送给消息中间件,标记消息的状态为待处理。

2 消息中间件收到消息后,把消息存储在消息存储中,并不投递该消息。

3 消息中间件返回消息处理的结果(仅是入库的结果),结果是成功或者失败。

4 业务方收到消息中间件返回的结果并进行处理。

  • 如果收到的结果是失败 那么就放弃业务处理,结束。
  • 如果收到的结果是成功,则进行业务自身的操作。

5 业务操作完成,把业务操作的结果发送给消息中间件。

6 消息中间件收到业务操作结果,根据结果进行处理。

  • 如果业务失败,则删除消息存储中的消息,结束。
  • 如果业务成功,则更新消息存储中的消息状态为可发送,并且进行调度,进行消息的投递。

消息队列模型

Queue 模型

多个消费者,消费的消息是不同的,多个消费者的消费消息和是全部消息。

Topic 模型

所有消费者是可以收到所有的消费消息的