RocketMQ支持普通消息、分区有序消息、全局有序消息、延迟消息和事务消息。
普通消息:普通消息也称为并发消息,和传统的队列相比,并发消息没有顺序,但是生产消费都是并行进行的,单机性能可达十万级别的TPS。
分区有序消息:与Kafka中的分区类似,把一个Topic消息分为多个分区“保存”和消费,在一个分区内的消息就是传统的队列,遵循FIFO(先进先出)原则。全局有序消息:如果把一个 Topic 的分区数设置为 1,那么该 Topic 中的消息就是单分区,所有消息都遵循FIFO(先进先出)的原则。延迟消息:消息发送后,消费者要在一定时间后,或者指定某个时间点才可以消费。在没有延迟消息时,基本的做法是基于定时计划任务调度,定时发送消息。在RocketMQ中只需要在发送消息时设置延迟级别即可实现。事务消息:主要涉及分布式事务,即需要保证在多个操作同时成功或者同时失败时,消费者才能消费消息。RocketMQ通过发送Half消息、处理本地事务、提交(Commit)消息或者回滚(Rollback)消息优雅地实现分布式事务。
生产者的高可用
通常,我们希望不管Broker、Namesrv出现什么情况,发送消息都不要出现未知状态或者消息丢失。在消息发送的过程中,客户端、Broker、Namesrv 都有可能发生服务器损坏、掉电等各种故障。当这些故障发生时,RocketMQ是怎么处理的呢?
第一种保证机制:重试机制。RocketMQ 支持同步、异步发送,不管哪种方式都可以在配置失败后重试,如果单个 Broker 发生故障,重试会选择其他 Broker 保证消息正常发送。
配置项 retryTimesWhenSendFailed表示同步重试次数,默认为 2次,加上正常发送 1次,总共3次机会。同步发送的重试代码可以参考org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl.sendDefaultImpl(),每次发送失败后,除非发送被打断否则都会执行重试代码。
重试是在通信层异步发送完成的,当operationComplete()方法返回的response值为null时,会重新执行重试代码。返回值 response 为 null 通常是因为客户端收到 TCP请求解包失败,或者没有找到匹配的request。生产者配置项 retryTimesWhenSendAsyncFailed 表示异步重试的次数,默认为2 次,加上正常发送的1次,总共有3次发送机会。
第二种保证机制:客户端容错。RocketMQ Client会维护一个“Broker-发送延迟”关系,根据这个关系选择一个发送延迟级别较低的 Broker 来发送消息,这样能最大限度地利用 Broker 的能力,剔除已经宕机、不可用或者发送延迟级别较高的 Broker,尽量保证消息的正常发送。这种机制主要体现在发送消息时如何选择 Queue,源代码在 sendDefaultImpl()方法调用的selectOneMessageQueue()方法中,
我们分两段来讲。第一段代码如下:
sendLatencyFaultEnable:发送延迟容错开关,默认为关闭,如果开关打开了,会触发发送延迟容错机制来选择发送Queue。
发送Queue时如何选择呢?第一步:获取一个在延迟上可以接受,并且和上次发送相同的Broker。首先获取一个自增序号 index,通过取模获取Queue的位置下标 Pos。如果 Pos对应的Broker的延迟时间是可以接受的,并且是第一次发送,或者和上次发送的Broker相同,则将Queue返回。第二步:如果第一步没有选中一个Broker,则选择一个延迟较低的Broker。第三步:如果第一、二步都没有选中一个Broker,则随机选择一个Broker。第二段代码主要包括一个随机选择方法 tpInfo.selectOneMessageQueue(lastBrokerName),该方法的功能就是随机选择一个Broker,具体实现代码如

上面这段代码标注了三个步骤,分别解释如下:第一步:如果没有上次使用的Broker作为参考,那么随机选择一个Broker。第二步:如果存在上次使用的Broker,就选择非上次使用的Broker,目的是均匀地分散Broker的压力。第三步:如果第一、二步都没有选中一个Broker,则采用兜底方案——随机选择一个Broker。在执行如上两段代码时,需要 Broker 和发送延迟的数据作为判断的依据,这些数据是怎么来的呢?客户端在发送消息后,会调用 updateFaultItem()方法来更新当前接收消息的Broker的延迟情况,这些主要逻辑都在 MQFaultStrategy类中实现,延迟策略有一个标准接口LatencyFaultTolerance,如果读者想要自己实现一种延迟策略,可以通过这个接口来实现。
2.Broker端保证
数据同步方式保证:Broker主从复制分为两种:同步复制和异步复制。同步复制是指消息发送到Master Broker后,同步到SlaveBroker才算发送成功;异步复制是指消息发送到Master Broker,即为发送成功。在生产环境中,建议至少部署2个Master和2个Slave,下面分为几种情况详细描述。(1)1个Slave掉电。Broker同步复制时,生产第一次发送失败,重试到另一组Broker后成功;Broker异步复制时,生产正常不受影响。(2)2个 Slave掉电。Broker同步复制时,生产失败;Broker异步复制时,生产正常不受影响。(3)1 个 Master 掉电。Broker 同步复制时,生产第一次失败,重试到另一组Broker后成功;Broker异步复制时的做法与同步复制相同。(4)2个Master掉电。全部生产失败。(5)同一组Master和Slave掉电。Broker同步复制时,生产第一次发送失败,重试到另一组Broker后成功;Broker异步复制时,生产正常不受影响。(6)2组机器都掉电:全部生产失败。综上所述,想要做到绝对的高可靠,将 Broker 配置的主从同步进行复制即可,只要生产者收到消息保存成功的反馈,消息就肯定不会丢失。一般适用于金融领域的特殊场景。绝大部分场景都可以配置Broker主从异步复制,这样效率极高。
