1.全局有序:生产者发送和消费者获取的队列只有一个,可以保证所有topic中的消息都是有序的。
2.分区有序:在生产和消费的过程中有多个queue参与,但是每个queue中的消息都是有序的,这就是分区有序。
3.如何实现分区有序呢?
我们只要保证将需要满足有序的一组消息按顺序放到同一个队列中即可,例如将同一订单号的所有消息放置在一个queue中,然后消费者再采用一定的策略(例如,一个线程独立处理一个queue,保证处理消息的顺序性),能够保证消费的顺序性。
那么如何进行队列的选择呢(如何保证将同一订单的所有消息放到同一个队列中呢)?在定义生产者的时候我们可以可以指定消息队列选择器,这个选择器是通过实现MessageQueueSelector接口定义的。在定义选择器的选择算法时,一般需要使用选择key。这个选择key可以是消息key也可以是其它数据。但无论谁做选择key,都不能重复,都是唯一的。
一般性的选择算法是,让选择key(或其hash值)与该主题Topic所包含的队列Queue的数量取模,其结果即为选择出的队列Queue的QueueId(例如选择key是id,queue的数量是len,那么这条消息最后选择的队列序号就是id%len)。
但是在这种情况下,不同的选择key最后的取模结果可能是相同的,那么可能出现不同选择key的消息出现在了同一个queue中。此时一个consumer可能会消费到不同选择key的消息。这个问题如何解决呢?可以对消息的选择key进行判断,如果它是当前consumer要消费的消息,那么处理,否则什么也不做。
可是上面的做法会不会出现新的问题:不属于consumer A的消息被拉走了,但A却不处理。另一个consumerB想要处理这个消息,此时它还能处理吗?这种情况是不存在的。同一个Queue中的消息不可能被同一个Group中的不同Consumer同时消费。所以,消费一个Queue的不同选择key的消息的Consumer一定属于不同的Group。而不同的Group中的Consumer间的消费是相互隔离的,互不影响的。也就是说对于queue中的消息,如果A和B属于同一个group,那么它俩不可能同时消费这个消息。如果A和B属于不同的group,它俩都可以消费这个queue中的消息,但是它俩是相互隔离,互不影响的,即使A已经拉取了消息,B也可以接着拉取。
4.XA协议:
XA(Unix Transaction)是一种分布式事务解决方案,一种分布式事务处理模式,是基于XA协议的。XA协议由Tuxedo(Transaction for Unix has been Extended for Distributed Operation,分布式操作扩展之后的Unix事务系统)首先提出的,并交给X/Open组织,作为资源管理器与事务管理器的接口标准。
XA模式中有三个重要组件:TC、TM、RM。
TC:
Transaction Coordinator,事务协调者。维护全局和分支事务的状态,驱动全局事务提交或回滚。
RocketMQ中Broker充当着TC。
TM:
Transaction Manager,事务管理器。定义全局事务的范围:开始全局事务、提交或回滚全局事务。它实际是全局事务的发起者。
RocketMQ中事务消息的Producer充当着TM。
RM:
Resource Manager,资源管理器。管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
RocketMQ中事务消息的Producer及Broker均是RM。
5.事务消息:1.事务消息不支持延时消息。2.对于事务消息要做好幂等性检查,因为事务消息可能不止一次被消费(因为存在回滚后再提交的情况)
6.简单的生产者消费者处理事务消息的过程:
生产者生产事务消息(此时相当于事务消息处理中的预提交消息,生产消息完成后相当于预提交消息成功),然后消费者消费消息(普通消费者就行),然后生产者监听消费者返回的消息(消息预提交成功后就会触发监听回调事件,随时监听消费者的返回结果),根据收到的消息进行事务的提交、回查或者回滚。
7.一般的生产者和消费者处理消息的流程:
生产者显式地生产消息。在实际应用中是否存在这样的情况:前端向后端某个接口发送请求,在controller层中处理这个请求时,生产者开始根据前端发送过来的请求参数生产消息,然后将其发布出去。
消费者隐式地消费消息。消费者创建之后,会交给容器管理,当监听到订阅主题的消息后,消费者自动调用相关方法对监听到的消息进行消费。
但是我有个问题,消费者可以调用接口对应的方法吗?就比如下面的接口:
@GetMapping
public List<User> list(){
return userService.select();
}
消费者在消费消息的时候可以直接使用list()吗?
如果在springboot单体项目中使用rocketmq,每个接口(controller中的方法)对应的是生产者还是消费者呢?