本文主要讲述在使用消息队列过程中需要注意的问题以及解决方案
消息中间件是分布式系统中重要的组件,主要解决应用解耦,异步消息,流量削峰等问题,实现高性能,高可用,可伸缩和最终一致性的系统架构。目前使用较多的消息队列有ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ等
何为消息队列
消息队列是一种在应用程序之间传递消息的通信模式。它是一种异步通信机制 ,允许发送者 将消息放入队列中,而不需要立即将其发送给接收者。接收者可以在合适的时间从队列中提取消息并进行处理。
消息队列作用
削峰填谷
通过使用消息队列来平衡系统的负载,使系统能够处理峰值期间的大量请求,并在非峰值期间利用空闲时间处理积压的请求。通常应对突发流量冲击,常见的比如在电商场景下的抢购、秒杀等场景
-
在高负载期间,系统可能会面临大量的请求,超出了系统的处理能力。这可能导致系统性能下降、响应时间延长甚至系统崩溃。通过使用消息队列,可以将请求暂时存储在队列中,而不是立即处理它们。这样,系统能够在自己的处理能力范围内逐渐处理这些请求,避免超出负载极限。
-
在非峰值期间,系统可能会面临较少的请求,导致系统资源和处理能力未被充分利用。通过消息队列,可以利用系统的空闲时间处理积压的请求。这种填谷的方式可以充分利用资源,并提高系统的处理效率。
异步处理
简化流程,提升性能。比较常见的例子是电商下单后订单状态变更通过发送异步消息来通知其他系统做对应的处理。
比如下面这个例子,如果下单使用了积分、优惠券、代金券,如果订单取消,OMS系统发送订单取消MQ消息,积分系统、优惠券系统、代金券系统通过消费MQ消息来进行回退。
解耦合
上述例子其实也是一个应用解耦的例子。如果不这样做,那么系统间调用会变得非常复杂。
下单时ORDER系统调用POINT、COUPON、CHARGE系统后,调用OMS系统创建订单。订单取消如果不采用MQ消息,那么它就要调POINT等系统回退这些请求,系统间的调用会变得非常复杂。
解耦合能够提升系统的鲁棒性
何为鲁棒性:指系统、算法或模型对于输入数据的变化或扰动的稳定性和健壮性。具有鲁棒性的系统能够在面对不同类型的输入、噪声、错误或异常情况时仍能保持良好的性能和预测能力。
如何保证消息只被消费一次
消息丢失场景
在消息生产的过程中丢失消息
措施:重发
在消息队列中丢失消息
解决措施:
- 异步刷盘(极端情况导致有请求未同步磁盘):改为同步刷盘,不建议,性能损耗大
- 集群部署:通过部署多个副本备份数据
- 遇到消息丢失由业务重试:对消息丢失有一定容忍度,做好监控,补偿给用户
消费的过程中存在消息丢失
一定要等到消息接收和处理完成后才能更新消费进度
导致重复消费消息
如何保证消息只被消费一次
在生产、消费过程中增加消息幂等性的保证
- 唯一transtionId
- 锁机制规避并发问题,乐观锁
如何降低消息延迟
监控消息延迟
和监控组件集成
降低消息延迟策略
- 优化消费代码,减少无效调用
- 增加消费者数量,提高并行度
- 增加队列
- 消费端使用线程池