图解MQ面试_死亡连环炮_再也不怕MQ了

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
面试题三:如何选型MQ

市面上的MQ有多种,如何选择合适自己项目的MQ呢?

现在常用的的MQ有ActiveMQ,RabbitMQ,RocketMQ,ZeroMQ,Kafka。网上比较这几种MQ的文章有很多,大家可以去参考下。我下面就给大家简单说下。

公司选型MQ主要就在于稳定性、社区活跃性、功能性(当然也不是功能越多越好,也要根据适用场景分析)。

在现如今分布式大行其道的时候,ZeroMQ对分布式的不支持对于互联网企业肯定是不合适的。而ActiveMQ的社区活跃度也不高了,对于技术跟跌如此快的今天也很少企业会去选择了。而RabbitMQ稳定的维护团队,可视化的维护界面,低延迟等优点更加受中小型企业的青睐。但是其开发语言死Erlang,对于企业来说就是个黑盒子,完全依赖RbbitMQ高迭代来维护。而RocketMQ来自阿里巴巴家族,现阶段其活跃度还是可以的。但是谁也说不好他不会像dubbo一样被阿里停更。但是RocketMQ用JAVA开发,天生的分布式架构,10W级以上的吞吐量,低延时,使他更加受大型企业的欢迎。需要企业对其源码有详细的了解。有精读源码的开发人才来对其进行拓展自定义等。Kafka业界大数据的代表作,其功能虽然不多,但是其对分布式的支持,以及高吞吐量(Kafka单机写入TPS约在百万条/秒,消息大小10个字节)使其更加受大数据的欢迎。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
总结(一个字一个字的打了好久):
1、为什么要用mq?
解耦、削峰、异步
解耦:
做电商的,都会存在几个系统,商品、订单、支付、物流、库存、优惠劵。如果用户浏览商品满意后,进行下单,一个完整的流程,必然需要订单系统去调用其他系统。如果一个功能需要提供给多个系统,那么就需要给每个系统做定制开发,将消息发给各个系统。如果使用MQ则能解决此问题。消费者只需要发送一条消息给MQ,各个消费去订阅自己感兴趣的消息即可。

削峰:
比如mysql的处理能力在每秒2000个请求,如果在高峰期,大量用户访问系统,一下子又5000个请求达到mysql,那么毫无疑问,mysql无法支撑这么请求的并发,就会挂了。导致服务无法正常使用。如果使用MQ,将请求发送到MQ,消费者根据自己的能力量力而行,则能很好的解决高峰请求量大的情况。

异步:
如果系统间调用时同步的,会导致调用方的整个耗时时间会很长,用户体验度将大打折扣。如果用MQ实现异步化,则能很好的解决此问题。

2、既然MQ有那么多优点,那么其有什么缺点呢?
系统增加了MQ,就增加了系统的复杂性,也会引入很多问题,如一致性问题,消息丢失,重复消费,如何保证幂等,消息顺序消费,消息积压等

3、那MQ如何选型呢?
zeroMQ/ActiveMQ/RabbitMQ/RocketMQ/Kafka
zeroMQ其基于C语言,不选择其原因是其不具备持久化的功能,存在消息丢失的风险,zeroMQ不支持分布式部署。
ActiveMQ其基于Java语言,早期比较推荐ActiveMQ,但是现在其社区已经不活跃了,所以不太推荐。
RabbitMQ其基于erlang语言,功能完备,社区活跃,吞吐量高,但是其对分布式部署不是很好。
RocketMQ基于Java语言,阿里系,天生支持分布式部署,现在的社区活跃度还可以,但是建议中大型企业选择,因为其阿里系,谁也说不好他会不会像dubbo一样,被半路停更。
Kafka基于Scala语言,其高吞吐量,天生支持分布式部署,使其更加适合大数据领域。

4、MQ如何保证高可用呢?
就拿RabbitMQ来说,RabbitMQ的集群模式,普通模式和镜像模式。普通模式由于只有一个节点存储了元数据和消息,其他节点只是存储了元数据。如队列属性,是否持久化等。而且其他节点不提供写,只提供读,只有主节点用来提供写,其他节点同步其元数据。其他节点提供读的时候,也是去主节点去拉取消息数据。导致普通集群只是解决了吞吐量,并没有解决高可用。一旦主节点挂了,服务将不可用。
而镜像模式则不同,其每个节点都存储了相同的数据,可以再某个节点挂了之后选择其他节点进行写入,并继续提供服务。
如果需要在不同的数据中心搬运消息,则需要使用sholve或者federation

至于kafka天生的分布式架构,让其对高可用具有良好的支撑,kafka对于一个topic可以指定分配多少个partition。而每个partition至少要有两个备份。每个partition有一个leader提供读写。这样即使一个备份数据所在服务挂了,其他备份数据会被选为leader继续提供服务。而且增加partition的数量就可以明显提高吞吐量。

5、MQ如何确保消息不丢失呢?
RabbitMQ消息丢失问题分析:
数据的丢失可能发生在生产端,也可能发生在MQ,也可能发生在消费端。所以要分别加以分析。
生产端:如果生产者发送消息,由于网络问题,没有发送到MQ就有可能发生消息丢失
那么如何避免生产端丢失消息呢。一方面可以使用事务,但是事务机制是同步的,会降低吞吐量。另一方面可以考虑使用confirm机制。异步确认消息是否发送成功。producer提供两个回调函数。ack()和nack()分别用来处理成功发送消息,和失败发送消息的场景,如失败则重试发送消息。
MQ端:如果到达了MQ,但是MQ将消息存在在内存,如果MQ挂了,则会导致消息丢失。或者MQ保存消息失败了,也会导致消息丢失。
所以MQ端可以设置消息持久化到磁盘,避免MQ挂机后消息丢失。另一面MQ和Producer的confirm机制配合使用,当MQ成功将消息存入磁盘后给回调Producer的方法。告知消息是否接受成功。
消费端:如果开启了autoAck模式,消费者接到了消息时,就会给MQ发送一个通知,告诉MQ已经收到消息了,如果此时消费者还没有来得及处理消息就挂了,消息丢失。
关闭autoAck模式,手动控制给MQ发送消息的时机,当处理完消息再给MQ发送消息,即使消费者挂了,MQ在监测到此消费者挂了后,会把消息分配给其他消费者消费。此时就会存在消息重复消费的问题,需要消费者做好幂等操作。

kafaka消息丢失问题分析:
同样会存在以上在生产者、Kafka端、消费者端丢失数据的情况。
举例:
1、消费者受到Kafka的消息后,会自动提交offset到zookeeper,但是如果这消息在消费前,生产者挂了,那么这消息不就丢了。
关闭自动提交offset,等到消息被成功消费完后再去更新offset。
2、当Kafka的leader受到消费者发来的消息后,在把消息同步到其他follower之前,leader挂了,那么重新选举出leader,此时此leader上不存在那条未被同步过来的消息。那么这消息就会丢失。
Kafka需要设置几个参数,来确保消息不丢失。
1/设置每个partition数量必须大于1;
2/设置至少在一个follower同步到leader的数据后再发送ack给producer;
3/producer设置只有kafka把消息同步给了所有的flower后再给自己发确认消息。
4/producer设置重试次数为无限大,无限次重试消息。确保消息不丢失。
这样即使leader挂了,也会选举出那个已经同步了消息的follower为新leader,确保消息不丢失,即使没有同步就挂了,但是producer没有收到ack消息就会不断的重试发送消息。

6、MQ如何保证消息被消费的顺序呢?
rabbitMQ将一个队列绑定多个消费者,消费者轮询消息,其消费顺序就会发生变化
那么可以创建多个队列,让每个消费者固定消费某个队列,队列本身就可以保证顺序性。所以消费者就能顺序消费消息,确保了消息的顺序性。

kafka的每个partition就是给一个消费者消费的,那么是否就能保证顺序性呢(每个partition里的消息就是顺序的)。当消费者开启多线程去处理partition里 消息时,就会导致消费乱序。
可以创建多个内存队列,并按照业务需要把需要保证顺序的消息投递到一个内存队列里。每个线程绑定一个内存队列,这样一个线程消费消息的顺序就能保证了

7、MQ如何避免消息被重复消费呢?
上面分析MQ如何不丢失消息的过程中,提到RabbitMQ在收到消费者确认消息前,检测到消费者挂了,就会把消息分配到其他消费者消费。如果之前的消费者已经消费过这条消息。则会造成消息重试。
而kafka产生重复消费主要在,kafka认为消费者挂了后重新rebalance的情况,会出现重复消费。
那如何来保证消息被重复消费后对数据不产生影响呢?就是我们常说的幂等操作。
1/我们新建一个set,当一条消息被消费过就把对应的消息ID存储起来,当下次再次消费消息,去这个set中比对下,这条消息是否已经在set中;
2/利用数据库的唯一键来保证幂等性

8、MQ消息大量积压了怎么办?
当消费者突然因为网络或者宕机没法提供消费服务的时候,MQ中会迅速堆积大量的消息无法消费。如果大量消息无法消费,如果MQ 还设置了消息持久化,那么对磁盘对内存来说都是灾难。可能就会造成MQ不可用。
解决方式,就是迅速扩容。拿kafka来说,可以新建一个topic,修改线上代码,把消息都写到这个topic对应的partition中,然后给这个topic分配几十个partition,让十几个消费者去消费。这样能快速的消耗掉消息。

9、MQ导致的一致性问题?
当多个系统去消费同一个消息时,其他系统都消费成功了,但是某个系统出错了,就会导致系统间数据不一致的问题。
使用分布式事务,提供补偿机制,如果出错则全部执行回滚操作。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章