Skip to content

MQ

1. MQ 作用

  • 应用解耦:生产和消费分离,甚至可以多个消费者
  • 异步处理:比回调请求获取数据更快,性能更高
  • 流量削峰:限制最大入库数据量,不超过系统所能承受的最大请求量,避免数据库压力过大

2. 缺陷

  • 系统可用性降低:因为MQ可能宕机,以前只要担心系统的问题,现在还要考虑 MQ 挂掉的问题,若 MQ 挂掉,所关联的系统都会无法提供服务;
  • 复杂度变高:要考虑消息丢失、消息重复消费等问题;
  • 一致性问题:多个 MQ 消费系统,部分成功,部分失败,要考虑事务问题。

3. 常用MQ

  • ActiveMQ:支持万级的吞吐量,较成熟完善;官方更新迭代较少,社区的活跃度不是很高,有消息丢失的情况。
  • RabbitMQ:延时低,微妙级延时,社区活跃度高,bug 修复及时,而且提供了很友善的后台界面;用 Erlang 语言开发,只熟悉 Java 的无法阅读源码和自行修复 bug。
  • RocketMQ:阿里维护的消息中间件,可以达到十万级的吞吐量,支持分布式事务。
  • Kafka:分布式的中间件,最大优点是其吞吐量高,一般运用于大数据系统的实时运算和日志采集的场景,功能简单,可靠性高,扩展性高;缺点是可能导致重复消费。

4. 使用场景

  • 秒杀抢购场景流量削峰,入队列,超过最大长度丢弃
  • 异步处理和解耦。如注册用户发邮件验证,提交MQ由业务模块消费,将两个模块解耦
  • 日志采集,常用的如 kafka
  • 消息通讯。点对点或发布/订阅模式

5. 高可用方法

  • RabbitMQ 镜像集群,多节点复制 queue 节点信息
  • ActiveMQ 部署主从热备
  • RocketMQ 有多 master 多 slave 异步复制模式和多 master 多 slave 同步双写模式支持集群部署模式

6. 如何保证消息不被重复消费

  • 消息带上全局唯一id,缓存在 redis 做校验或入库校验
  • 消息入库可用数据库唯一键约束

7. 如何保证消息不丢失?

  • 生产者丢失:主流的 MQ 都有确认机制或事务机制,可以保证生产者将消息送达到 MQ。如 RabbitMQ 就有事务模式和 confirm 模式。

  • MQ丢失:MQ 成功接收消息内部处理出错、宕机等情况。解决办法:开启 MQ 的持久化配置(queue设置持久化,发消息deliveryMode设置为2)。

  • 消费者丢失:采用消息自动确认模式,消费者取到消息未处理挂掉了。 解决办法:改为手动确认模式,消费者成功消费消息再确认。

8. 如何保证消息的顺序性

  • 生产者保证消息入队的顺序;
  • MQ 本身是一种先进先出的数据接口,将同一类消息,发到同一个 queue 中,就能保证出队是有序的;
  • 避免多消费者并发消费同一个 queue 中的消息。 、

9. 消息大量堆积如何处理

消息的积压来自于两方面:要么发送快了,要么消费变慢了。

扩容消费端的实例数提高消费能力。比如启用多个消费者,并发接收消息消费。并另起一套 MQ 环境给当前业务使用,堆积消息由另一个 MQ 环境自己消费,不要影响当前业务。

如果短时间内没有服务器资源扩容,妥协的办法是将系统降级,通过关闭某些不重要的业务,减少发送的数据量,最低限度让系统还能正常运转,服务重要业务。

监控产生和消费消息的速度没什么变化,是否出现消息积压的情况,检查是有消费失败反复消费的情况;监控消费消息的速度是否变慢,检查各消费实例,看看日志中是否有大量消费错误、消费线程是否死锁、是否卡在某些资源上。