生产问题总结及性能优化
# 如何保证消息不丢失
# 生产者使用事务消息机制保证消息零丢失
# RocketMQ配置同步刷盘+Dledger主从架构保证MQ自身不会丢消息
# 同步刷盘
# Dledger的文件同步
# 消费者端不要使用异步消费机制
# RocketMQ特有的问题,NameServer挂了如何保证消息不丢失?
当NameServer全部挂了后,生产者和消费者是立即就无法工作了的;只要有一个就没问题,能正常工作。
在这种情况下,RocketMQ相当于整个服务都不可用了,那他本身肯定无法给我们保证消息不丢失了。我们只能自己设计一个降级方案来处理这个问题了。
例如在订单系统中,如果多次尝试发送RocketMQ不成功,那就只能另外找给地方(Redis、文件或者内存等)把订单消息缓存下来,然后起一个线程定时的扫描这些失败的订单消息,尝试往RocketMQ发送。这样等RocketMQ的服务恢复过来后,就能第一时间把这些消息重新发送出去。
# 总结
这套方案带来的性能损失的代价可能远远大于部分消息丢失的代价
- 生产者使用事务消息机制。
- Broker配置同步刷盘+Dledger主从架构
- 消费者不要使用异步消费。
- 整个MQ挂了之后准备降级方案
# 如何保证消息顺序
# 局部有序
只保证一部分关键消息的消费顺序。
只需要将有序的一组消息都存入同一个MessageQueue里,这样MessageQueue的FIFO设计天生就可以保证这一组消息的有序。RocketMQ中,可以在发送者发送消息时指定一个MessageSelector对象,让这个对象来决定消息发入哪一个MessageQueue。这样就可以保证一组有序的消息能够发到同一个MessageQueue里。
# 全局有序
整个MQ系统的所有消息严格按照队列先入先出顺序进行消费。
Topic全局消息有序的方式,就是将Topic配置成只有一个MessageQueue队列(默认是4个)。这样天生就能保证消息全局有序了。
而这种方式对整个Topic的消息吞吐影响是非常大的,如果这样用,基本上就没有用MQ的必要了。
# 快速处理积压消息
# 确定有大量的消息积压?
- 在Web控制台的主题页面,可以通过 Consumer管理 按钮实时看到消息的积压情况。
- 也可以通过mqadmin指令在后台检查各个Topic的消息延迟情况。
# 处理
# MessageQueue > Consumer
如果Topic下的MessageQueue配置得是足够多的,那每个Consumer实际上会分配多个MessageQueue来进行消费。这个时候,就可以简单的通过增加Consumer的服务节点数量来加快消息的消费,等积压消息消费完了,再恢复成正常情况。最极限的情况是把Consumer的节点个数设置成跟MessageQueue的个数相同。但是如果此时再继续增加Consumer的服务节点就没有用了。
# MessageQueue < Consumer
如果Topic下的MessageQueue配置得不够多的话,那就不能用上面这种增加Consumer节点个数的方法了。这时怎么办呢? 这时如果要快速处理积压的消息,可以创建一个新的Topic,配置足够多的MessageQueue。然后把所有消费者节点的目标Topic转向新的Topic,并紧急上线一组新的消费者,只负责消费旧Topic中的消息,并转储到新的Topic中,这个速度是可以很快的。然后在新的Topic上,就可以通过增加消费者个数来提高消费速度了。之后再根据情况恢复成正常情况。
# 主从架构 切换成 Dledger高可用
在官网中,还分析了一个特殊的情况。就是如果RocketMQ原本是采用的普通方式搭建主从架构,而现在想要中途改为使用Dledger高可用集群,这时候如果不想历史消息丢失,就需要先将消息进行对齐,也就是要消费者把所有的消息都消费完,再来切换主从架构。因为Dledger集群会接管RocketMQ原有的CommitLog日志,所以切换主从架构时,如果有消息没有消费完,这些消息是存在旧的CommitLog中的,就无法再进行消费了。这个场景下也是需要尽快的处理掉积压的消息。
# 消息轨迹
# 消息轨迹数据的关键属性
| Producer端 | Consumer端 | Broker端 |
|---|---|---|
| 生产实例信息 | 消费实例信息 | 消息的Topic |
| 发送消息时间 | 投递时间,投递轮次 | 消息存储位置 |
| 消息是否发送成功 | 消息是否消费成功 | 消息的Key值 |
| 发送耗时 | 消费耗时 | 消息的Tag值 |
# 消息轨迹配置
打开消息轨迹功能,需要在broker.conf中打开一个关键配置:
traceTopicEnable=true // 默认是false关闭的
# 数据存储
- 默认情况下,消息轨迹数据是存于一个系统级别的Topic ,RMQ_SYS_TRACE_TOPIC。
- 这个Topic在Broker节点启动时,会自动创建出来。
- 也支持客户端自定义轨迹数据存储的Topic。
- 客户端的两个核心对象 DefaultMQProducer和DefaultMQPushConsumer,他们的构造函数中,都有两个可选的参数来打开消息轨迹存储
- enableMsgTrace:是否打开消息轨迹。默认是false。
- customizedTraceTopic:配置将消息轨迹数据存储到用户指定的Topic 。
# 系统级别的Topic
- RMQ_SYS_TRACE_TOPIC 消息轨迹
- RMQ_SYS_TRANS_HALF_TOPIC 事务消息HALF的TOPIC
- SCHEDULE_TOPIC_XXX 延迟消息topic