RocketMQ异步通信组件入门2

RocketMQ核心概念与实战

RocketMq消息Tag

业务相近但有区别,主题一致,可用tag,用tag区分同一主题的不同消息
在这里插入图片描述
发送消息:创建消息对象时再写一个tag就行了

@Test
void tagProducer() throws Exception{
    DefaultMQProducer orderProducer = new DefaultMQProducer("tag-order-Producer");
    orderProducer.setNamesrvAddr(mqConstant.Name_Serve_Addr);
    orderProducer.start();
    //创建消息
    Message vip1Message = new Message("tag-order-topic", "vip1", "我的vip1的文章".getBytes());

    Message vip2Message = new Message("tag-order-topic", "vip2", "我的vip2的文章".getBytes());

    SendResult send = orderProducer.send(vip1Message);
    SendResult send1 = orderProducer.send(vip2Message);
    log.info(send.getSendStatus().toString());
    log.info(send1.getSendStatus().toString());

    orderProducer.shutdown();
}

消费者代码如下vip1Consumer.subscribe("tag-order-topic","vip1");在订阅消息时换掉*就行了

 /**
  * 订阅vip1
  * @throws Exception
  */
 @Test
 void consumeVip1() throws Exception{
     DefaultMQPushConsumer vip1Consumer = new DefaultMQPushConsumer("tag-order-consumer-A");
     vip1Consumer.setNamesrvAddr(mqConstant.Name_Serve_Addr);
     vip1Consumer.subscribe("tag-order-topic","vip1");
     vip1Consumer.registerMessageListener(new MessageListenerConcurrently() {
         @Override
         public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
             log.info("我在消费vip1");
             return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
         }
     });
 }

 /**
  * 订阅vip2 vip1
  * @throws Exception
  */
 @Test
 void consumeVip2_Vip2() throws Exception{
     DefaultMQPushConsumer vip1_2Consumer = new DefaultMQPushConsumer("tag-order-consumer-B");
     vip1_2Consumer.setNamesrvAddr(mqConstant.Name_Serve_Addr);
     vip1_2Consumer.subscribe("tag-order-topic","vip1||vip2");
     vip1_2Consumer.registerMessageListener(new MessageListenerConcurrently() {
         @Override
         public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
             log.info("我在消费vip1和vip2");
             return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
         }
     });
 }

RocketMq什么时候用Topic 什么时候用Tag

1.不同的消息类型:如普通消息,延迟消息,顺序消息等不同的消息类型使用不同的topic,无法通过tag进行区分
2.业务不关联用topic 如果都是订单,但是是不同项目的订单,就用tag
3.消息的优先级是否不同,不同的优先级用不同的topic
4.消息的量级是否相当,有的业务量小时效性高,有的量特别大,放一个topic可能会因为过长等待而饿死

RocketMq 消息Key

在RocketMq中的消息,默认会有一个MessageId当做消息的唯一标识,我们也可以给消息携带一个key,用作唯一标识或者业务标识,包括在控制面板查询的时候也可以使用Messageid和key来查询
在这里插入图片描述
创建消息的时候指定一下key就行了,业务参数我们自己程序要保证唯一,为了查阅以及后期的去重

 String uuid = UUID.randomUUID().toString();
 //创建消息
 Message vip1Message = new Message("tag-order-topic", "vip1",uuid ,"我的vip1的文章".getBytes());

消费者,key是在Message里面

vip1_2Consumer.registerMessageListener(new MessageListenerConcurrently() {
    @Override
    public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
        log.info("我在消费vip1和vip2");
        MessageExt messageExt = list.get(0);
        //获取key
        String keys = messageExt.getKeys();
        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
    }
});

RocketMq重复消费问题

在这里插入图片描述
1、生产者多次投递:mq返回ack时消息丢失,生产者以为投递失败就再投一次
2、消费者扩容重试,在负载均衡情况下,原来只有C1,C1拿到A信息时,还没有消费完,位点还在A,突然C2来了,会和C1负载均衡,C2分到01队列,C2会重新消费一遍A
在这里插入图片描述
如何判断这个消息的key是否存在
在消费的时候怎么判断目前这个key之前有没有消费过呢?
就需要一个容器来存放key 一般使用redis 或者 MySQL
插述:幂等性:多次操作产生的影响和第一次操作产生的影响相同
下图是使用数据库记录,这个数据库表叫去重表,但是并发时就会出问题,先执行业务逻辑再插入key,会重复只想业务逻辑的,要如何改正呢
在这里插入图片描述
利用唯一索引,将key的字段在数据库设置为唯一索引,取消查询直接插入key即可key插入成功就说明没有消费,插入失败就是已经有了,抛出异常即可,就不会再执行业务逻辑了
下面是特别关键一点,如果发生主键冲突,只是抛出异常的话,重复消息又会回到消息队列里面,重复投递就会发生问题,所以要捕获唯一索引异常SQLIntegrityConstraintViolationException然后返回消息成功就可以了
在这里插入图片描述

消息重试和死信问题

生产者重试,可以设置发送失败后,重试的次数
在这里插入图片描述
消费者重试,业务抛异常return null return RECONSUME_LATER会重试,但是重试不是发生问题就立刻重试,会有一定时间差,因为要先回队里再投递,重试的时间间隔和延迟消息的时间间隔是一致的,默认重试16次,从10s这个等级开始加
在这里插入图片描述
一个MessageExt类里面有什么信息呢?即一个消息对象里面有什么信息
在这里插入图片描述

1、如果最大重试次数都是失败的该怎么做?(死信处理)
并发模式下是16次 顺序模式是int的最大值,或者达到自定义次数都是失败的,那么这个消息就是死信
这个死信消息就会被放在另外一个队列叫做死信队列 Topic为%DLQ%消费者组名,这个组里面只有一个队列,然后再启动一个死信消费者处理死信信息即可
在这里插入图片描述
//那如果死信的topic太多要启动很多消费者嘛?
第二种方案,在正常消费者里面处理死信,获取Message的次数,判断一下即可
在这里插入图片描述
2、重试16次太久了,我想自定义重试次数怎么做?
在注册消息监听前可以设置最大消费次数
在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值