RocketMQ学习笔记

目录

  • 前言
  • 1 RocketMQ概述
    • 1.1 MQ概述
      • 1.1.1 MQ简介
      • 1.1.2 MQ用途
      • 1.1.3 常见MQ产品
      • 1.1.4 MQ常见协议
  • 1.2 RocketMQ概述
    • 1.2.1 简介
      • 1.2.2 RocketMQ发展历程
  • 2 RocketMQ的安装与启动
    • 2.1 基本概念
      • 2.1.1 消息(Message)
      • 2.1.2 主题(Topic)
      • 2.1.3 标签(Tag)
      • 2.1.4 队列(Queue)
      • 2.1.5 消息标识(MessageId/Key)
    • 2.2 系统架构
      • 2.2.1 Producer
      • 2.2.2 Consumer
      • 2.2.3 Name Server
      • 2.2.4 Broker
      • 2.2.5 工作流程
    • 2.3 单机安装与启动
      • 2.3.1 准备工作
      • 2.3.2 修改初始内存
      • 2.3.3 启动
      • 2.3.4 发送/接收消息测试
      • 2.3.5 关闭server
    • 2.4 控制台的安装与启动
      • 2.4.1 下载
      • 2.4.2 修改配置
      • 2.4.3 添加依赖
      • 2.4.4 打包
      • 2.4.5 启动
      • 2.4.6 访问
    • 2.5 集群搭建理论
      • 2.5.1 数据复制与刷盘策略
      • 2.5.2 Broker集群模式
    • 2.6 磁盘阵列RAID
      • 2.6.1 RAID历史
      • 2.6.2 RAID等级
      • 2.6.3 关键技术
      • 2.6.4 RAID分类
      • 2.6.5 常见RAID等级详解
    • 2.7 集群搭建实践
    • 2.8 mqadmin命令
      • 2.8.1 修改bin/tools.sh
      • 2.8.2 运行mqadmin
      • 2.8.3 该命令的官网详解
  • 3 RocketMQ工作原理
    • 3.1 消息的生产
      • 3.1.1 消息的生产过程
      • 3.3.2 Queue选择算法
    • 3.2 消息的存储
      • 3.2.1 commitlog文件
      • 3.2.2 consumequeue
      • 3.3.3 对文件的读写
      • 3.3.4 与Kafka的对比
    • 3.3 indexFile
      • 3.3.1 索引条目结构
      • 3.3.2 indexFile的创建
      • 3.3.3 查询流程
    • 3.4 消息的消费
      • 3.4.1 获取消费类型
      • 3.4.2 消费模式
      • 3.4.3 Rebalance机制
      • 3.4.4 Queue分配算法
      • 3.4.5 至少一次原则
    • 3.5 订阅关系的一致性
      • 3.5.1 正确订阅关系
      • 3.5.2 错误订阅关系
    • 3.6 offset管理
      • 3.6.1 offset本地管理模式
      • 3.6.2 offset远程管理模式
      • 3.6.3 offset用途
      • 3.6.4 重试队列
      • 3.6.5 offset的同步提交与异步提交
    • 3.7 消费幂等
      • 3.7.1 什么是消费幂等
      • 3.7.2 消息重复的场景分析
      • 3.7.3 通用解决方案
      • 3.7.4 消费幂等的实现
    • 3.8 消息堆积与消费延迟
      • 3.8.1 概念
      • 3.8.2 产生原因分析
      • 3.8.3 消费耗时
      • 3.8.4 消费并发度
      • 3.8.5 单机线程数计算
      • 3.8.6 如何避免
    • 3.9 消息的清理
  • 4 RocketMQ应用
    • 4.1 普通消息
      • 4.1.1 消息发送分类
      • 4.1.2 代码举例
    • 4.2 顺序消息
      • 4.2.1 什么是顺序消息
      • 4.2.2 为什么需要顺序消息
      • 4.2.3 有序性分类
      • 4.2.4 代码举例
    • 4.3 延时消息
      • 4.3.1 什么是延时消息
      • 4.3.2 延时等级
      • 4.3.3 延时消息实现原理
      • 4.3.4 代码举例
    • 4.4 事务消息
      • 4.4.1 问题引入
      • 4.4.2 解决思路
      • 4.4.3 基础知识
      • 4.4.4 XA模式三剑客
      • 4.4.5 XA模式架构
      • 4.4.6 注意
      • 4.4.7 代码举例
    • 4.5 批量消息
      • 4.5.1 批量发送消息
      • 4.5.2 批量消费消息
      • 4.5.3 代码举例
    • 4.6 消息过滤
      • 4.6.1 Tag过滤
      • 4.6.2 SQL过滤
      • 4.6.3 代码举例
    • 4.7 消息发送重试机制
      • 4.7.1 说明
      • 4.7.2 同步发送失败策略
      • 4.7.3 异步发送失败策略
      • 4.7.4 消息刷盘失败策略
    • 4.8 消息消费重试机制
      • 4.8.1 顺序消息的消费重试
      • 4.8.2 无序消息的消费重试
      • 4.8.3 消费重试次数间隔
      • 4.8.4 重试队列
      • 4.8.5 消费重试配置方式
      • 4.8.6 消费不重试配置方式
    • 4.9 死信队列
      • 4.9.1 什么是死信队列
      • 4.9.2 死信队列的特征
      • 4.9.3 死信消息的处理
  • 后记

前言

跟随尚硅谷雷老师的讲解,迈入RocketMQ的学习中。

1 RocketMQ概述

1.1 MQ概述

1.1.1 MQ简介

MQ,Message Queue,是一种提供消息队列服务的中间件,也称为消息中间件,是一套提供了消息生产、存储、消费全过程API的软件系统。消息即数据。一般消息的体量不会很大。

1.1.2 MQ用途

从网上可以查看到很多的关于MQ用途的叙述,但总结起来其实就以下三点。
RocketMQ学习笔记_第1张图片

异步解耦
RocketMQ学习笔记_第2张图片
数据收集
分布式系统会产生海量级数据流,如:业务日志、监控数据、用户行为等。针对这些数据流进行实时或批量采集汇总,然后对这些数据流进行大数据分析,这是当前互联网平台的必备技术。通过MQ完成此类数据收集是最好的选择。

1.1.3 常见MQ产品

RocketMQ学习笔记_第3张图片
RocketMQ学习笔记_第4张图片

1.1.4 MQ常见协议

一般情况下MQ的实现是要遵循一些常规性协议的。常见的协议如下:
JMS
JMS,Java Messaging Service(Java消息服务)。是Java平台上有关MOM(Message OrientedMiddleware,面向消息的中间件 PO/OO/AO)的技术规范,它便于消息系统中的Java应用程序进行消息交换,并且通过提供标准的产生、发送、接收消息的接口,简化企业应用的开发。ActiveMQ是该协议的典型实现。

STOMP
STOMP,Streaming Text Orientated Message Protocol(面向流文本的消息协议),是一种MOM设计的简单文本协议。STOMP提供一个可互操作的连接格式,允许客户端与任意STOMP消息代理(Broker)进行交互。ActiveMQ是该协议的典型实现,RabbitMQ通过插件可以支持该协议。

AMQP
AMQP,Advanced Message Queuing Protocol(高级消息队列协议),一个提供统一消息服务的应用层标准,是应用层协议的一个开放标准,是一种MOM设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同开发语言等条件的限制。 RabbitMQ是该协议的典型实现。

MQTT
MQTT,Message Queuing Telemetry Transport(消息队列遥测传输),是IBM开发的一个即时通讯协议,是一种二进制协议,主要用于服务器和低功耗IoT(物联网)设备间的通信。该协议支持所有平台,几乎可以把所有联网物品和外部连接起来,被用来当做传感器和致动器的通信协议。 RabbitMQ通过插件可以支持该协议。

1.2 RocketMQ概述

1.2.1 简介

RocketMQ学习笔记_第5张图片

1.2.2 RocketMQ发展历程

RocketMQ学习笔记_第6张图片
RocketMQ学习笔记_第7张图片

2 RocketMQ的安装与启动

2.1 基本概念

2.1.1 消息(Message)

消息是指,消息系统所传输信息的物理载体,生产和消费数据的最小单位,每条消息必须属于一个主题。

2.1.2 主题(Topic)

在这里插入图片描述

Topic表示一类消息的集合,每个主题包含若干条消息,每条消息只能属于一个主题,是RocketMQ进行消息订阅的基本单位。 topic:message 1:n message:topic 1:1。
一个生产者可以同时发送多种Topic的消息;而一个消费者只对某种特定的Topic感兴趣,即只可以订阅和消费一种Topic的消息。 producer:topic 1:n consumer:topic 1:1。

2.1.3 标签(Tag)

为消息设置的标签,用于同一主题下区分不同类型的消息。来自同一业务单元的消息,可以根据不同业务目的在同一主题下设置不同标签。标签能够有效地保持代码的清晰度和连贯性,并优化RocketMQ提供的查询系统。消费者可以根据Tag实现对不同子主题的不同消费逻辑,实现更好的扩展性。
Topic是消息的一级分类,Tag是消息的二级分类。
RocketMQ学习笔记_第8张图片
RocketMQ学习笔记_第9张图片

2.1.4 队列(Queue)

存储消息的物理实体。一个Topic中可以包含多个Queue,每个Queue中存放的就是该Topic的消息。一个Topic的Queue也被称为一个Topic中消息的分区(Partition)。
一个Topic的Queue中的消息只能被一个消费者组中的一个消费者消费。一个Queue中的消息不允许同一个消费者组中的多个消费者同时费。
RocketMQ学习笔记_第10张图片
在学习参考其它相关资料时,还会看到一个概念:分片(Sharding)。分片不同于分区。在RocketMQ中,分片指的是存放相应Topic的Broker。每个分片中会创建出相应数量的分区,即Queue,每个Queue的大小都是相同的。
RocketMQ学习笔记_第11张图片

2.1.5 消息标识(MessageId/Key)

RocketMQ学习笔记_第12张图片

2.2 系统架构

RocketMQ学习笔记_第13张图片

2.2.1 Producer

RocketMQ学习笔记_第14张图片

2.2.2 Consumer

RocketMQ学习笔记_第15张图片
RocketMQ学习笔记_第16张图片
RocketMQ学习笔记_第17张图片

2.2.3 Name Server

RocketMQ学习笔记_第18张图片
RocketMQ学习笔记_第19张图片
RocketMQ学习笔记_第20张图片
RocketMQ学习笔记_第21张图片
RocketMQ学习笔记_第22张图片

2.2.4 Broker

RocketMQ学习笔记_第23张图片
RocketMQ学习笔记_第24张图片
RocketMQ学习笔记_第25张图片
RocketMQ学习笔记_第26张图片

2.2.5 工作流程

RocketMQ学习笔记_第27张图片
RocketMQ学习笔记_第28张图片
RocketMQ学习笔记_第29张图片

2.3 单机安装与启动

2.3.1 准备工作

RocketMQ学习笔记_第30张图片

RocketMQ学习笔记_第31张图片
RocketMQ学习笔记_第32张图片
为保证和课程一致性,本次下载使用4.9.0版本。
RocketMQ学习笔记_第33张图片
在这里插入图片描述

RocketMQ学习笔记_第34张图片

2.3.2 修改初始内存

修改runserver.sh
使用vim命令打开bin/runserver.sh文件。现将这些值修改为如下:
RocketMQ学习笔记_第35张图片
RocketMQ学习笔记_第36张图片

2.3.3 启动

RocketMQ学习笔记_第37张图片
启动server

  > nohup sh bin/mqnamesrv &
  > tail -f ~/logs/rocketmqlogs/namesrv.log
  The Name Server boot success...

RocketMQ学习笔记_第38张图片

启动broker

  > nohup sh bin/mqbroker -n localhost:9876 &
  > tail -f ~/logs/rocketmqlogs/broker.log 
  The broker[%s, 172.30.30.233:10911] boot success...

RocketMQ学习笔记_第39张图片

2.3.4 发送/接收消息测试

发送消息

export NAMESRV_ADDR=localhost:9876
sh bin/tools.sh org.apache.rocketmq.example.quickstart.Producer

接收消息

sh bin/tools.sh org.apache.rocketmq.example.1 quickstart.Consumer

2.3.5 关闭server

无论是关闭name server还是broker,都是使用bin/mqshutdown命令。

[root@mqOS rocketmq]# sh bin/mqshutdown broker
The mqbroker(1740) is running...
Send shutdown request to mqbroker(1740) OK
[root@mqOS rocketmq]# sh bin/mqshutdown namesrv
The mqnamesrv(1692) is running...
Send shutdown request to mqnamesrv(1692) OK
[2]+ 退出 143 nohup sh bin/mqbroker -n localhost:98

2.4 控制台的安装与启动

RocketMQ有一个可视化的dashboard,通过该控制台可以直观的查看到很多数据。

2.4.1 下载

console项目取消了,从这里下载最新的。https://github.com/apache/rocketmq-dashboard
RocketMQ学习笔记_第40张图片

2.4.2 修改配置

RocketMQ学习笔记_第41张图片
RocketMQ学习笔记_第42张图片
注意上面的namesrvAddr地址如果没有配置映射的话,需要写ip地址。

2.4.3 添加依赖

在这里插入图片描述

		
				javax.xml.bind
				jaxb-api
				2.3.0
		
		
				com.sun.xml.bind
				jaxb-impl
				2.3.0
		
		
				com.sun.xml.bind
				jaxb-core
				2.3.0
		
		
				javax.activation
				activation
				1.1.1
		

2.4.4 打包

RocketMQ学习笔记_第43张图片

mvn clean package -Dmaven.test.skip=true

RocketMQ学习笔记_第44张图片

2.4.5 启动

RocketMQ学习笔记_第45张图片

2.4.6 访问

RocketMQ学习笔记_第46张图片

2.5 集群搭建理论

RocketMQ学习笔记_第47张图片

2.5.1 数据复制与刷盘策略

RocketMQ学习笔记_第48张图片
RocketMQ学习笔记_第49张图片

2.5.2 Broker集群模式

RocketMQ学习笔记_第50张图片
RocketMQ学习笔记_第51张图片
RocketMQ学习笔记_第52张图片

2.6 磁盘阵列RAID

2.6.1 RAID历史

RocketMQ学习笔记_第53张图片

2.6.2 RAID等级

RocketMQ学习笔记_第54张图片
在这里插入图片描述

2.6.3 关键技术

RocketMQ学习笔记_第55张图片
在这里插入图片描述

2.6.4 RAID分类

RocketMQ学习笔记_第56张图片
RocketMQ学习笔记_第57张图片

2.6.5 常见RAID等级详解

RocketMQ学习笔记_第58张图片
RocketMQ学习笔记_第59张图片
RocketMQ学习笔记_第60张图片
RocketMQ学习笔记_第61张图片
RocketMQ学习笔记_第62张图片
RocketMQ学习笔记_第63张图片
RocketMQ学习笔记_第64张图片

2.7 集群搭建实践

RocketMQ学习笔记_第65张图片
RocketMQ学习笔记_第66张图片

# 指定整个broker集群的名称,或者说是RocketMQ集群的名称
brokerClusterName=DefaultCluster
# 指定master-slave集群的名称。一个RocketMQ集群可以包含多个master-slave集群
brokerName=broker-a
# master的brokerId为0
brokerId=0
# 指定删除消息存储过期文件的时间为凌晨4点
deleteWhen=04
# 指定未发生更新的消息存储文件的保留时长为48小时,48小时后过期,将会被删除
fileReservedTime=48
# 指定当前broker为异步复制master
brokerRole=ASYNC_MASTER
# 指定刷盘策略为异步刷盘
flushDiskType=ASYNC_FLUSH
# 指定Name Server的地址
namesrvAddr=192.168.119.150:9876;192.168.119.160:9876

修改broker-b-s.properties
将该配置文件内容修改为如下:

brokerClusterName=DefaultCluster
# 指定这是另外一个master-slave集群
brokerName=broker-b
# slave的brokerId为非0
brokerId=1
deleteWhen=04
fileReservedTime=48
# 指定当前broker为slave
brokerRole=SLAVE
flushDiskType=ASYNC_FLUSH
namesrvAddr=192.168.119.150:9876;192.168.119.160:9876
# 指定Broker对外提供服务的端口,即Broker与producer与consumer通信的端口。默认
10911。由于当前主机同时充当着master1与slave2,而前面的master1使用的是默认端口。这
里需要将这两个端口加以区分,以区分出master1与slave2
listenPort=11911
# 指定消息存储相关的路径。默认路径为~/store目录。由于当前主机同时充当着master1与
slave2,master1使用的是默认路径,这里就需要再指定一个不同路径
storePathRootDir=~/store-s
storePathCommitLog=~/store-s/commitlog
storePathConsumeQueue=~/store-s/consumequeue
storePathIndex=~/store-s/index
storeCheckpoint=~/store-s/checkpoint
abortFile=~/store-s/abort

其他配置
除了以上配置外,这些配置文件中还可以设置其它属性。

#指定整个broker集群的名称,或者说是RocketMQ集群的名称
brokerClusterName=rocket-MS
#指定master-slave集群的名称。一个RocketMQ集群可以包含多个master-slave集群
brokerName=broker-a
#0 表示 Master,>0 表示 Slave
brokerId=0
#nameServer地址,分号分割
namesrvAddr=nameserver1:9876;nameserver2:9876
#默认为新建Topic所创建的队列数
defaultTopicQueueNums=4
#是否允许 Broker 自动创建Topic,建议生产环境中关闭
autoCreateTopicEnable=true
#是否允许 Broker 自动创建订阅组,建议生产环境中关闭
autoCreateSubscriptionGroup=true
#Broker对外提供服务的端口,即Broker与producer与consumer通信的端口
listenPort=10911
#HA高可用监听端口,即Master与Slave间通信的端口,默认值为listenPort+1
haListenPort=10912
#指定删除消息存储过期文件的时间为凌晨4点
deleteWhen=04
#指定未发生更新的消息存储文件的保留时长为48小时,48小时后过期,将会被删除
fileReservedTime=48
#指定commitLog目录中每个文件的大小,默认1G
mapedFileSizeCommitLog=1073741824
#指定ConsumeQueue的每个Topic的每个Queue文件中可以存放的消息数量,默认30w条
mapedFileSizeConsumeQueue=300000
#在清除过期文件时,如果该文件被其他线程所占用(引用数大于0,比如读取消息),此时会阻止
#此次删除任务,同时在第一次试图删除该文件时记录当前时间戳。该属性则表示从第一次拒绝删除
#后开始计时,该文件最多可以保留的时长。在此时间内若引用数仍不为0,则删除仍会被拒绝。不过
#时间到后,文件将被强制删除
destroyMapedFileIntervalForcibly=120000
#指定commitlog、consumequeue所在磁盘分区的最大使用率,超过该值,则需立即清除过期文diskMaxUsedSpaceRatio=88
#指定store目录的路径,默认在当前用户主目录中
storePathRootDir=/usr/local/rocketmq-all-4.5.0/store
#commitLog目录路径
storePathCommitLog=/usr/local/rocketmq-all-4.5.0/store/commitlog
#consumeueue目录路径
storePathConsumeQueue=/usr/local/rocketmq-all-4.5.0/store/consumequeue
#index目录路径
storePathIndex=/usr/local/rocketmq-all-4.5.0/store/index
#checkpoint文件路径
storeCheckpoint=/usr/local/rocketmq-all-4.5.0/store/checkpoint
#abort文件路径
abortFile=/usr/local/rocketmq-all-4.5.0/store/abort
#指定消息的最大大小
maxMessageSize=65536
#Broker的角色
# - ASYNC_MASTER 异步复制Master
# - SYNC_MASTER 同步双写Master
# - SLAVE
brokerRole=SYNC_MASTER
#刷盘策略
# - ASYNC_FLUSH 异步刷盘
# - SYNC_FLUSH 同步刷盘
flushDiskType=SYNC_FLUSH
#发消息线程池数量
sendMessageThreadPoolNums=128
#拉消息线程池数量
pullMessageThreadPoolNums=128
#强制指定本机IP,需要根据每台机器进行修改。官方介绍可为空,系统默认自动识别,但多网卡
时IP地址可能读取错误
brokerIP1=192.168.3.105

RocketMQ学习笔记_第67张图片

brokerClusterName=DefaultCluster
brokerName=broker-b
brokerId=0
deleteWhen=04
fileReservedTime=48
brokerRole=ASYNC_MASTER
flushDiskType=ASYNC_FLUSH
namesrvAddr=192.168.59.164:9876;192.168.59.165:9876

修改broker-a-s.properties
将该配置文件内容修改为如下:

brokerClusterName=DefaultCluster
brokerName=broker-a
brokerId=1
deleteWhen=04
fileReservedTime=48
brokerRole=SLAVE
flushDiskType=ASYNC_FLUSH
namesrvAddr=192.168.59.164:9876;192.168.59.165:9876
listenPort=11911
storePathRootDir=~/store-s
storePathCommitLog=~/store-s/commitlog
storePathConsumeQueue=~/store-s/consumequeue
storePathIndex=~/store-s/index
storeCheckpoint=~/store-s/checkpoint
abortFile=~/store-s/abort

6 启动服务器
启动NameServer集群
分别启动rocketmqOS1与rocketmqOS2两个主机中的NameServer。启动命令完全相同。

nohup sh bin/mqnamesrv &
tail -f ~/logs/rocketmqlogs/namesrv.log

启动两个Master
分别启动rocketmqOS1与rocketmqOS2两个主机中的broker master。注意,它们指定所要加载的配置文件是不同的。

nohup sh bin/mqbroker -c conf/2m-2s-async/broker-a.properties &
tail -f ~/logs/rocketmqlogs/broker.log

nohup sh bin/mqbroker -c conf/2m-2s-async/broker-b.properties &
tail -f ~/logs/rocketmqlogs/broker.log

启动两个Slave
分别启动rocketmqOS1与rocketmqOS2两个主机中的broker slave。注意,它们指定所要加载的配置文件是不同的。

nohup sh bin/mqbroker -c conf/2m-2s-async/broker-b-s.properties &
tail -f ~/logs/rocketmqlogs/broker.log

nohup sh bin/mqbroker -c conf/2m-2s-async/broker-a-s.properties &
tail -f ~/logs/rocketmqlogs/broker.log

2.8 mqadmin命令

在mq解压目录的bin目录下有一个mqadmin命令,该命令是一个运维指令,用于对mq的主题,集群,broker 等信息进行管理。

2.8.1 修改bin/tools.sh

在运行mqadmin命令之前,先要修改mq解压目录下bin/tools.sh配置的JDK的ext目录位置。本机的ext
目录在/usr/java/jdk1.8.0_161/jre/lib/ext
使用vim命令打开tools.sh文件,并在JAVA_OPT配置的-Djava.ext.dirs这一行的后面添加ext的路径。
在这里插入图片描述

JAVA_OPT="${JAVA_OPT} -server -Xms1g -Xmx1g -Xmn256m -
XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=128m"
JAVA_OPT="${JAVA_OPT} -
Djava.ext.dirs=${BASE_DIR}/lib:${JAVA_HOME}/jre/lib/ext:${JAVA_HOME}/lib/
ext:/usr/java/jdk1.8.0_161/jre/lib/ext"
JAVA_OPT="${JAVA_OPT} -cp ${CLASSPATH}"

2.8.2 运行mqadmin

直接运行该命令,可以看到其可以添加的commands。通过这些commands可以完成很多的功能。

[root@mqOS rocketmq-all-4.8.0-bin-release]# ./bin/mqadmin
The most commonly used mqadmin commands are:
updateTopic Update or create topic
deleteTopic Delete topic from broker and NameServer.
updateSubGroup Update or create subscription group
deleteSubGroup Delete subscription group from broker.
updateBrokerConfig Update broker's config
updateTopicPerm Update topic perm
topicRoute Examine topic route info
topicStatus Examine topic Status info
topicClusterList get cluster info for topic
brokerStatus Fetch broker runtime status data
queryMsgById Query Message by Id
queryMsgByKey Query Message by Key
queryMsgByUniqueKey Query Message by Unique key
queryMsgByOffset Query Message by offset
QueryMsgTraceById query a message trace
printMsg Print Message Detail
printMsgByQueue Print Message Detail
sendMsgStatus send msg to broker.
brokerConsumeStats Fetch broker consume stats data
producerConnection Query producer's socket connection and client
version
consumerConnection Query consumer's socket connection, client
version and subscription
consumerProgress Query consumers's progress, speed
consumerStatus Query consumer's internal data structure
cloneGroupOffset clone offset from other group.
clusterList List all of clusters
topicList Fetch all topic list from name server
updateKvConfig Create or update KV config.
deleteKvConfig Delete KV config.
wipeWritePerm Wipe write perm of broker in all name server
resetOffsetByTime Reset consumer offset by timestamp(without
client restart).
updateOrderConf Create or update or delete order conf
cleanExpiredCQ Clean expired ConsumeQueue on broker.
cleanUnusedTopic Clean unused topic on broker.
startMonitoring Start Monitoring
statsAll Topic and Consumer tps stats
allocateMQ Allocate MQ
checkMsgSendRT check message send response time
clusterRT List All clusters Message Send RT
getNamesrvConfig Get configs of name server.
updateNamesrvConfig Update configs of name server.
getBrokerConfig Get broker config by cluster or special broker!
queryCq Query cq command.
sendMessage Send a message
consumeMessage Consume message
updateAclConfig Update acl config yaml file in broker
deleteAccessConfig Delete Acl Config Account in broker
clusterAclConfigVersion List all of acl config version information in
cluster
updateGlobalWhiteAddr Update global white address for acl Config File
in broker
getAccessConfigSubCommand List all of acl config information in
cluster

2.8.3 该命令的官网详解

该命令在官网中有详细的用法解释。
https://github.com/apache/rocketmq/blob/master/docs/cn/operation.md
RocketMQ学习笔记_第68张图片
RocketMQ学习笔记_第69张图片

3 RocketMQ工作原理

3.1 消息的生产

3.1.1 消息的生产过程

RocketMQ学习笔记_第70张图片
RocketMQ学习笔记_第71张图片
RocketMQ学习笔记_第72张图片

3.3.2 Queue选择算法

在这里插入图片描述

3.2 消息的存储

RocketMQ学习笔记_第73张图片

3.2.1 commitlog文件

RocketMQ学习笔记_第74张图片
RocketMQ学习笔记_第75张图片
在这里插入图片描述
RocketMQ学习笔记_第76张图片

3.2.2 consumequeue

RocketMQ学习笔记_第77张图片
RocketMQ学习笔记_第78张图片

RocketMQ学习笔记_第79张图片
RocketMQ学习笔记_第80张图片
RocketMQ学习笔记_第81张图片
RocketMQ学习笔记_第82张图片

3.3.3 对文件的读写

RocketMQ学习笔记_第83张图片
RocketMQ学习笔记_第84张图片
RocketMQ学习笔记_第85张图片
RocketMQ学习笔记_第86张图片

3.3.4 与Kafka的对比

RocketMQ学习笔记_第87张图片

3.3 indexFile

在这里插入图片描述
RocketMQ学习笔记_第88张图片

3.3.1 索引条目结构

RocketMQ学习笔记_第89张图片
RocketMQ学习笔记_第90张图片
RocketMQ学习笔记_第91张图片
RocketMQ学习笔记_第92张图片
RocketMQ学习笔记_第93张图片

3.3.2 indexFile的创建

RocketMQ学习笔记_第94张图片

3.3.3 查询流程

RocketMQ学习笔记_第95张图片
RocketMQ学习笔记_第96张图片

3.4 消息的消费

在这里插入图片描述

3.4.1 获取消费类型

RocketMQ学习笔记_第97张图片

3.4.2 消费模式

RocketMQ学习笔记_第98张图片
RocketMQ学习笔记_第99张图片
RocketMQ学习笔记_第100张图片

3.4.3 Rebalance机制

Rebalance机制讨论的前提是:集群消费。
RocketMQ学习笔记_第101张图片
RocketMQ学习笔记_第102张图片
RocketMQ学习笔记_第103张图片
RocketMQ学习笔记_第104张图片
RocketMQ学习笔记_第105张图片
RocketMQ学习笔记_第106张图片

3.4.4 Queue分配算法

RocketMQ学习笔记_第107张图片
RocketMQ学习笔记_第108张图片
RocketMQ学习笔记_第109张图片
一致性hash策略
RocketMQ学习笔记_第110张图片
RocketMQ学习笔记_第111张图片
RocketMQ学习笔记_第112张图片
RocketMQ学习笔记_第113张图片

3.4.5 至少一次原则

RocketMQ学习笔记_第114张图片

3.5 订阅关系的一致性

在这里插入图片描述

3.5.1 正确订阅关系

RocketMQ学习笔记_第115张图片

3.5.2 错误订阅关系

RocketMQ学习笔记_第116张图片
RocketMQ学习笔记_第117张图片
RocketMQ学习笔记_第118张图片
RocketMQ学习笔记_第119张图片
RocketMQ学习笔记_第120张图片
RocketMQ学习笔记_第121张图片

3.6 offset管理

RocketMQ学习笔记_第122张图片

3.6.1 offset本地管理模式

RocketMQ学习笔记_第123张图片

3.6.2 offset远程管理模式

RocketMQ学习笔记_第124张图片
RocketMQ学习笔记_第125张图片

3.6.3 offset用途

在这里插入图片描述
RocketMQ学习笔记_第126张图片
RocketMQ学习笔记_第127张图片

3.6.4 重试队列

RocketMQ学习笔记_第128张图片
在这里插入图片描述

3.6.5 offset的同步提交与异步提交

RocketMQ学习笔记_第129张图片

3.7 消费幂等

3.7.1 什么是消费幂等

RocketMQ学习笔记_第130张图片

3.7.2 消息重复的场景分析

RocketMQ学习笔记_第131张图片

3.7.3 通用解决方案

RocketMQ学习笔记_第132张图片
RocketMQ学习笔记_第133张图片

3.7.4 消费幂等的实现

RocketMQ学习笔记_第134张图片
RocketMQ学习笔记_第135张图片

3.8 消息堆积与消费延迟

3.8.1 概念

3.8.2 产生原因分析

RocketMQ学习笔记_第136张图片
RocketMQ学习笔记_第137张图片

3.8.3 消费耗时

RocketMQ学习笔记_第138张图片

3.8.4 消费并发度

RocketMQ学习笔记_第139张图片

3.8.5 单机线程数计算

RocketMQ学习笔记_第140张图片

3.8.6 如何避免

RocketMQ学习笔记_第141张图片
RocketMQ学习笔记_第142张图片

3.9 消息的清理

RocketMQ学习笔记_第143张图片

4 RocketMQ应用

4.1 普通消息

4.1.1 消息发送分类

RocketMQ学习笔记_第144张图片
RocketMQ学习笔记_第145张图片
RocketMQ学习笔记_第146张图片
RocketMQ学习笔记_第147张图片

4.1.2 代码举例

RocketMQ学习笔记_第148张图片

    <dependencies>
        <dependency>
            <groupId>org.apache.rocketmqgroupId>
            <artifactId>rocketmq-clientartifactId>
            <version>4.9.0version>
        dependency>
    dependencies>

定义同步消息发送生产者

/**
 * 定义同步发送消息生产者
 */
public class SyncProducer {
    public static void main(String[] args) throws Exception {
        //创建一个producer,参数为producer group名称
        DefaultMQProducer producer = new DefaultMQProducer("pg");
        //指定nameserver地址
        producer.setNamesrvAddr("192.168.119.100:9876");
        //设置当发送失败时重试发送的次数,默认为2次
        producer.setRetryTimesWhenSendFailed(3);
        //设置发送超时时限为5s,默认为3s
        producer.setSendMsgTimeout(5000);

        //开启生产者
        producer.start();

        //生产者发送100条消息
        for (int i = 0; i < 100; i++) {
            byte[] body = ("hi" + i).getBytes();
            Message msg = new Message("someTopic", "someTag", body);
            //为消息指定key
            msg.setKeys("key-"+i);
            //发送消息
            SendResult sendResult = producer.send(msg);
            System.out.println(sendResult);
        }
        //关闭producer
        producer.shutdown();

    }
}

RocketMQ学习笔记_第149张图片
定义异步消息发送生产者

/**
 * 定义异步发送消息生产者
 */
public class AsyncProducer  {
    public static void main(String[] args) throws Exception {
        DefaultMQProducer producer = new DefaultMQProducer("pg");
        producer.setNamesrvAddr("192.168.119.100:9876");
        //指定异步发送消息失败后不进行重试发送
        producer.setRetryTimesWhenSendAsyncFailed(0);
        //指定新创建的Topic的Queue数量为2,默认为4
        producer.setDefaultTopicQueueNums(2);

        //启动生产者
        producer.start();

        //生产消息
        try {
            for (int i = 0; i < 100; i++) {
                byte[] body = ("hi"+i).getBytes();
                Message msg = new Message("myTopic", "myTag", body);
                //异步发送,指定回调
                producer.send(msg, new SendCallback() {
                    @Override
                    public void onSuccess(SendResult sendResult) {

                        System.out.println(sendResult);
                    }

                    @Override
                    public void onException(Throwable throwable) {

                        throwable.printStackTrace();
                    }
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        //适当将线程睡眠,否则消息都还没发送完就直接关闭生产了。
        TimeUnit.SECONDS.sleep(3);
        producer.shutdown();


    }
}

定义单向消息发送生产者

/**
 * 单向消息发送者
 */
public class OnewayProducer {
    public static void main(String[] args) throws Exception {
        DefaultMQProducer producer = new DefaultMQProducer("pg");
        producer.setNamesrvAddr("192.168.119.100:9876");
        producer.start();

        for (int i = 0; i < 100; i++) {
            byte[] body = ("hi" + i).getBytes();

            Message message = new Message("single", "someTag", body);
            //单向发送
            producer.sendOneway(message);

        }
        producer.shutdown();
        System.out.println("producer shudown");

    }
}

定义消息消费者

/**
 * 定义消息消费者
 */
public class MessageConsumer {
    public static void main(String[] args)  throws  Exception{
        //定义一个pull消费者
//        DefaultLitePullConsumer consumer = new DefaultLitePullConsumer("cg");
        //定义一个push消费者(发布-订阅模式)
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("cg");
        //指定nameServer
        consumer.setNamesrvAddr("192.168.119.100:9876");
        //指定从第一条消息开始消费
        consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
        //指定消费Topic与Tag
        consumer.subscribe("someTopic","*");
        //指定采用广播模式进行消费,默认为集群模式
//        consumer.setMessageModel(MessageModel.BROADCASTING);

        //注册消息监听器
        //一旦broker中有了其订阅的消息就会触发该方法的执行
        //其返回值为当前consumer消费的状态
        //写法1:lambda表达式
        consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
           //逐条消费消息
            for(MessageExt msg:msgs){
                System.out.println(msg);

            }
            //返回消费状态,消费成功
            return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
        });


     //写法2:匿名内部类方式
//        consumer.registerMessageListener(new MessageListenerConcurrently() {
//            //一旦broker中有了其订阅的消息就会触发该方法的执行
//            //其返回值为当前consumer消费的状态
//            @Override
//            public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext context) {
//                //逐条消费消息
//                for(MessageExt msg:msgs){
//                    System.out.println(msg);
//
//                }
//                //返回消费状态,消费成功
//                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
//            }
//        });


        //开启消费者消费
        consumer.start();
        System.out.println("Consumer started");

    }
}

4.2 顺序消息

4.2.1 什么是顺序消息

在这里插入图片描述

4.2.2 为什么需要顺序消息

RocketMQ学习笔记_第150张图片
RocketMQ学习笔记_第151张图片
RocketMQ学习笔记_第152张图片

4.2.3 有序性分类

在这里插入图片描述
RocketMQ学习笔记_第153张图片
RocketMQ学习笔记_第154张图片
RocketMQ学习笔记_第155张图片

4.2.4 代码举例

/**
 * 定时投递
 */
public class OrderProducer {
    public static void main(String[] args) throws Exception{
        DefaultMQProducer producer = new DefaultMQProducer("pg");
        producer.setNamesrvAddr("192.168.119.100:9876");

        producer.start();


        for (int i = 0; i < 100; i++) {
            //使用整形数作为orderId
            Integer orderId = i ;
            byte[] body = ("hi" +i ).getBytes();
            Message msg = new Message("TopicA", "TagA", body);

            //将orderId作为消息key
            msg.setKeys(orderId.toString());

            //send()的第三个参数值会传递给选择器的select()的第三个参数
            //使用同步发送
            SendResult sendResult = producer.send(msg, new MessageQueueSelector() {
                @Override
                public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
                    //使用消息key作为选择的选择算法
                    String keys = msg.getKeys();
                    Integer id = Integer.valueOf(keys);

                    //使用arg作为选择算法
//                    Integer id = (Integer) arg;

                    int index = id % mqs.size();
                    return mqs.get(index);

                }
            }, orderId);
            System.out.println(sendResult);
        }
       producer.shutdown();
    }
}

4.3 延时消息

4.3.1 什么是延时消息

RocketMQ学习笔记_第156张图片

4.3.2 延时等级

RocketMQ学习笔记_第157张图片

4.3.3 延时消息实现原理

RocketMQ学习笔记_第158张图片
RocketMQ学习笔记_第159张图片
RocketMQ学习笔记_第160张图片
RocketMQ学习笔记_第161张图片
RocketMQ学习笔记_第162张图片

4.3.4 代码举例

DelayProducer

public class DelayProducer {
    public static void main(String[] args) throws Exception {
        DefaultMQProducer producer = new DefaultMQProducer("pg");
        producer.setNamesrvAddr("192.168.119.100:9876");
        producer.start();

        for (int i = 0; i < 100 ; i++) {
            byte[] body = ("hi"+i).getBytes();
            Message msg = new Message("TopicB", "someTag", body);
            //指定消息延迟等级为3 级,即延迟10s
            SendResult sendResult = producer.send(msg);
            //输出消息被发送的时间
            System.out.println(new SimpleDateFormat("mm:ss").format(new Date()));
            System.out.println(","+sendResult);
        }
        producer.shutdown();
    }
}

OtherConsumer

public class OtherConsumer {
    public static void main(String[] args) throws Exception{
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("cg");
        consumer.setNamesrvAddr("192.168.119.100:9876");
        consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);

        consumer.subscribe("TopicB","*");

        consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
            for (MessageExt msg : msgs) {
                //输出消息被消费的时间
                System.out.println(new SimpleDateFormat("mm:ss").format(new Date()));
                System.out.println("," + msg);
            }
            return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
        });
        consumer.start();
        System.out.println("consumer started");
    }
}

4.4 事务消息

4.4.1 问题引入

在这里插入图片描述
RocketMQ学习笔记_第163张图片

4.4.2 解决思路

RocketMQ学习笔记_第164张图片

RocketMQ学习笔记_第165张图片
RocketMQ学习笔记_第166张图片

4.4.3 基础知识

RocketMQ学习笔记_第167张图片
RocketMQ学习笔记_第168张图片
RocketMQ学习笔记_第169张图片
RocketMQ学习笔记_第170张图片
RocketMQ学习笔记_第171张图片

4.4.4 XA模式三剑客

RocketMQ学习笔记_第172张图片
在这里插入图片描述

4.4.5 XA模式架构

RocketMQ学习笔记_第173张图片
RocketMQ学习笔记_第174张图片

4.4.6 注意

在这里插入图片描述

4.4.7 代码举例

定义工行事务监听器

//定义工行事务监听器
public class ICBCTransactionListener implements TransactionListener {

    //回调操作方法
    //消息预提交成功就会触发该方法的执行,用于完成本地事务
    @Override
    public LocalTransactionState executeLocalTransaction(Message message, Object o) {
        System.out.println("预提交消息成功:"+message);
        //假设接收到TAGA的消息就表示扣款成功,TAGB的消息表示扣款失败
        //TAGC表示扣款结果不清楚,需要执行消息回查
        if(StringUtils.equals("TAGA",message.getTags())){
            return LocalTransactionState.COMMIT_MESSAGE;
        }else if (StringUtils.equals("TAGB",message.getTags())){
            return LocalTransactionState.ROLLBACK_MESSAGE;
        }else if (StringUtils.equals("TAGC",message.getTags())){
            return LocalTransactionState.UNKNOW;
        }
        return LocalTransactionState.UNKNOW;
    }

    @Override
    public LocalTransactionState checkLocalTransaction(MessageExt messageExt) {
        System.out.println("执行消息回查"+messageExt.getTags());
        return LocalTransactionState.COMMIT_MESSAGE;
    }
}

定义事务消息生产者

//定义事务消息生产者
public class TransactionProducer {
    public static void main(String[] args) throws MQClientException {
        TransactionMQProducer producer = new TransactionMQProducer("tpg");
        producer.setNamesrvAddr("192.168.119.100:9876");

        /**
         * 定义一个线程池
          corePoolSize  线程池中核心线程数量
         maximumPoolSize 线程池中最多线程数
         keepAliveTime   当线程池中线程数量大于核心线程数量时,多余空闲线程的存活时长
         unit  时间单位
         workQueue  临时存放任务的队列,其参数就是队列的长度
         threadFactory  线程工厂
         */
        ThreadPoolExecutor executorService = new ThreadPoolExecutor(2, 5,
                100, TimeUnit.SECONDS,
                new ArrayBlockingQueue<Runnable>(2000), new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread thread = new Thread(r);
                thread.setName("client-transaction-msg-check-thread");
                return thread;
            }
        });

        //为生产者指定一个线程池
        producer.setExecutorService(executorService);

        //为生产者添加事务监听器
        producer.setTransactionListener(new ICBCTransactionListener());

        producer.start();

        String[] tags = {"TAGA","TAGB","TAGC"};
        for (int i = 0; i < 3; i++) {
            byte[] body = ("hi"+i).getBytes();
            Message message = new Message("TTopic", tags[i], body);
            SendResult sendResult = producer.sendMessageInTransaction(message, null);
            System.out.println("发送结果为:"+sendResult.getSendStatus());
        }


    }
}

定义事务消息消费者

/**
 * 定义消息消费者
 */
public class Consumer {
    public static void main(String[] args)  throws  Exception{
        //定义一个pull消费者
//        DefaultLitePullConsumer consumer = new DefaultLitePullConsumer("cg");
        //定义一个push消费者(发布-订阅模式)
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("cg");
        //指定nameServer
        consumer.setNamesrvAddr("192.168.119.100:9876");
        //指定从第一条消息开始消费
        consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
        //指定消费Topic与Tag
        consumer.subscribe("TTopic","*");
        //指定采用广播模式进行消费,默认为集群模式
//        consumer.setMessageModel(MessageModel.BROADCASTING);

        //注册消息监听器
        //一旦broker中有了其订阅的消息就会触发该方法的执行
        //其返回值为当前consumer消费的状态
        //写法1:lambda表达式
        consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
           //逐条消费消息
            for(MessageExt msg:msgs){
                System.out.println(msg);

            }
            //返回消费状态,消费成功
            return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
        });


     //写法2:匿名内部类方式
//        consumer.registerMessageListener(new MessageListenerConcurrently() {
//            //一旦broker中有了其订阅的消息就会触发该方法的执行
//            //其返回值为当前consumer消费的状态
//            @Override
//            public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext context) {
//                //逐条消费消息
//                for(MessageExt msg:msgs){
//                    System.out.println(msg);
//
//                }
//                //返回消费状态,消费成功
//                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
//            }
//        });


        //开启消费者消费
        consumer.start();
        System.out.println("Consumer started");

    }
}

4.5 批量消息

4.5.1 批量发送消息

RocketMQ学习笔记_第175张图片
RocketMQ学习笔记_第176张图片

4.5.2 批量消费消息

批量修改属性
RocketMQ学习笔记_第177张图片
RocketMQ学习笔记_第178张图片

4.5.3 代码举例

该批量发送的需求是,不修改最大发送4M的默认值,但要防止发送的批量消息超出4M的限制。
定义消息列表分割器

/**
 * @author hxld
 * @create 2022-09-07 16:12
 */
/**
 *
 * 消息列表分割器:其只会处理每条消息的大小不超4M的情况,若存在某条消息,其本身大小大于4M,这个分割器就无法进行处理
 * 会直接将这条消息构成一个子列表返回。
  */
public class MessageListSplitter implements Iterator<List<Message>> {
    //指定极限值为4M
    private final int SIZE_LIMIT = 4 * 1024 * 1024;
    //存放所有要发送的消息
    private final List<Message> messages;
    //要进行批量发送消息的小集合起始索引
    private int currIndex;

    public MessageListSplitter(List<Message> messages) {
        this.messages = messages;
    }

    @Override
    public boolean hasNext() {
        //判断当前开始遍历的消息索引要小于消息总数
        return currIndex < messages.size();
    }

    @Override
    public List<Message> next() {
        int nextIndex = currIndex;
        //记录当前要发送的这一批次消息列表的大小
        int totalSize = 0 ;
        for(; nextIndex < messages.size(); nextIndex ++){
            //获取当前遍历的消息
            Message message = messages.get(nextIndex);

            //统计当前遍历的message的大小
            int tmpSize = message.getTopic().length() + message.getBody().length;
            Map<String, String> properties = message.getProperties();
            for (Map.Entry<String,String> entry : properties.entrySet()){
                tmpSize += entry.getKey().length() + entry.getValue().length();
            }
            tmpSize = tmpSize + 20 ;

            //判断当前消息本身是否大于4M
            if(tmpSize > SIZE_LIMIT) {
                if(nextIndex - currIndex == 0){
                    nextIndex ++ ;
                }
                break;
            }
            if (tmpSize + totalSize > SIZE_LIMIT){
                break;
            }else{
                totalSize += tmpSize;
            }
        }
        //获取当前messages列表的子集合[currIndex,nextIndex)
        List<Message> subList = this.messages.subList(currIndex, nextIndex);
        //下次遍历的开始索引
        currIndex = nextIndex;
        return subList;
    }
}

定义批量消息生产者

public class BatchProducer {
    public static void main(String[] args) throws MQClientException {
        DefaultMQProducer producer = new DefaultMQProducer("pg");
        producer.setNamesrvAddr("192.168.119.100:9876");
        //指定要发送的消息的最大大小,默认是4m
        producer.start();
        
        //定义要发送的消息集合
        List<Message> messages = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            byte[] body = ("hi" + i).getBytes();
            Message msg = new Message("someTopic", "someTag", body);
            messages.add(msg);

        }

        //定义消息列表分割器,将消息列表分割为多个不超出4M大小的小列表
        MessageListSplitter splitter = new MessageListSplitter(messages);
        while (splitter.hasNext()) {
            try {
                List<Message> listItem = splitter.next();
                producer.send(listItem);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        producer.shutdown();

    }
}

定义批量消息消费者

public  class BatchConsumer  {
    public static void main(String[] args) throws MQClientException {
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("cg");
        consumer.setNamesrvAddr("192.168.119.100:9876");
        consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
        consumer.subscribe("someTopicA","*");

        //指定每次可以消费10调消息,默认为1
        consumer.setConsumeMessageBatchMaxSize(10);
        //指定每次可以从Broker拉取40条消息,默认为32
        consumer.setPullBatchSize(40);
        consumer.registerMessageListener(new MessageListenerConcurrently() {
            @Override
            public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
                for (MessageExt msg : msgs){
                    System.out.println(msg);
                }

                //消费成功的返回结果
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;

            }
        });

        consumer.start();
        System.out.println("Consumer Started");
    }
}

4.6 消息过滤

在这里插入图片描述

4.6.1 Tag过滤

RocketMQ学习笔记_第179张图片

4.6.2 SQL过滤

RocketMQ学习笔记_第180张图片
RocketMQ学习笔记_第181张图片

4.6.3 代码举例

定义Tag过滤生产者

public class FilterByTagProducer {
    public static void main(String[] args) throws MQClientException, MQBrokerException, RemotingException, InterruptedException {
        DefaultMQProducer producer = new DefaultMQProducer("pg");
        producer.setNamesrvAddr("192.168.119.100:9876");
        producer.start();
        String[] tags = {"myTagA","myTagB","myTagC"};
        for (int i = 0; i < 10; i++) {
            byte[] body = ("hi" + i ).getBytes();
            String tag = tags[i % tags.length];
            Message msg = new Message("myTopic", tag, body);
            SendResult sendResult = producer.send(msg);
            System.out.println(sendResult);

        }
            producer.shutdown();
    }
}

定义Tag过滤消费者

public class FilterByTagConsumer {
    public static void main(String[] args) throws MQClientException {
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("cg");
        consumer.setNamesrvAddr("192.168.119.100:9876");
        consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
         consumer.subscribe("myTopic","myTopiA || myTagB");
         consumer.registerMessageListener((MessageListenerConcurrently) (list, consumeConcurrentlyContext) -> {
             for (MessageExt mg:list){
                 System.out.println(mg);
             }
             return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
         });
         consumer.start();
        System.out.println("Consumer Started");
    }
}

定义SQL过滤生产者

public class FilterBySQLProducer {
    public static void main(String[] args) throws MQClientException, MQBrokerException, RemotingException, InterruptedException {
        DefaultMQProducer producer = new DefaultMQProducer("pg");
        producer.setNamesrvAddr("192.168.119.100:9876");
        producer.start();

//        String[] tags = {"myTagA","myTagB","myTagC"};

        for (int i = 0; i < 10; i++) {
            byte[] body = ("hi" + i ).getBytes();
//            String tag = tags[i % tags.length];
            Message msg = new Message("myTopic", "myTag", body);
            msg.putUserProperty("age",i + " ");
            SendResult sendResult = producer.send(msg);
            System.out.println(sendResult);

        }
            producer.shutdown();
    }
}

定义SQL过滤消费者

public class FilterBySQLConsumer {
    public static void main(String[] args) throws MQClientException {
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("cg");
        consumer.setNamesrvAddr("192.168.119.100:9876");
        consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
//         consumer.subscribe("myTopic","myTopiA || myTagB");
        consumer.subscribe("myTopic", MessageSelector.bySql("age between 0 and 6"));
         consumer.registerMessageListener((MessageListenerConcurrently) (list, consumeConcurrentlyContext) -> {
             for (MessageExt mg:list){
                 System.out.println(mg);
             }
             return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
         });
         consumer.start();
        System.out.println("Consumer Started");
    }
}

4.7 消息发送重试机制

4.7.1 说明

RocketMQ学习笔记_第182张图片

4.7.2 同步发送失败策略

RocketMQ学习笔记_第183张图片
RocketMQ学习笔记_第184张图片

4.7.3 异步发送失败策略

RocketMQ学习笔记_第185张图片

4.7.4 消息刷盘失败策略

在这里插入图片描述

4.8 消息消费重试机制

4.8.1 顺序消息的消费重试

RocketMQ学习笔记_第186张图片
RocketMQ学习笔记_第187张图片

4.8.2 无序消息的消费重试

在这里插入图片描述

4.8.3 消费重试次数间隔

RocketMQ学习笔记_第188张图片
RocketMQ学习笔记_第189张图片

4.8.4 重试队列

RocketMQ学习笔记_第190张图片
RocketMQ学习笔记_第191张图片
在这里插入图片描述

4.8.5 消费重试配置方式

RocketMQ学习笔记_第192张图片

4.8.6 消费不重试配置方式

RocketMQ学习笔记_第193张图片

4.9 死信队列

4.9.1 什么是死信队列

RocketMQ学习笔记_第194张图片

4.9.2 死信队列的特征

RocketMQ学习笔记_第195张图片

4.9.3 死信消息的处理

在这里插入图片描述

后记

这个课程真的是一言难尽,期待后续进行重新更新吧。

你可能感兴趣的:(RocketMQ,java-rocketmq,rocketmq,学习)