RocketMQ4.3.x对顺序消息的理解
1、RocketMQ消息队列简单介绍
这里简单介绍一下RocketMQ的消息队列的模型
一个topic对应多个队列如下图:

生产者和消费者分别向队列中发送和消费消息,生产者和消费者都可以是多个,通过组名进行群组约束。由于负载因素造成生产消息会生产到各个queue中。
消费群组进行queue消费时首先因为负载因素,queue会分配给各自的消费实例中,如果消费组有变化会重新分配,导致queue分配乱序。
另外一个消费者实例消费对应的queue时,消费者使用线程池进行处理消息。
以上各种操作都会导致消息不一定先处理就会先完成,所以造成消息消费不是严格顺序处理的。
所以在之前的版本中假如我们要求要严格按照顺序进行消息处理的话就必须进行单队列单线程进行消息消费处理
4.0.0之后版本支持顺序消费处理,我们看一看他是如何处理的。。。
2、顺序消费原来介绍
根据上面的简单介绍我们知道一个topic对应多个队列,我们生产消息的时候就可以针对队列的数量和消息的有效标识进行取模进行队列选择发送,如下示例代码
package org.apache.rocketmq.example.ordermessage; import java.io.UnsupportedEncodingException;
import java.util.List;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.MQProducer;
import org.apache.rocketmq.client.producer.MessageQueueSelector;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.remoting.common.RemotingHelper;
import org.apache.rocketmq.remoting.exception.RemotingException; public class Producer {
public static void main(String[] args) throws UnsupportedEncodingException {
try {
MQProducer producer = new DefaultMQProducer("please_rename_unique_group_name");
producer.start(); String[] tags = new String[] {"TagA", "TagB", "TagC", "TagD", "TagE"};
for (int i = 0; i < 100; i++) {
int orderId = i % 10;
Message msg =
new Message("TopicTestjjj", tags[i % tags.length], "KEY" + i,
("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET));
SendResult sendResult = producer.send(msg, new MessageQueueSelector() {
@Override
public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
Integer id = (Integer) arg;
int index = id % mqs.size();
return mqs.get(index);
}
}, orderId); System.out.printf("%s%n", sendResult);
} producer.shutdown();
} catch (MQClientException | RemotingException | MQBrokerException | InterruptedException e) {
e.printStackTrace();
}
}
}
比如我们使用订单号作为和queue的ID取模的关键字段,我们就可以保证这个订单号的消息都会发送给一个队列,这样我们就保证了生产者生产消息在业务上是有序的
接下来我们看看消费端是怎样实现的。
1、消费者与broker建立连接分配队列的时候会尝试给队列加锁,如果成功则获取queue消费权利,否则尝试下一个queue。
2、如果消费模式为集群每20秒对分配给自己的队列自动加锁
3、消息消费时对queue进行加锁,同一时刻只允许一个线程对一个queue进行消费
4、根据消费时间进行队列和线程的切换默认60s(这个时间就是锁住队列的时间)
5、消息重试次数超过最大次数之后将消息移入死信queue

根据以上几点可以保证一个队列中的消息可以按顺序进行消费。
3、总结
RocketMQ4.0.0对顺序消息做了升级,但是牺牲了部分消费性能。因为要给队列加锁,并且只能一个队列同一时间只能有一个线程处理消息。
至于为什么是60秒(时间可设置)进行线程切换可能是更好的利用cpu或者不因为某个队列消息异常拖慢其他队列消息处理吧,还有待深入研究。
本人理解如有误请广大网友指正,谢谢!
RocketMQ4.3.x对顺序消息的理解的更多相关文章
- RocketMQ入门到入土(二)事务消息&顺序消息
接上一篇:RocketMQ入门到入土(一)新手也能看懂的原理和实战! 一.事务消息的由来 1.案例 引用官方的购物案例: 小明购买一个100元的东西,账户扣款100元的同时需要保证在下游的积分系统给小 ...
- 聊一聊顺序消息(RocketMQ顺序消息的实现机制)
当我们说顺序时,我们在说什么? 日常思维中,顺序大部分情况会和时间关联起来,即时间的先后表示事件的顺序关系. 比如事件A发生在下午3点一刻,而事件B发生在下午4点,那么我们认为事件A发生在事件B之前, ...
- RocketMQ源码 — 十、 RocketMQ顺序消息
RocketMQ本身支持顺序消息,在使用上发送顺序消息和非顺序消息有所区别 发送顺序消息 SendResult sendResult = producer.send(msg, new MessageQ ...
- RocketMQ学习笔记(9)----RocketMQ的Producer 顺序消息
1. 顺序消息原理图 2. 什么是顺序消息? 消费消息的顺序要求同发送消息的顺序一致,在RocketMQ中,主要指的是局部顺序,即一类消息为满足顺序性,必须Producer单线程顺序发送,并且发送给到 ...
- RocketMQ顺序消息
rocketmq的顺序消息需要满足2点: 1.Producer端保证发送消息有序,且发送到同一个队列.2.consumer端保证消费同一个队列. 生产端: RocketMQ可以严格的保证消息有序.但这 ...
- 【mq读书笔记】顺序消息
注意异常情况导致整个消费无限重试 阻塞消费 mq支持局部消息顺序消费,可以确保同一个消息消费队列中的消息被顺序消费.看下针对顺序消息在整个消费过程中做的调整: 队列负载: DefaultMQPushC ...
- junit4X系列源码--Junit4 Runner以及test case执行顺序和源代码理解
原文出处:http://www.cnblogs.com/caoyuanzhanlang/p/3534846.html.感谢作者的无私分享. 前一篇文章我们总体介绍了Junit4的用法以及一些简单的测试 ...
- 20171126-handler消息机制理解
1.handler消息机制的理解 http://www.jianshu.com/p/8343a39b8a2c?s_q_s_h_a_r_e_1MTAzNTIwODAxNTExNTg5NTkwMzE0Nz ...
- 一条sql语句搞定基于mysql的sql执行顺序的基本理解
对数据库基本操作是每个程序员基本功,如何理解并快速记住sql执行的顺序呢,其实一条复杂的sql就能搞定: SELECT DISTINCT <select_list> FROM <le ...
随机推荐
- Sqlserver 事务处理模板
USE StuDB GO /****** Object: StoredProcedure [dbo].[proc_live_send_answer_v4] Script Date: 06/20/201 ...
- Powershell-查询当前文件目录层级结构
日常工作中我们往往有需要导出当前共享环境或磁盘文件目录层级结构等的需求,最早在目录少的情况下我们使用CMD下tree 命令可以很清晰的看到目录.文件层级结构,那么我们又如何通过powershell直观 ...
- Intellij Idea 无法启动项目的配置坑
1. run/debug configuration里面,tomcat的deployment点击添加不能自动创建war-explorded包: 方案:删除project libraries,重新mav ...
- [Abp vNext 源码分析] - 2. 模块系统的变化
一.简要说明 本篇文章主要分析 Abp vNext 当中的模块系统,从类型构造层面上来看,Abp vNext 当中不再只是单纯的通过 AbpModuleManager 来管理其他的模块,它现在则是 I ...
- 【自然语言处理】--视觉问答(Visual Question Answering,VQA)从初始到应用
一.前述 视觉问答(Visual Question Answering,VQA),是一种涉及计算机视觉和自然语言处理的学习任务.这一任务的定义如下: A VQA system takes as inp ...
- 在Linux系统配置Nodejs环境的最简单步骤,部署多个thinkjs(nodejs)项目
发现一台服务器部署管理多个nodejs服务,可以采用二级域名weekly.mwcxs.top,也可以采用固定后缀www.mwcxs.top/weekly的方式,本文先从固定后缀的方式部署管理多个nod ...
- C#反射调用方法实例
下面是两个反射的实例 案例1: 动态调用类中的方法.传入参数,并获得返回值. xxxx:类名 Event:类中的方法 pra1,pra2,pra3:方法对应的入参 DoRet:方法返回的执行结果 Ty ...
- Spring Boot 2.x(十一):AOP实战--打印接口日志
接口日志有啥用 在我们日常的开发过程中,我们可以通过接口日志去查看这个接口的一些详细信息.比如客户端的IP,客户端的类型,响应的时间,请求的类型,请求的接口方法等等,我们可以对这些数据进行统计分析,提 ...
- 服务器linux centos 7.4 搭建ftp服务器
此操作是在腾讯云服务器linux centos 7.4 完成搭建ftp服务器 vsftpd 的: 安装 vsftpd $ yum install vsftpd -y 启动 $ service vsft ...
- sql字符串分割扩展方法
可编程性—表值函数 SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE FUNCTION [dbo].[Split] ( @RowData ...