RocketMQ快速入门

1. MQ简介

1.1 项目工程弊端

在这里插入图片描述

1.2 MQ简介

  1. MQ(Message Queue)消息队列,是一种用来保存消息数据的队列.

    1. 队列:数据结构的一种,特征为 “先进先出”

在这里插入图片描述

  1. 何为消息

    1. 服务器间的业务请求
      1. 原始架构:
        1. 服务器中的A功能需要调用B、C模块才能完成
      2. 微服务架构:
        1. 服务器A向服务器B发送要执行的操作(视为消息)
        2. 服务器A向服务器C发送要执行的操作(视为消息)
  2. 小节:MQ概念

1.3 MQ作用

` 1. 应用解耦

2. 快速应用变更维护
3. 流量削锋

1.4 MQ基本工作模式

应用解耦:(异步消息发送)

在这里插入图片描述
快速应用变更维护:(异步消息发送)
在这里插入图片描述

流量削锋:(异步消息发送)

1.5 MQ优缺点分析

优点(作用):

  1. 应用解耦
  2. 快速应用变更维护
  3. 流量削锋

缺点:

1. 系统可用性降低
2. 系统复杂度提高
3. 异步消息机制
  	1. 消息顺序性
  	2. 消息丢失
  	3. 消息一致性
  	4. 消息重复使用

在这里插入图片描述

1.6 MQ产品介绍

  1. ActiveMQ
    1. java语言实现,万级数据吞吐量,处理速度ms级,主从架构,成熟度高
  2. RabbitMQ
    1. erlang语言实现,万级数据吞吐量,处理速度us级,主从架构,
  3. RocketMQ
    1. java语言实现,十万级数据吞吐量,处理速度ms级,分布式架构,功能强大,扩展性强
  4. kafka
    1. scala语言实现,十万级数据吞吐量,处理速度ms级,分布式架构,功能较少,应用于大数据较多

RocketMQ

  1. RocketMQ是阿里开源的一款非常优秀中间件产品,脱胎于阿里的另一款队列技术MetaQ,后捐赠给Apache基金会 作为一款孵化技术,仅仅经历了一年多的时间就成为Apache基金会的顶级项目。并且它现在已经在阿里内部被广泛 的应用,并且经受住了多次双十一的这种极致场景的压力(2017年的双十一,RocketMQ流转的消息量达到了万亿 级,峰值TPS达到5600万)

在这里插入图片描述

  1. 解决所有缺点

幂等性:就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。举个最简单的例子,那就是支付,用户购买商品后支付,支付扣款成功,但是返回结果的时候网络异常,此时钱已经扣了,用户再次点击按钮,此时会进行第二次扣款,返回结果成功,用户查询余额发现多扣钱了,流水记录也变成了两条。在以前的单应用系统中,我们只需要把数据操作放入事务中即可,发生错误立即回滚,但是再响应客户端的时候也有可能出现网络中断或者异常等等。

在增删改查4个操作中,尤为注意就是增加或者修改,查询对于结果是不会有改变的,删除只会进行一次,用户多次点击产生的结果一样,修改在大多场景下结果一样,增加在重复提交的场景下会出现。

2. 环境搭建

在这里插入图片描述

2.1 基础概念

在这里插入图片描述

在这里插入图片描述

两边生产者消费者都会去找命名服务器,之后找到broke,信息生产者会推送消息,消费者会拉取监听器监听队列之后消费消息.

  1. 生产者
  2. 消费者
  3. 消息服务器
  4. 命名服务器
  5. 消息
    1. 主题
    2. 标签
  6. 心跳
  7. 监听器
  8. 拉取消费、推动消费
  9. 注册

2.2 安装

  1. 命名服务器
  2. 消息服务器

2.3 下载

⚫ https://www.apache.org/

2.4 安装过程

  1. 步骤1:安装JDK(1.8)

  2. 步骤2:上传压缩包(zip)

   yum -y install lrzsz 
  rz
  1. 步骤3:解压缩
  unzip rocketmq-all-4.5.2-bin-release.zip
  1. 步骤4:修改目录名称
   mv rocketmq-all-4.5.2-bin-release rocketmq

2.5 启动服务器

  1. 步骤1:启动命名服务器(bin目录下)
   sh mqnamesrv
  1. 步骤2:启动消息服务器(bin目录下)
   sh mqbroker -n localhost:9876

修改runbroker.sh文件中有关内存的配置(调整的与当前虚拟机内存匹配即可,推荐256m-128m)

2.6 测试服务器环境

  1. 步骤1:配置命名服务器地址
   export NAMESRV_ADDR=localhost:9876
  1. 步骤2:启动生产者程序客户端(bin目录下)
   sh tools.sh org.apache.rocketmq.example.quickstart.Producer

启动后产生大量日志信息(注意该信息是测试程序中自带的,不具有通用性,仅供学习查阅参考)

  1. 步骤3:启动消费者程序客户端(bin目录下)
   sh tools.sh org.apache.rocketmq.example.quickstart.Consumer

启动后产生大量日志信息

3. 消息发送(重点)

3.1 主要内容和相关概念

3.1.1 Topic

首先看看官方的定义:

Topic是生产者在发送消息和消费者在拉取消息的类别相当于操作类型。Topic与生产者和消费者之间的关系非常松散。具体来说,一个Topic可能有0个,一个或多个生产者向它发送消息;相反,一个生产者可以发送不同类型Topic的消息。类似的,消费者组可以订阅一个或多个主题,只要该组的实例保持其订阅一致即可。

Topic在Google翻译中解释为话题。我们可以理解为第一级消息类型,类比于书的标题。在应用系统中,一个Topic标识为一类消息类型,比如交易信息。

在Producer中使用Topic:

Message msg = new Message(“TopicTest” /* Topic */,“TagA”,("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET));
在Consumer中订阅Topic:

consumer.subscribe(“TopicTest”, “*”);

3.1.2 Tag

同样,先看看官方怎么定义的:

标签,换句话的意思就是子主题,为用户提供了额外的灵活性。有了标签,来自同一业务模块的具有不同目的的消息可以具有相同的主题和不同的标记。标签有助于保持代码的清晰和连贯,同时标签也方便RocketMQ提供的查询功能。

Tag在Google翻译中解释为标签。我们可以理解为第二级消息类型,类比于书的目录,方便检索使用消息。在应用系统中,一个Tag标识为一类消息中的二级分类,比如交易信息下的交易创建、交易完成。

在Producer中使用Tag:

Message msg = new Message(“TopicTest”,“TagA” /* Tag */,
("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET));
在Consumer中订阅Tag:

consumer.subscribe(“TopicTest”, “TagA||TagB”);// * 代表订阅Topic下的所有消息

3.1.3 GroupName

和现实世界中一样,RocketMQ中也有组的概念。代表具有相同角色的生产者组合或消费者组合,称为生产者组或消费者组。

作用是在集群HA的情况下,一个生产者down之后,本地事务回滚后,可以继续联系该组下的另外一个生产者实例,不至于导致业务走不下去。在消费者组中,可以实现消息消费的负载均衡和消息容错目标。

另外,有了GroupName,在集群下,动态扩展容量很方便。只需要在新加的机器中,配置相同的GroupName。启动后,就立即能加入到所在的群组中,参与消息生产或消费。

在Producer中使用GroupName:

DefaultMQProducer producer = new DefaultMQProducer(“group_name_1”);// 使用GroupName来初始化Producer,如果不指定,就会使用默认的名字:DEFAULT_PRODUCER
在Consumer中使用GroupName:

DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(“group_name_1”);// 使用GroupName来初始化Consumer,如果不指定,就会使用默认的名字:DEFAULT_CONSUMER

  1. 基于Java环境构建消息发送与消息接收基础程序
    1. 单生产者单消费者
    2. 单生产者多消费者
    3. 多生产者多消费者
  2. 发送不同类型的消息
    1. 同步消息
    2. 异步消息
    3. 单向消息
  3. 特殊的消息发送
    1. 延时消息
    2. 批量消息
  4. 特殊的消息接收
    1. 消息过滤
  5. 消息发送与接收顺序控制
  6. 事务消息

在这里插入图片描述

3.2 消息发送与接收开发流程

  1. 谁来发?
  2. 发给谁?
  3. 怎么发?
  4. 发什么?
  5. 发的结果是什么?
  6. 打扫战场

3.3 单生产者单消费者消息发送(OneToOne)

在这里插入图片描述
在这里插入图片描述

  1. 导入RocketMQ客户端坐标
  <dependency>
      <groupId>org.apache.rocketmq</groupId>
      <artifactId>rocketmq-client</artifactId>
      <version>4.5.2</version>
  </dependency>

3.4 单生产者单消费者消息发送(OneToOne)

  1. 生产者
   //1.创建一个发送消息的对象Producer
   DefaultMQProducer producer = new DefaultMQProducer("group1");
   //2.设定发送的命名服务器地址
   producer.setNamesrvAddr("192.168.184.128:9876");
   //3.1启动发送的服务
   producer.start();
   //4.创建要发送的消息对象,指定topic,指定内容body
   Message msg = new Message("topic1","hello rocketmq".getBytes("UTF-8"));
   //3.2发送消息
   SendResult result = producer.send(msg);
   System.out.println("返回结果:"+result);
   //5.关闭连接
   producer.shutdown();
   返回结果:SendResult [
   sendStatus=SEND_OK, 
   msgId=C0A80F291A1018B4AAC268E060E00000, offsetMsgId=C0A8410100002A9F000000000005E699, 
   messageQueue=MessageQueue [topic=topic1, brokerName=WIN-P2JLR6AM32M, queueId=3], queueOffset=7]
  1. 注意:关闭服务器防火墙
   systemctl stop firewalld.service 

3.5 单生产者单消费者消息发送(OneToOne)

  1. 消费者
   //1.创建一个接收消息的对象Consumer
   DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("group1");
   //2.设定接收的命名服务器地址
   consumer.setNamesrvAddr("192.168.184.128:9876");
   //3.设置接收消息对应的topic,对应的sub标签为任意*
   consumer.subscribe("topic1","*");
   //3.开启监听,用于接收消息
   consumer.registerMessageListener(new MessageListenerConcurrently() {
   public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list,
   ConsumeConcurrentlyContext consumeConcurrentlyContext) {
   //接收结果是一个集合
   for(MessageExt msg : list){
   System.out.println("消息:"+new String(msg.getBody()));
   }
   return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
   }});
   //4.启动接收消息的服务
   consumer.start();
接收结果:消息:MessageExt [queueId=3, storeSize=163, queueOffset=5, sysFlag=0, bornTimestamp=1608470799151, bornHost=/192.168.65.1:58055, storeTimestamp=1608470799152, storeHost=/192.168.65.1:10911, msgId=C0A8410100002A9F000000000005E103, commitLogOffset=385283, bodyCRC=1932557065, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='topic1', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=8, CONSUME_START_TIME=1608511664435, UNIQ_KEY=C0A80F29350C18B4AAC26672CB2F0006, WAIT=true}, body=[104, 101, 108, 108, 111, 32, 114, 111, 99, 107, 101, 116, 109, 113], transactionId='null'}]

3.6 单生产者多消费者消息发送(OneToMany)

  1. 消费者(负载均衡模式:默认模式)
  DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("group1");
  consumer.setNamesrvAddr("192.168.184.128:9876");
  consumer.subscribe("topic1","*");
  //设置当前消费者的消费模式(默认模式:负载均衡)
  consumer.setMessageModel(MessageModel.CLUSTERING);
  consumer.registerMessageListener(new MessageListenerConcurrently() {
  public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list,
  ConsumeConcurrentlyContext consumeConcurrentlyContext) {
  for(MessageExt msg : list){
  System.out.println("消息:"+new String(msg.getBody()));
  }
  return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
  }
  });
  //4.启动接收消息的服务
  consumer.start();

3.7 单生产者多消费者消息发送(OneToMany)

  1. 消费者(广播模式)
   DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("group1");
   consumer.setNamesrvAddr("192.168.184.128:9876");
   consumer.subscribe("topic1","*");
   //设置当前消费者的消费模式为广播模式:所有客户端接收的消息都是一样的
   consumer.setMessageModel(MessageModel.BROADCASTING);
   consumer.registerMessageListener(new MessageListenerConcurrently() {
   public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list,
   ConsumeConcurrentlyContext consumeConcurrentlyContext) {
   for(MessageExt msg : list){
   System.out.println("消息:"+new String(msg.getBody()));
   }
   return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
   }
   });
   //4.启动接收消息的服务
   consumer.start();

3.8 多生产者多消费者消息发送(ManyToMany)

  1. 多生产者产生的消息可以被同一个消费者消费,也可以被多个消费者消费

3.9 小节

  1. 消息发送
    1. One-To-One(基础发送与基础接收)
    2. One-To-Many(负载均衡模式与广播模式)
    3. Many-To-Many
      在这里插入图片描述

3.10 消息类别

  1. 同步消息
  2. 异步消息
  3. 单向消息

3.11 同步消息

特征:即时性较强,重要的消息,且必须有回执的消息,例如短信,通知(转账成功)

在这里插入图片描述

3.12 异步消息

特征:即时性较弱,但需要有回执的消息,例如订单中的某些信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dLNGDHtx-1608424332896)(img/image-20201211154108518.png)]

3.13 单向消息

特征:不需要有回执的消息,例如日志类消息

在这里插入图片描述

3.14 单向消息

  1. 同步消息
   SendResult result = producer.send(msg);
  1. 异步消息(回调处理结果必须在生产者进程结束前执行,否则回调无法正确执行)
  producer.send(msg, new SendCallback() {
  //表示成功返回结果
  public void onSuccess(SendResult sendResult) {
  System.out.println(sendResult);
  }
  //表示发送消息失败
  public void onException(Throwable t) {
  System.out.println(t);
  }
  });
  1. 单向消息
   producer.sendOneway(msg);

3.15 延时消息

  1. 消息发送时并不直接发送到消息服务器,而是根据设定的等待时间到达,起到延时到达的缓冲作用
   Message msg = new Message("topic3",("延时消息:hello rocketmq "+i).getBytes("UTF-8"));
   //设置当前消息的延时效果
   msg.setDelayTimeLevel(3);
   SendResult result = producer.send(msg);
   System.out.println("返回结果:"+result);
  1. 目前支持的消息时间

    1. 秒级:1,5,10,30
    2. 分级:1~10,20,30
    3. 时级:1,2
    4. 1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h

3.16 批量消息

  1. 发送批量消息
   List<Message> msgList = new ArrayList<Message>();
   SendResult send = producer.send(msgList);
  1. 消息内容总长度不超过4M

  2. 消息内容总长度包含如下:

    1. topic(字符串字节数)
    2. body (字节数组长度)
    3. 消息追加的属性(key与value对应字符串字节数)
    4. 日志(固定20字节)

3.17 消息过滤

  1. 分类过滤

    1. 生产者
      Message msg = new Message("topic6","tag2",("消息过滤按照tag:hello rocketmq 2" 标题 Tag ).getBytes("UTF-8"));
  1. 消费者
      //接收消息的时候,除了制定topic,还可以指定接收的tag,*代表任意tag
      consumer.subscribe("topic6","tag1 || tag2");
  1. 语法过滤(属性过滤/语法过滤/SQL过滤)

    1. 生产者
     //为消息添加属性
     msg.putUserProperty("vip","1");
     msg.putUserProperty("age","20");
  1. 消费者
     //使用消息选择器来过滤对应的属性,语法格式为类SQL语法
     consumer.subscribe("topic7", MessageSelector.bySql("age >= 18"));
  1. 注意:SQL过滤需要依赖服务器的功能支持,在broker配置文件中添加对应的功能项,并开启对应功能
      enablePropertyFilter=true
  1. 启动服务器使启用对应配置文件
      sh mqbroker -n localhost:9876 -c ../conf/broker.conf

3.18 错乱的消息顺序

在这里插入图片描述
在这里插入图片描述

3.19 顺序消息

在这里插入图片描述
在这里插入图片描述

  1. 发送消息
   //设置消息进入到指定的消息队列中
   for(final Order order : orderList){
   Message msg = new Message("orderTopic",order.toString().getBytes());
   //发送时要指定对应的消息队列选择器
   SendResult result = producer.send(msg, new MessageQueueSelector() {
   //设置当前消息发送时使用哪一个消息队列
   public MessageQueue select(List<MessageQueue> list, Message message, Object o) {
   //根据发送的信息不同,选择不同的消息队列
   //根据id来选择一个消息队列的对象,并返回->id得到int值
   int mqIndex = order.getId().hashCode() % list.size();
   return list.get(mqIndex);
   }
   }, null);
   System.out.println(result);
   }

3.20 顺序消息

  1. 接收消息
   //使用单线程的模式从消息队列中取数据,一个线程绑定一个消息队列
   consumer.registerMessageListener(new MessageListenerOrderly() {
   //使用MessageListenerOrderly接口后,对消息队列的处理由一个消息队列多个线程服务
   / /,转化为一个消息队列一个线程服务
   public ConsumeOrderlyStatus consumeMessage(List<MessageExt> list, ConsumeOrderlyContext
   consumeOrderlyContext) {
   for(MessageExt msg : list){
   System.out.println("消息:"+new String(msg.getBody()));
   }
   return ConsumeOrderlyStatus.SUCCESS;
   }
   });

3.21 事务消息

  1. 正常事务过程
  2. 事务补偿过程

在这里插入图片描述
在这里插入图片描述

3.22 事务消息状态

  1. 提交状态:允许进入队列,此消息与非事务消息无区别
  2. 回滚状态:不允许进入队列,此消息等同于未发送过
  3. 中间状态:完成了half消息的发送,未对MQ进行二次状态确认
  4. 注意:事务消息仅与生产者有关,与消费者无关

3.23 事务消息

//事务消息使用的生产者是TransactionMQProducer
TransactionMQProducer producer = new TransactionMQProducer("group1");
producer.setNamesrvAddr("192.168.184.128:9876");
//添加本地事务对应的监听
producer.setTransactionListener(new TransactionListener() {
//正常事务过程
public LocalTransactionState executeLocalTransaction(Message message, Object o) {
return LocalTransactionState.COMMIT_MESSAGE;
}
//事务补偿过程
public LocalTransactionState checkLocalTransaction(MessageExt messageExt) {
return null;
}
});
producer.start();
Message msg = new Message("topic8",("事务消息:hello rocketmq ").getBytes("UTF-8"));
SendResult result = producer.sendMessageInTransaction(msg,null);
System.out.println("返回结果:"+result);
producer.shutdown();
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
一、rocketmq入门到精通视频教程目录大纲 001-001_RocketMQ_简介 002-002_RocketMQ_核心概念详解 003-003_RocketMQ_集群构建模型详解(一) 004-004_RocketMQ_集群构建模型详解(二) 005-005_RocketMQ_双主模式集群环境搭建 006-006_RocketMQ_控制台使用讲解 007-007_RocketMQ_Broker配置文件详解 008-008_RocketMQ_helloworld示例讲解 009-009_RocketMQ_整体架构概述详解 010-010_RocketMQ_Producer_API详解 011-011_RocketMQ_Producer_顺序消费机制详解 012-012_RocketMQ_Producer_事务消息机制详解 013-013_RocketMQ_Consumer_Push和Pull模式及使用详解 014-014_RocketMQ_Consumer_配置参数详解 015-015_RocketMQ_Consumer_重试策略详解 016-016_RocketMQ_Consumer_幂等去重策略详解 017-017_RocketMQ_消息模式及使用讲解 018-018_RocketMQ_双主双从集群环境搭建与使用详解 019-019_RocketMQ_FilterServer机制及使用详解 020-020_RocketMQ_管理员命令 二、rocketmq实战视频教程目录大纲 01_rocketmq_实战项目介绍 02_rocketMQ实战项目设计(一) 03_rocketMQ实战项目设计(二) 04_rocketMQ实战-环境搭建(一) 05_rocketMQ实战-环境搭建(二) 06_rocketMQ实战-生产者与spring结合 07_rocketMQ实战-消费者与spring结合 08_rocketMQ实战-数据库模型设计 09_rocketMQ实战-数据库DAO代码生成 10_rocketMQ实战-远程RPC接口设计与实现(一) 11_rocketMQ实战-远程RPC接口设计与实现(二) 12_rocketMQ实战-远程RPC接口设计与实现(三) 13_rocketMQ实战-下单流程(一) 14_rocketMQ实战-下单流程(二) 15_rocketMQ实战-下单流程(三) 16_rocketMQ实战-下单流程(四) 17_rocketMQ实战-下单流程(五) 18_rocketMQ实战-下单流程(六) 19_rocketMQ实战-下单流程(七) 20_rocketMQ实战-下单流程(八)-商品库存 21_rocketMQ实战-下单流程(九)-商品库存 22_rocketMQ实战-下单流程(十)-支付模块 23_rocketMQ实战-整体联调

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赵广陆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值