MQ的几个常见面试问题

1、为什么要用MQ?

关键词:解耦、异步、削峰

  1. 解耦:比如A要发数据给BCD,通过接口调用发送。此时新增E,或C现在不需要这个数据了,此时就很难受了。如果使用MQ,A发送消息到MQ,谁需要就就去订阅。A完全不需要考虑给谁发送数据,不需要维护这个代码,也不需要考虑别人是否调用成功、失败超时等情况。

  2. 异步

  3. 削峰:减少高峰时刻对服务器的压力。

2、MQ的优缺点

优点上面说了,解耦、异步、削峰

缺点:

  1. 系统可用性降低。万一MQ挂了,整套系统就崩溃了。

  2. 系统负责度提高。新增一套MQ系统,引入了很多问题,比如消息重复消费、消息丢失等等。

  3. 一致性问题。A发送数据给BCD,万一BD成功了,C失败了,就会导致数据不一致。

3、Kafka、ActiveMQ、RabbitMQ、RocketMQ都有什么区别?

  1. 吞吐量:kafka和RocketMQ支持高吞吐,amq和rmq低一个数量级,但是rmq延迟最低。

  2. 持久化消息:amq和rmq都支持。在不可抗力因素下挂掉了,消息不会丢失。

  3. 高并发:rmq最高

  4. 关注度:rmq比kfk成熟,可用性、稳定性、可靠性都高于kfk

4、如何保证高可用性?

以rmq为例,有3种模式:单机模式、普通集群模式、镜像集群模式

单机模式:生产一般不使用

普通集群模式:多台机器启动多个rmq实例。创建的queue,只会放在一个rmq实例上,但是每个实例都同步queue的元数据(通过元数据,可以找到queue所在实例)。当消费的时候,实际上当前机器上实例会从queue实际所在的实例上去拉取数据。此方案主要是提高吞吐量,让集群中多个节点来服务某个queue的读写操作。

镜像集群模式:每个创建的queue,无论是元数据还是消息体都会存在于多个实例上,也就是说,每个rmq节点都有queue的一个完整镜像。

kafka:由多个broker组成,每个broker是一个节点;当创建一个topic后,这个topic可以划分为多个partition,每个partition可以存在不同的broker上,每个partition就存放一部分数据。这就是一个天然的分布式消息队列,就是说一个topic的数据,分散保存再不同服务器上。

kafka8.0之后,提供了HA机制,就是replica副本机制。每个partition的数据库都会同步到其他机器上,并选举一个leader,生产者和消费者都与leader打交道,然后其他的副本就是follower。leader挂掉的时候,会从follower中重新选举一个新的leader。

5、如何保证消息的可靠传输,消息丢了怎么办?

数据的丢失分为3个方面:生产者、消费者、MQ。

  1. 生产者丢失:

    生产者发送消息到rmq时,数据在半路就丢失了(有可能是网络问题)。可以选择事务功能,但是这样吞吐量会下来。一般来说,在生产者这边设置开启confirm模式,每次写的消息都会分配为一个id,rmq收到消息回传一个ack消息,如果rmq没能处理这个消息,会回调一个nack接口。结合这个机制,可以加入超时重发。

    事务机制和confirm机制的最大不同是:事务是同步的,confirm机制是异步的。

  2. MQ丢失:

    rmq自己弄丢了数据。这个必须开启rmq的持久化,就是消息写入之后会持久化到磁盘。哪怕挂了,恢复之后会自动读取之前存储的数据。

    设置持久化的步骤:

    1、创建queue时设置为持久化,保证持久化queue的元数据。

    2、发送消息的时候设置deliveryMode=2,保证持久化消息数据。配合confirm支持后,只有消息被持久化后,才会通知生产者ack了。

  3. 消费者丢失:消费的时候,刚消费到,还没处理,结果进程挂了,比如重启了,那么rmq认为你消费了。这个时候得用rmq提供ack机制,通过api调用关闭rmq的自动ack机制,消费者需要在每次消费完成后手动ack,就可以保证消费者已经消费完成。

6、如何解决消息队列的延时以及过期失效问题?队列满了以后怎么处理?有几百万消息持续积压几小时,该怎么解决?

消息积压处理办法:

kafka:临时紧急扩容,将现有consumer停掉,新建一个topic,partition是原来的10倍,临时建立好原先10倍的queue数量。然后写一个临时分外数据的consumer,部署上去消费积压的数据,消费之后不做耗时的处理,直接均匀轮询写入临时建立好的10倍queue中。接着临时征用10倍的机器来部署consumer,相当于把queue资源和consumer资源扩大10倍,以正常的10倍速度消费数据。等消费完积压数据后,恢复原先部署的架构,重新用原来的consumer机器来消费消息。

rmq:设置过期时间ttl。但是这样会导致大量的数据丢失,采取另外一种方案,就是批量重导。直接丢弃大量积压的数据,等到低峰时间段,写程度把丢失的那批数据一点点查出来,重新灌入mq,把数据补回来。假设10k个订单积压在mq里面没有处理,其中1k个订单都丢了,那么只能写程序把那1k个订单给查出来,手动发到mq再补一次。

7、给你机会设计一个消息队列,怎么设计?

几个角度:

  1. 支持可伸缩性,需要的时候快速扩容,就可以增加吞吐量和容量。分布式参考kafka的设计理念,broker->topic-partition,每个partition放一个机器,存一部分数据。当资源不够的时候,给topic增加partition,然后数据迁移,增加机器,就可以存放更多数据了。

  2. 存储方式。存到磁盘,顺序写,可以就没有磁盘随机读写的寻址开销了。

  3. 高可用性。参考kafka,多副本->leader&follower->leader挂了之后重新选举leader对外服务。

  4. 0丢失。confirm机制,持久化,手动ack;

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值