漫谈 RocketMQ 消息发送
RocketMQ 支持 3 种消息发送方式:同步(sync)、异步(async)和单向(one way)。
-
同步:发送者向 RocketMQ 执行发送消息 API 时,同步等待,直到消息服务器返回发送结果。
-
异步:发送者向 RocketMQ 执行发送消息 API 时,指定消息发送成功后的回调函数,调用消息发送 API 后,立即返回,消息发送者线程不阻塞,直到运行结束,消息发送成功或失败的回调任务在一个新的线程中执行。
-
单向:消息发送者向 RocketMQ 执行发送消息 API 时,直接返回,不等待消息服务器的结果,也不注册回调函数。简单地说,就是只管发,不在乎消息是否成功存储在消息服务器上。
RocketMQ 消息发送需要考虑以下 3 个问题。
-
消息队列如何进行负载?
-
消息发送如何实现高可用?
-
批量消息发送如何实现一致性?
topic路由机制
消息发送者向某一个 topic 发送消息时,需要查询 topic 的路由信息。初次发送时会根据 topic 的名称向 NameServer 集群查询 topic 的路由信息,然后将其存储在本地内存缓存中,并且每隔 30s 依次遍历缓存中的 topic,向 NameServer 查询最新的路由信息。如果成功查询到路由信息,会将这些信息更新至本地缓存,实现 topic 路由信息的动态感知。
RocketMQ 提供了自动创建主题(topic)的机制,消息发送者向一个不存在的主题发送消息时,向 NameServer 查询该主题的路由信息会先返回空,如果开启了自动创建主题机制,会使用一个默认的主题名再次从 NameServer 查询路由信息,然后消息发送者会使用默认主题的路由信息进行负载均衡,但不会直接使用默认路由信息为新主题创建对应的路由信息。使用默认主题创建路由信息的流程如图 3-1 所示。

RocketMQ 中的路由消息是持久化在 Broker 中的,NameServer 中的路由信息来自 Broker 的心跳包并存储在内存中。 |
消息发送高可用设计
发送端在自动发现主题的路由信息后,RocketMQ 默认使用轮询算法进行路由的负载均衡。RocketMQ 在消息发送时支持自定义的队列负载算法,需要特别注意的是,使用自定义的路由负载算法后,RocketMQ 的重试机制将失效。
RocketMQ 为了实现消息发送高可用,引入了两个非常重要的特性。
-
消息发送重试机制
RocketMQ 在消息发送时如果出现失败,默认会重试两次。
-
故障规避机制
当消息第一次发送失败时,如果下一次消息还是发送到刚刚失败的 Broker 上,其消息发送大概率还是会失败,因此为了保证重试的可靠性,在重试时会尽量避开刚刚接收失败的 Broker,而是选择其他 Broker 上的队列进行发送,从而提高消息发送的成功率。
消息发送的高可用性设计如图3-2 所示。

在开始消息发送、消息存储、消息消费之前,我们整体了解一下消息发送的流程,如图 3-3 所示。
