1、为什么要使用消息中间件?

一般说法:

  • 解耦与复用
  • 异步
  • 削峰

以登录举例说明,假设登录服务和认证服务不是同一个系统,登录服务收到登录请求后调用认证服务的接口认证用户名、密码,需要等待认证服务的结果,认证通过后通知其他应用服务做相应的处理。这个过程对于登录服务来说,只有认证服务是需要强依赖的,是一种典型的调用关系,而登录服务与其他应用服务之间如果也使用这种调用关系,它们之间的依赖关系会使得整体架构非常复杂,每个应用服务的变化扩展都可能需要同步修改登录服务。因此使用MQ可以做到将登录服务与应用服务解耦,登录服务处理完登录后只需要往MQ发送通知,其他应用服务从MQ接收通知即可,登录服务不需要关注谁要接收这些通知。
异步仅适用于不需要关注返回结果的调用关系,例如登录成功后发通知加载广告。
对于削峰,首先需要知道MQ并不能解决高并发问题,只是一种缓解的策略。将消息放到队列中等待各个服务节点消费,使用队列维护消息,可以暂时将来不及处理的消息缓存在队列中。对于偶现的高并发,使用MQ是一种很好的缓解策略,高并发时有队列顶着,并发量降下来时队列的压力慢慢减小了。但是如果服务节点的消费速度太慢,并发量一直不降,这种情况MQ的队列只会越堆积越多,数据延迟越来越大,这时候应该考虑的服务的垂直扩展与水平扩展。无法扩展的时候应该考虑限流、熔断等方式。

2、引入MQ导致的问题

  • 系统可用性降低
    各个服务依赖于MQ,若是MQ挂掉了,整个系统功能都会不正常。(可提一提RabbitMQ的事务机制)
  • 系统复杂度提高
    很多中间件无法避免消息重复、消息丢失的问题,无法保证消息顺序。为了解决这些问题,需要设计一些补偿机制,导致系统复杂度提高。
  • 数据一致性问题
    A 系统调用 BC 系统接口,如果 BC 系统出错了,会抛出异常,返回给 A 系统让 A 系统知道,这样的话就可以做回滚操作了。但是使用了 MQ 之后,A 系统发送完消息就完事了,认为成功了。而刚好 C 系统写数据库的时候失败了,但是 A 认为 C 已经成功了?这样一来数据就不一致了。所以说使用MQ解决异步调用问题要考虑适用场景,它适用于不需要关注返回结果的调用关系。

3、如何保证MQ不丢失消息

4、怎么保证MQ的高可用性

5、如何保证不重复消费