You need to enable JavaScript to run this app.
文档中心
消息队列 RocketMQ版

消息队列 RocketMQ版

复制全文
下载 pdf
最佳实践
RocketMQ 生产者使用建议
复制全文
下载 pdf
RocketMQ 生产者使用建议
本文档介绍 RocketMQ 生产者的使用建议,推荐在使用消息队列 RocketMQ版进行消息生产与消费之前,阅读以下使用建议,提高接入效率和业务稳定性。
消息 Tag
  • 建议组合使用 Topic 和 tags,以减少 Topic 的使用。
  • Tag 可以由应用自行设置。
  • 仅当生产者在发送消息时设置了 Tag,消费者在订阅消息时才可以利用 Tag 进行消息过滤,例如 message.setTags("TagA")。消费者在 Broker 侧根据 Tag 的 hashcode 进行初步过滤,在消费端根据字符串过滤。
消息 Key
每个消息在业务层面的唯一标识码要设置到 keys 字段,便于定位消息丢失等问题。消息队列 RocketMQ版服务端会为每个消息创建索引,您可以在控制台中通过 topic + key 来查询这条消息的内容,以及消息被谁消费。使用消息 Key 时,请注意:
  • 建议消息生产者为每条消息设置具有业务区分度的 Key。
  • 索引类型为哈希索引,所以务必保证 key 尽可能唯一,以确保以此避免潜在的哈希冲突。
  • 相同的 Key 的消息数量尽量少,最大不超过 64 条,否则消息查询结果不完整。
设置消息 Key 的方式请参考:
// 订单Id String orderId = "20034568923546";
message.setKeys(orderId);
消息 ID
RocketMQ 发送消息返回的 SendResult 里面会有两个消息 ID,一个是 msgId,一个是 offsetMsgId。
  • msgId:客户端生成的唯一消息 ID,即便消息重发,消息 ID 也不会发生变化,一般可以作为唯一键用来消息去重。 msgId 生成规则主要包括客户端 IP、进程 ID、加载 MessageClientIDSetter 的类加载器的 hashcode、当前时间与系统启动时间的差值、自增序号等
  • offsetMsgId:Broker 生成的消息 ID,主要是记录的 Broker 的地址和消息的物理偏移量。不能保证唯一,消息重发就会导致相同的消息有不一样的 msgId。
日志打印
建议在消息发送成功或者失败时打印消息日志,日志中应包含 SendResult 和 Key 字段。可根据实际情况来选择是否打印消息体,如果消息内容比较重要,在消息发送失败时推荐打印消息体。
说明
对于发送结果为 SEND_OK 的消息,可以不打印消息日志,以免造成日志过多,浪费存储资源。
消息发送模式
目前消息队列 RocketMQ版提供了三种消息发送模式,说明如下:
说明
  • 异步发送和单向发送由于不需要等待返回结果就可以继续发送,消息的吞吐量会比较高,但是容易造成broker的发送线程池处理不过来,造成队列满了任务被拒绝。
  • 各种发送模式的完整实例代码可参考普通消息
发送模式
说明
示例
同步发送
Producer 发送消息后会等待服务端 broker 的返回结果,消息可靠性高,推荐使用这种模式。
SendResult sendResult = producer.send(msg)
异步发送
Producer 发送消息后,不会被阻塞,可以继续发送下一条消息。消息处理完毕从 Broker 返回结果后,直接回调 CallBack 函数进行逻辑处理。
producer.send(msg, new SendCallback() {
@Override
public void onSuccess(SendResult sendResult) {
}
@Override
public void onException(Throwable e) {
}
});
单向发送
Producer 只负责消息发送,不关心结果,Broker也不会返回处理结果。这种模式消息的可靠性比较低,一般用于日志处理,或者对消息可靠性要求不高的场景。
producer.sendOneway(msg);
发送成功状态
send 消息方法只要不抛出异常,就代表发送成功。发送成功会有多个状态,在 sendResult 里定义。每个状态的说明如下:
状态
说明
SEND_OK
消息发送成功。但是消息发送成功也不意味着它是可靠的。要确保不会丢失任何消息,还应启用同步 Master 服务器或同步刷盘,即 SYNC_MASTER 或 SYNC_FLUSH。
FLUSH_DISK_TIMEOUT
刷盘超时。表示消息发送成功但是服务器刷盘超时。
此时消息已经进入服务器队列(内存),只有服务器宕机,消息才会丢失。消息存储配置参数中可以设置刷盘方式和同步刷盘时间长度,如果 Broker 服务器设置了刷盘方式为同步刷盘,即 FlushDiskType=SYNC_FLUSH(默认为异步刷盘方式),当 Broker 服务器未在同步刷盘时间内(默认为 5s)完成刷盘,则将返回该状态。
FLUSH_SLAVE_TIMEOUT
数据同步到 Slave 服务器超时。表示消息发送成功,但是服务器同步到Slave时超时。
此时消息已经进入服务器队列,只有服务器宕机,消息才会丢失。如果 Broker 服务器的角色是同步 Master,即 SYNC_MASTER(默认是异步 Master 即 ASYNC_MASTER),并且从 Broker 服务器未在同步刷盘时间(默认为 5 秒)内完成与主服务器的同步,则将返回该状态。
SLAVE_NOT_AVAILABLE
无 Slave 服务器可用。表示消息发送成功,但是此时 Slave 不可用。如果 Broker 服务器的角色是同步 Master,即 SYNC_MASTER(默认是异步 Master 服务器即 ASYNC_MASTER),但没有配置 Slave Broker 服务器,则将返回该状态。
消息发送失败处理
Producer 的 send 方法本身支持内部重试,重试逻辑如下:
  • 同步发送:重试 2 次,总共发送 3 次。通过 retryTimesWhenSendFailed 参数可以配置重试逻辑。重试时会选择另一个 Broker master 进行重试。
  • 异步发送:重试 2 次,总共发送 3 次。通过 retryTimesWhenSendAsyncFailed 可配置重试次数。
  • 单向发送:不重试。
以上策略在一定程度上可保证消息成功发送。如果业务对消息可靠性要求比较高,建议应用增加相应的重试逻辑。例如调用 send 同步方法发送失败时,则尝试将消息存储到数据库,然后由后台线程定时重试,确保消息一定到达 Broker。
说明
如果服务端 Broker 返回的 response code 为 SYSTEM_BUSY,客户端会直接抛出异常。例如以下情况:
  • 消息存入 Broker pagecache 耗时超过 1000ms,导致消息快速失败被清理。
  • 消息在发送队列里面等待时间超过 waitTimeMillsInSendQueue(默认 1000ms)。
  • Broker pagecache busy,消息到达 Broker 直接被拒绝请求。
  • Broker 发送线程池队列任务已满,新任务被拒绝提交到线程池。
消息发送超时时间
Producer 默认的消息发送超时时间是 3000ms,可通过 sendMsgTimeout 配置。在生产环境,不建议将超时时间配置的很短,因为 RocketMQ 只能保证 P99 的延迟在几毫秒以内,部分毛刺的时间可能会比较大。如果时间配置较短,容易导致消息发送失败。
最近更新时间:2025.07.09 16:22:42
这个页面对您有帮助吗?
有用
有用
无用
无用