RocketMQ
分布式事务
相对于本地事务,分布式事务是为了满足跨数据源或跨服务的事务场景。上图展示了RocketMQ在分布式事务中的应用,满足CAP定理中的AP,保证最终一致性。主要工作流程就是:本地服务先发一个半消息,这个消息是不能被其他服务进行消费的,然后执行本地事务,根据本地事务执行的成功与否,决定半消息是commit还是rollback,如是commit,这个消息就能被第三方消息进行消费;如果是rollback,这个消息就会被彻底删除。消息的生产服务可能会因为网络原因、应用问题等,导致一直没有对这个半消息进行确认,那么这时候 Broker服务器会定时扫描这些半消息,主动找Producer端查询该消息的状态。当然,什么时候去扫描,包含扫描几次,我们都可以配置。对于消息的消费,在分布式事务的场景中还要考虑幂等性问题,因为RocketMQ、Kafka仅仅保证at-least-once语义,但是无法满足exactly-once(仅一次)语义。比如一个订单消息消息可能被重复消息,这时候可以通过订单处理日志/状态表来对以处理过的订单消息进行过滤。
延时消息
生产者把消息发送到消息队列中以后,并不期望被立即消费,而是等待指定时间后才可以被消费,这类消息通常被称为延迟消息。延时消息是一种很常用的业务场景,在RocketMQ中,只支持特定级别的延迟消息,但是不支持任意时间精度的延迟消息。如果要支持任意时间精度,不能避免在Broker层面做消息排序,再涉及到持久化的考量,那么消息排序就不可避免产生巨大的性能开销。在RocketMQ中,消息延迟级别分别为1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h,共18个级别。
如上图所示,延时消息在RocketMQ的工作流程如下:
如果消息的延迟级别大于0,则表示该消息为延迟消息,修改该消息的主题为SCHEDULE_TOPIC_XXXX,队列Id为延迟级别减1。
消息进入SCHEDULE_TOPIC_XXXX的队列中。
定时任务根据上次拉取的偏移量不断从队列中取出所有消息。
根据延时级别的时间,筛选出已经到期的消息
根据消息属性重新创建消息,清除延迟级别,恢复原主题和队列Id。
重新发送消息到原主题的队列中,供消费者进行消费。
顺序消息
对于RocketMQ中的同一个队列,消息的到达顺序决定了消息的消费顺序(FIFO),但是RocketMQ是无法保证全局消息的有序性,原因是如果读写队列有多个,
消息就会存储在多个队列中,消费者负载时可能会分配到多个消费队列同时进行消费,多队列并发消费时,无法保证消息消费顺序性。所以本文想说的是针对同一个队列如何实现顺序消息,如下图所示:
队列选择器(MessageQueueSelector)可以帮助我们将顺序消息发送到同一个消息队列上,如图中订单消息所示,我们仅仅在消息发送的过程实现MessageQueueSelector接口的select方法,在select方法中根据订单ID选择消息队列即可,如下面示例代码所示:
保证订单消息发送到同一个消息队列之后,还需要保证顺序消息,在RocketMQ中MessageListenerOrderly自带此实现,如果使用MessageListenerConcurrently则需要使用单线程模式
标签:事务,Day08,乔亚,队列,玛丽,消费,消息,RocketMQ,延迟 From: https://www.cnblogs.com/dwj-ngu/p/17107632.html