RocketMQ使用总结心得

84 阅读3分钟

消息发送

以下内容为spring整合RocketMQ下实现

同步消息

producer向 broker 发送消息后同步等待, 直到broker 服务器返回发送结果

    SendResult sendResult = rocketMQTemplate.syncSend("topic", "message");
    if (sendResult.getSendStatus() == SendStatus.SEND_OK) {
        log.info("同步发送成功") ;
    }
    log.info("同步发送失败") ;

异步消息

producer向 broker 发送消息注册回调方法,调用 API 后立即返回,消息发送成功或失败的回调任务在一个新的线程中执行

    rocketMQTemplate.asyncSend("topic", "message", new SendCallback() {
        @Override
        public void onSuccess(SendResult sendResult) {
            log.info("异步消息发送成功");
        }

        @Override
        public void onException(Throwable throwable) {
            log.info("异步消息发送失败");
        }
    });

顺序消息

RocketMQ的一个主题topic下会有多个消息队列,通过第三个参数计算hash值来指定发送到的消息队列,一般把类似订单id产品id这种作为参数值,如果发送多次消息,这多次消息都在该队列中排队即有序,前面完成了有序存储,后面需要消费者有序消费

rocketMQTemplate.syncSendOrderly("topic", "message", "hashkey");

事务消息

事务消息就是,先发送个信息给broker,表明发送了消息,然后执行本地事务,如果本地事务成功执行了,则发送commit给broker,则该消息可以被消费者消费了,如果发送的是rollback,则该消息不会被消费

Message<String> message = MessageBuilder.withPayload("message")
            .setHeader(RocketMQHeaders.KEYS, 1)
            .setHeader(RocketMQHeaders.TRANSACTION_ID, 100)
            .build();
    TransactionSendResult transactionSendResult = rocketMQTemplate.sendMessageInTransaction("topic", message, null);

该代码也是写在消息生产者中,executeLocalTransaction即执行本地事务的代码,如果返回的是RocketMQLocalTransactionState.COMMIT,可以在消费者看到消息被消费,如果执行的是RocketMQLocalTransactionState.ROLLBACK可以看到消息不会被消费

@RocketMQTransactionListener
public class TransactionListener implements RocketMQLocalTransactionListener {
    @Override
    public RocketMQLocalTransactionState executeLocalTransaction(Message message, Object o) {
        System.out.println("运行executeLocalTransaction");
        return RocketMQLocalTransactionState.COMMIT;
      //  return RocketMQLocalTransactionState.ROLLBACK;
    }

    @Override
    public RocketMQLocalTransactionState checkLocalTransaction(Message message) {
        System.out.println("checkLocalTransaction");
        return RocketMQLocalTransactionState.COMMIT;
    }
}

消息消费

消费消息都是由@RocketMQMessageListener注解来实现,通过配置messagemodel实现消息模式、consumemode 实现消费方式。@RocketMQMessageListener注解默认为集群模式、并发消费

messageModel有两种模式BROADCASTING 和 CLUSTERING,代表广播模式和集群模式,简单理解广播模式指的是一条消息会被所有订阅该topic的消费组下的所有消费者消费,而集群模式一条消息可以被订阅该topic的多个消费组消费,但只会被消费组下的其中一个消费者消费。

consumemode有两种模式concurrently和orderly,代表并发消费和顺序消费,并发消费是指使用线程池开启多个线程并发的去消费queue中的消息,而顺序消费是指加分布式锁和本地锁保证同时只有一条线程去消费一个队列上的数据。

总结一下,顺序消费和并发消费实际上都是使用线程池消费,但是不同的是,对于同一个消息队列的消息,并发消费可能有多条线程并发的消费消息,提升了消息速度,但是没有顺序性。

而顺序消费则通过一系列锁,保证同一时刻对于同一个队列只有一个线程去消费它,注意是“只有一个线程”而不是“同一个线程”,因此有可能你先发送的消息被ThreadA消费了,但是你发送的的第二个消息被ThreadB消费了,这是完全正确的,因为他们并不是同时消费的。但是对于不同的队列,顺序消费则不能保证消费有序性,因为不同的队列有不同的锁。所以顺序消费也必须配合顺序发送,保证消息发送到同一队列才可以。