消息队列常见面试题

1.为何要用消息队列

解耦、异步、削峰数据库

  • A系统调用B系统、C系统,传统的调用是直接调用,可是当B系统说我不须要你提供数据了,这时候A须要改代码,C系统说我不须要某个字段了,这时候A也要改代码,若是又多了一个D系统,A又要写代码。为了实现解耦,引入消息队列,A将产生的数据丢到消息队列中,哪一个系统须要 哪一个系统就去取;
  • A系统调用B系统,B系统因为某个须要调用第三方接口超时,致使A系统响应速度慢,而B系统的好坏又不会影响业务逻辑,因此能够改成A异步调用B,A将消息丢到消息队列中,B系统订阅消息,实现A的快速响应;
  • 当大量流量请求到系统A时,因为数据库的处理能力有限,形成数据库链接异常。使用消息队列,大量请求先丢到消息队列中,系统A使用按批拉数据的方式,批量处理数据,生产中,高峰期短暂的消息积压是容许的。

2.使用消息队列有什么缺点

  • 系统复杂性增长:加了消息队列,须要保证消息不会重复消费,须要保证消息的可靠性,须要保证消息队列的高可用
  • 系统的可用性下降:若是消息队列挂了,那么系统也会受到影响

3.为何选用RocketMQ;RocketMQ和ActiveMQ的区别

RocketMQ模型简单、接口易用,在阿里大规模使用,社区活跃,单机吞吐量10万级,可用性很是高,消息理论上不会丢失;异步

  • ActiveMQ严格遵循JMS规范,可持久化到内存、文件、数据库,可用性高主要是主从,多语言支持,消失丢失率低;
  • RocketMQ持久化到磁盘文件,可用性很是高,支持分布式,只支持Java,消息理论上不会丢失;

4.RocketMQ是怎么保证系统高可用的?分布式

  • 多Master部署,防止单点故障;
  • 主从结构,消息冗余,防止消息丢失;

5.MQ可否保证消息必达,即消息的可靠性?

为了下降消息丢失的几率,MQ须要进行超时和重传cdn

(1) MQ-client-sender 发送消息给MQ-serverserver

(2) MQ-server接收到消息后,发送 ACK消息给发送方接口

(3) MQ-client-sender 接收到 ACK消息后,则 消息已经投递成功队列

若是上述 2 消息丢失或者超时,MQ-client-sender 内的 timer 会重发消息,直到收到 ACK消息,若是重试N次后还未收到,则回调发送失败。须要注意的是,这个过程当中 MQ-server 可能会收到同一条消息的屡次重发。内存

对每条消息,MQ系统内部必须生成一个inner-msg-id,做为去重和幂等的依据,这个内部消息ID的特性是:部署

  • 全局惟一
  • MQ生成,具有业务无关性,对消息发送方和消息接收方屏蔽

(4) MQ-server 将消息发送给 MQ-client-receiver消息队列

(5) MQ-client-receiver 获得消息处理业务逻辑

(6) MQ-client-receiver 回复 ACK消息给 MQ-server

(7) MQ-server收到 ACK消息,将已消费的消息删除

若是上述 6 消息丢失或者超时,MQ-server 内的 timer 会重发消息,直到 MQ-server 收到ACK消息 而且 将已消费的消息删除,这个过程也可能会重发屡次,MQ-client-receiver 也可能会收到同一条消息的屡次重发。

须要强调的是,MQ-client-receiver 回ACK给 MQ-server,是消息消费业务方的主动调用行为,不能由 MQ-client-sender 自动发起,由于MQ系统不知道消费方何时真正消费成功。

为了保证业务幂等性,业务消息体中,必须有一个biz-id,做为去重和幂等的依据,这个业务ID的特性是:

  • 对于同一个业务场景,全局惟一
  • 由业务消息发送方生成,业务相关,对MQ透明
  • 由业务消息消费方负责判重,以保证幂等

最多见的业务ID有:支付ID,订单ID,帖子ID等。

欢迎关注个人公众号~ 搜索公众号: 码咖 或者 扫描下方二维码:

img