一、RocketMQ 概述
1. 什么是 RocketMQ?
- 定义:RocketMQ 是一款分布式消息中间件,支持发布/订阅、点对点等多种消息传递模式。
-
特点:
- 高性能:单机支持百万级消息吞吐。
- 高可靠:支持消息持久化、消息重试、消息幂等等。
- 高可用:支持多主多从架构,自动故障转移。
- 可扩展:支持水平扩展,轻松应对业务增长。
- 丰富的功能:支持事务消息、延迟消息、顺序消息等。
2. RocketMQ 的应用场景
- 异步通信:系统间异步解耦,提高系统响应速度。
- 削峰填谷:平滑流量高峰,避免系统过载。
- 系统解耦:降低系统间的耦合度,提高系统可维护性。
- 消息广播:向多个消费者广播消息,实现数据同步。
- 分布式事务:通过事务消息实现分布式事务的一致性。
二、RocketMQ 核心概念
1. 消息(Message)
-
定义:消息是 RocketMQ 中传递的数据单元,可以是任何格式的数据,如文本、JSON、XML 等。
-
属性:
- Topic:消息的主题,用于分类和路由。
- Tag:消息的标签,用于更细粒度的消息分类。
- Key:消息的唯一标识,用于消息去重和查询。
- Body:消息的内容。
2. 主题(Topic)
-
定义:Topic 是消息的分类标识,生产者向指定的 Topic 发送消息,消费者订阅指定的 Topic 接收消息。
-
特点:
- 一个 Topic 可以有多个生产者发布消息。
- 一个 Topic 可以有多个消费者订阅消息。
3. 生产者(Producer)
-
定义:Producer 是消息的发送者,负责向 RocketMQ 发送消息。
-
类型:
- 同步生产者:发送消息后等待服务器响应。
- 异步生产者:发送消息后不等待服务器响应,通过回调函数处理结果。
- 单向生产者:发送消息后不等待服务器响应,也不处理结果。
4. 消费者(Consumer)
-
定义:Consumer 是消息的接收者,负责从 RocketMQ 接收消息并处理。
-
类型:
- 集群消费(Clustering) :多个消费者共同消费一个 Topic 的消息,消息被均衡分配到各个消费者。
- 广播消费(Broadcasting) :每个消费者都会接收所有消息。
5. 消息队列(Message Queue)
- 定义:Message Queue 是消息的存储单元,一个 Topic 可以包含多个 Message Queue,用于消息的负载均衡和并行处理。
6. Broker
-
定义:Broker 是 RocketMQ 的核心组件,负责消息的存储、转发和持久化。
-
架构:
- 主从架构:一个主 Broker 多个从 Broker,主 Broker 负责消息的写入,从 Broker 负责消息的读取和备份。
- 多主多从架构:多个主 Broker 和多个从 Broker,提高系统的可用性和吞吐量。
7. 命名服务(NameServer)
-
定义:NameServer 是 RocketMQ 的服务发现和路由组件,负责管理 Broker 的注册信息、Topic 的路由信息等。
-
特点:
- 无状态:NameServer 不存储消息数据,只存储路由信息。
- 高可用:支持多实例部署,通过负载均衡提高可用性。
三、RocketMQ 安装与部署
1. 环境准备
- 操作系统:Linux(推荐使用 CentOS、Ubuntu 等)。
- Java 环境:JDK 1.8 及以上。
- 内存:建议至少 4GB 内存。
- 磁盘空间:根据消息量确定,建议至少 50GB。
2. 下载与解压
bash
取消自动换行
复制
wget https://github.com/apache/rocketmq/releases/download/rocketmq-all-4.9.4/rocketmq-all-4.9.4-bin-release.zip
unzip rocketmq-all-4.9.4-bin-release.zip
cd rocketmq-all-4.9.4-bin-release
3. 启动 NameServer
bash
取消自动换行
复制
nohup sh bin/mqnamesrv &
-
验证:
bash 取消自动换行 复制 tail -f ~/logs/rocketmqlogs/namesrv.log
4. 启动 Broker
bash
取消自动换行
复制
nohup sh bin/mqbroker -n localhost:9876 &
-
验证:
bash 取消自动换行 复制 tail -f ~/logs/rocketmqlogs/broker.log
5. 配置集群(可选)
-
多主多从架构:
- 配置多个 Broker 实例,指定主从关系。
- 配置 NameServer 集群,使用多个 NameServer 实例。
6. 关闭 RocketMQ
bash
取消自动换行
复制
sh bin/mqshutdown broker
sh bin/mqshutdown namesrv
四、RocketMQ 编程模型
1. 生产者编程
-
依赖引入(以 Maven 为例):
xml 取消自动换行 复制 <dependency> <groupId>org.apache.rocketmq</groupId> <artifactId>rocketmq-client</artifactId> <version>4.9.4</version> </dependency> -
示例代码:
java 取消自动换行 复制 import org.apache.rocketmq.client.producer.DefaultMQProducer; import org.apache.rocketmq.client.producer.SendResult; import org.apache.rocketmq.common.message.Message; public class ProducerExample { public static void main(String[] args) throws Exception { // 创建生产者实例 DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName"); producer.setNamesrvAddr("localhost:9876"); producer.start(); // 创建消息 Message msg = new Message("TopicTest", "TagA", "Hello RocketMQ".getBytes()); // 发送消息 SendResult result = producer.send(msg); System.out.println(result); // 关闭生产者 producer.shutdown(); } }
2. 消费者编程
-
示例代码:
java 取消自动换行 复制 import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; import org.apache.rocketmq.common.message.MessageExt; public class ConsumerExample { public static void main(String[] args) throws Exception { // 创建消费者实例 DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ConsumerGroupName"); consumer.setNamesrvAddr("localhost:9876"); consumer.subscribe("TopicTest", "TagA"); // 设置消息监听器 consumer.registerMessageListener(new MessageListenerConcurrently() { @Override public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) { for (MessageExt msg : msgs) { System.out.println(new String(msg.getBody())); } return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; } }); // 启动消费者 consumer.start(); } }
3. 消息发送方式
- 同步发送:发送消息后等待服务器响应。
- 异步发送:发送消息后不等待服务器响应,通过回调函数处理结果。
- 单向发送:发送消息后不等待服务器响应,也不处理结果。
4. 消息消费方式
- 集群消费:多个消费者共同消费一个 Topic 的消息,消息被均衡分配到各个消费者。
- 广播消费:每个消费者都会接收所有消息。
五、RocketMQ 高级特性
1. 事务消息
-
简介:事务消息用于实现分布式事务的一致性,保证消息发送和业务操作的原子性。
-
实现原理:
- 步骤1:生产者发送半消息(Half Message)到 RocketMQ。
- 步骤2:RocketMQ 返回半消息的发送结果。
- 步骤3:生产者执行本地事务。
- 步骤4:根据本地事务的执行结果,提交或回滚半消息。
- 步骤5:RocketMQ 根据提交或回滚操作,处理消息。
-
示例代码:
java 取消自动换行 复制 import org.apache.rocketmq.client.producer.TransactionMQProducer; import org.apache.rocketmq.client.producer.TransactionListener; import org.apache.rocketmq.client.producer.TransactionMQProducer; import org.apache.rocketmq.client.producer.TransactionExecuter; import org.apache.rocketmq.client.producer.TransactionCheckListener; import org.apache.rocketmq.client.producer.TransactionSendResult; import org.apache.rocketmq.common.message.Message; public class TransactionProducerExample { public static void main(String[] args) throws Exception { TransactionMQProducer producer = new TransactionMQProducer("TransactionProducerGroup"); producer.setNamesrvAddr("localhost:9876"); producer.setTransactionListener(new TransactionListener() { @Override public LocalTransactionState executeLocalTransaction(Message msg, Object arg) { // 执行本地事务 return LocalTransactionState.COMMIT_MESSAGE; } @Override public LocalTransactionState checkLocalTransaction(Message msg) { // 检查本地事务状态 return LocalTransactionState.COMMIT_MESSAGE; } }); producer.start(); Message msg = new Message("TransactionTopic", "TagA", "Hello Transaction".getBytes()); TransactionSendResult result = producer.sendMessageInTransaction(msg, null); System.out.println(result); producer.shutdown(); } }
2. 延迟消息
-
简介:延迟消息是指消息在指定的时间后被消费者消费。
-
实现原理:
- RocketMQ 通过设置消息的延迟级别(Delay Level)实现延迟消息。
- 延迟级别分为18个等级,分别对应不同的延迟时间。
-
示例代码:
java 取消自动换行 复制 import org.apache.rocketmq.client.producer.DefaultMQProducer; import org.apache.rocketmq.client.producer.SendResult; import org.apache.rocketmq.common.message.Message; public class DelayProducerExample { public static void main(String[] args) throws Exception { DefaultMQProducer producer = new DefaultMQProducer("DelayProducerGroup"); producer.setNamesrvAddr("localhost:9876"); producer.start(); Message msg = new Message("DelayTopic", "TagA", "Hello Delay".getBytes()); // 设置延迟级别为1,对应1秒 msg.setDelayTimeLevel(1); SendResult result = producer.send(msg); System.out.println(result); producer.shutdown(); } }
3. 顺序消息
-
简介:顺序消息是指消息按照发送的顺序被消费者消费。
-
实现原理:
- 使用 Message Queue 顺序发送和消费消息。
- 需要保证同一个 Message Queue 的消息被同一个消费者顺序消费。
-
示例代码:
java 取消自动换行 复制 import org.apache.rocketmq.client.producer.DefaultMQProducer; import org.apache.rocketmq.client.producer.SendResult; import org.apache.rocketmq.common.message.Message; public class OrderProducerExample { public static void main(String[] args) throws Exception { DefaultMQProducer producer = new DefaultMQProducer("OrderProducerGroup"); producer.setNamesrvAddr("localhost:9876"); producer.start(); for (int i = 0; i < 10; i++) { Message msg = new Message("OrderTopic", "TagA", ("Order " + i).getBytes()); SendResult result = producer.send(msg, messageQueue -> { // 选择同一个 Message Queue return messageQueue; }); System.out.println(result); } producer.shutdown(); } }
4. 消息去重
-
简介:消息去重是指保证消息不被重复消费。
-
实现方法:
- 业务层面去重:在消费者端实现去重逻辑,如使用数据库唯一键、Redis 缓存等。
- RocketMQ 层面去重:使用消息 Key 和去重策略。
5. 消息重试
-
简介:消息重试是指消费者在消费失败后,重新尝试消费消息。
-
实现方法:
- 配置消费者的重试次数和重试间隔。
- 使用死信队列(Dead Letter Queue)处理多次消费失败的消息。
六、RocketMQ 实战案例
1. 异步消息处理
-
场景:用户注册后,发送欢迎邮件和短信。
-
实现步骤:
- 1.用户注册后,发送注册消息到 RocketMQ。
- 2.邮件服务和短信服务订阅注册消息。
- 3.邮件服务和短信服务接收到消息后,发送邮件和短信。
2. 削峰填谷
-
场景:电商系统在大促期间,订单量激增。
-
实现步骤:
- 1.订单服务将订单消息发送到 RocketMQ。
- 2.订单处理服务订阅订单消息。
- 3.订单处理服务根据 RocketMQ 的负载均衡机制,动态调整消费速率,实现削峰填谷。
3. 系统解耦
-
场景:用户支付完成后,更新订单状态、发送通知等。
-
实现步骤:
- 1.支付服务将支付完成消息发送到 RocketMQ。
- 2.订单服务、通知服务等订阅支付完成消息。
- 3.各服务根据消息内容,执行相应的操作,实现系统解耦。
4. 分布式事务
-
场景:用户下单后,扣减库存、生成订单、支付等操作。
-
实现步骤:
- 1.订单服务发送事务消息到 RocketMQ。
- 2.事务消息的本地事务执行扣减库存、生成订单等操作。
- 3.根据本地事务的执行结果,提交或回滚事务消息。
- 4.支付服务订阅事务消息,执行支付操作。