1.消息队列
消息队列:在消息的传输过程中保存消息的容器,生产者和消费者不直接通讯,依靠队列保证消息的可靠性,避免了系统间的相互影响。
2.应用场景
异步调用,业务解耦,削峰填谷
具有高吞吐,高可靠性
3.基本概念
MQ将消息存储到Broker,用topic区分,内部有队列方便查找
broker和nameserver30s同步一次
生产者和nameserver建立连接信息,然后消息放入broker,,消费者再与nameserver建立联系,再从broker拿消息
RocketMQ相比zk更加轻量
搭建代码
在控制台中可查询消息
在Rocket中,topic:一级分类 tag:二级分类
topic是否相同使用场景
消息类型是否一致
业务是否相关联
消息的优先级是否一致:如物流信息和需要马上到达的信息
消息的量级是否相同
message的结构
对应代码
代码发送失败后重试,重新选一个broker发送
消费模式两种获取消息的方式
4.生产端核心
5.消费端核心
broker获取消息方式
1.拉取,使用消费者组,设置nameserver,设置topic并获取队列,循环中获取消息,获取偏移量,设置拉去数据(拉去偏移量)
package com.nx.simple.consumer;
import com.nx.Constant;
import org.apache.rocketmq.client.consumer.DefaultMQPullConsumer;
import org.apache.rocketmq.client.consumer.PullResult;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.message.MessageQueue;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class PullConsumer {
private static final Map<MessageQueue, Long> offsetTable = new HashMap<MessageQueue, Long>();
public static void main(String[] args) throws MQClientException {
DefaultMQPullConsumer consumer = new DefaultMQPullConsumer("nx-group-pull");
consumer.setNamesrvAddr(Constant.MQ);
consumer.start();
//1.获取MessageQueues并遍历(一个Topic包括多个MessageQueue)
Set<MessageQueue> mqs = consumer.fetchSubscribeMessageQueues("nx-user");
for (MessageQueue mq : mqs) {
System.err.println("Consume from the queue: " + mq);
SINGLE_MQ:
while (true) {
try {
// 针对不同的队列来拉取数据(如果没没有数据就会进行阻塞)
PullResult pullResult = consumer.pullBlockIfNotFound(mq, null, getMessageQueueOffset(mq), 32);
System.out.println(pullResult);
//2.维护Offsetstore(这里存入一个Map)
putMessageQueueOffset(mq, pullResult.getNextBeginOffset());
//3.根据不同的消息状态做不同的处理
switch (pullResult.getPullStatus()) {
case FOUND://获取到消息
List<MessageExt> messageExtList = pullResult.getMsgFoundList();
for (MessageExt m : messageExtList) {
System.out.println(new String(m.getBody()));
}
break;
case NO_MATCHED_MSG: // 没有匹配tag的消息
break;
case NO_NEW_MSG://没有新消息 该队列没有新消息,消费offset=最大offset
break SINGLE_MQ;// 跳出该队列遍历
case OFFSET_ILLEGAL://非法偏移量
break;
default:
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
consumer.shutdown();
}
private static void putMessageQueueOffset(MessageQueue mq, long offset) {
offsetTable.put(mq, offset);
}
private static long getMessageQueueOffset(MessageQueue mq) {
Long offset = offsetTable.get(mq);
if (offset != null){
return offset;
}
return 0;
}
}
2.推送模式:通过长轮询方式
消息模式:广播消息 集群消息
不推荐使用hash
消费位点
一般使用从头消费,如果添加新业务可以选择last
从activemq迁移到rocketmq
ACK确认机制,消息重试
消息进度存储
延时消息
可以使用在订单多少分钟未支付就取消上
6.架构原理
存储结构
消息放在commitlog中,会开辟一个g大小的空间,保证数据性。
刷盘机制,默认异步,但是同步安全性高