springboot继承rocketmq

<dependency>
    <groupId>org.apache.rocketmq</groupId>
    <artifactId>rocketmq-client</artifactId>
    <version>4.9.3</version>
</dependency>

修改配置文件

rocketmq:
  name-server: 127.0.0.1:9876     # rocketMq的nameServer地址
  producer:
    group: rocketmq-springboot-group       # 生产者组别

生产者

@SpringBootTest
public class RocketmqSpringbootTest {


    @Resource
    private RocketMQTemplate rocketMQTemplate;


    @Test
    void ProducerTest(){
        rocketMQTemplate.syncSend("bootTestTopic","我是boot的一个消息");
    }
}

消费者

@Component
@RocketMQMessageListener(topic = "bootTestTopic",consumerGroup = "boot-test-consumer-group")
public class SimpleMsgListener implements RocketMQListener<MessageExt> {

    @Override
    public void onMessage(MessageExt messageExt) {
        System.out.println(new String(messageExt.getBody()));
    }
}

重复消费问题

BROADCASTING(广播)模式下,所有注册的消费者都会消费,而这些消费者通常是集群部署的一个个微服务,这样就会多台机器重复消费,当然这个是根据需要来选择。

CLUSTERING(负载均衡)模式下,如果一个topic被多个consumerGroup消费,也会重复消费。

思路:设置唯一标识,每次消费之前判断唯一标识是否存在

rocketmq 账号密码连接 Java_java-rocketmq

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.7.11</version>
</dependency>

消费者方使用布隆过滤器进行去重

public static BitMapBloomFilter bloomFilter = new BitMapBloomFilter(100);

@Test
public void testRepeatConsumer() throws Exception {
    // 创建默认消费者组
    DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("consumer-group");
    consumer.setMessageModel(MessageModel.BROADCASTING);
    // 设置nameServer地址
    consumer.setNamesrvAddr("localhost:9876");
    // 订阅一个主题来消费   表达式,默认是*
    consumer.subscribe("TopicTest", "*");
    // 注册一个消费监听 MessageListenerConcurrently是并发消费
    // 默认是20个线程一起消费,可以参看 consumer.setConsumeThreadMax()
    consumer.registerMessageListener(new MessageListenerConcurrently() {
        @Override
        public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
                                                        ConsumeConcurrentlyContext context) {
            // 拿到消息的key
            MessageExt messageExt = msgs.get(0);
            String keys = messageExt.getKeys();
            // 判断是否存在布隆过滤器中
            if (bloomFilter.contains(keys)) {
                // 直接返回了 不往下处理业务
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
            // 这个处理业务,然后放入过滤器中
            // do sth...
            bloomFilter.add(keys);
            return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
        }
    });
    consumer.start();
    System.in.read();
}

 消息堆积问题

1. 生产者生产的速度太快了,可以在生产方做业务限流,增加消费者数量,但是消费者数量<=队列数量,适当的设置最大的消费线程数量(根据IO(2n)/CPU(n+1))

 2. 增加新的Topic进行引流,然后把所有消费者节点的目标Topic转向新的Topic,并紧急上线一组新的消费者,只负责转储,就是消费老Topic中的积压消息,并转储到新的Topic中。

如何保证消息不丢失?

  1. 生产者使用同步发送模式 ,收到mq的返回确认以后  顺便往自己的数据库里面写
  2. 消费者消费以后 修改数据这条消息的状态 = 1
  3. 写一个定时任务 间隔两天去查询数据  如果有status = 0 and time < day-2
  4. 将mq的刷盘机制设置为同步刷盘
  5. 使用集群模式 ,搞主备模式,将消息持久化在不同的硬件上
  6. 可以开启mq的trace机制,消息跟踪机制