MQ相关面试题

解耦、 异步、削峰

解耦:我有ABCD四个系统,A要分别发送数据给BCD,如果C不要了 我是不是得取消?

如果又来个E 我是不是又要发给E?

而且如果C挂了怎么办  那我还得整个重发机制

所以不如我直接弄个消息队列   A把数据发给消息队列  BCD直接去取即可

异步:用户点击提交以后,我得自己调用一次数据库,然后调用B系统完成相关操作,再给用户返回成功信息,那响应时间长

所以我不如用户点提交后  我把数据放消息队列中,然后直接给用户返回成功,那么用户体验感就会好很多,剩下的让B系统收到消息后去处理,做数据库操作即可

再者,我的消息不必即发即收,我随时发都可以,B想要的时候再收就行了

削峰:如果说比如中午A系统需要执行每秒5000条的sql请求,mysql可能会直接被打死。但是过了中午 到了下午   他每秒钟就只需要执行每条10条sql的请求

中午的时候呢  我们可以把每秒5000的请求写入到mq里面,系统从mq里面慢慢拉去请求,每秒钟拉取2000个,不要超过自己的每秒最大处理量  保证系统A不挂掉。这样下去 可能会有几十万甚至几百万的积压,  其实这是没问题的   只要高峰期一过,系统A 很快就会将积压的消息解决掉

MQ带来的问题:

1.系统可用性降低、MQ一旦故障,系统A就没办法发送消息给MQ了,就后面的系统BCD也没办法消费到消息

2.导致系统复杂性增加,系统A本来只需要给B发送一条数据即可,但是因为系统A与MQ协调出现问题,不小心把同一条数据给系统B发送了两次,导致系统B内部插入了两条一模一样的数据

3.消息在MQ内部丢失

4.一致性问题,有人给A发送了消息,本来是ABCD都要完成处理,但是D出了问题,没有走完逻辑,但在A这里已经返回了成功结果

activeMQ、RabbitMQ、RocketMQ、kafka各自有什么区别?

activeMQ是每秒万级的吞吐量、有可能丢消息。现在社区对他的维护越来越小

RabbitMq,万级,源码基于erlang,延迟最低,高可用,开源提供管理界面非常好用。社区非常活跃。

RacketMQ,阿里开源,10万级,topic可以达到几百,几千个级别,源码是java,阿里是java系

 kafka,10万级别,功能比较简单,适合大数据领域和日志采集

中小型公司用rabbitMQ,好维护 不容易黄,大型公司用RocketMq,有技术实力去维护

如果是大数据领域的实时计算,用kafka是业内标准,几乎是全世界的事实性规范

怎么提高消息队列高可用?

高可用:“高可用性”(High Availability)通常来描述一个系统经过专门的设计,从而减少停工时间,而保持其服务的高度可用性。

意思是宕机之后不用过多久马上就能用

Rabbit不是分布式的,镜像集群模式可以保证高可用

普通集群模式:queue是放在一个节点上的,里面包含了元数据和实际的数据

可能其他机器上的queue只有元数据, 元数据上是有实际数据的地址的 ,所以我们可以通过其他节点的元数据来找到实际数据 拉过来消费

缺点:可能会在集群中产生大量数据传输,可用性几乎没有什么保障

镜像集群模式:每个节点上都有queue的节点镜像,每个节点上都包含了这个queue的全部数据,你从任何一个节点去消费都没问题,任何一个节点宕机了, 其他节点上还有着这个节点的全部数据,别的消费者都可以到其他节点上去消费数据

缺点:不是分布式的,如果queue的数据量很大,因为每个节点都有全部数据,所以可能大到机器上无法承载。

kafka的高可用,kafka是分布式的

它会在每个机器上提供一个broker进程,可以认为是kafka的一个节点,topic可以划分为很多个portition  它会把数据存在不同的partition上面

0.8以后保证了高可用  他为每个porttition保存了一个副本

leader与follower,无论生产还是消费 都是往leader里面,而写入数据到leader ,leader会将数据同步到follower

如果leader挂了,该leader的follower会马上变成新的leader

如何保证消息不被重复消费?

01kafka消费端可能出现的重复消费问题:

消费者在准备提交offeset 11,但是还没有提交的时候,挂了,这时候消费者如果重启,

他会再次去拿数据,可能会再次拿到11这条数据

重复消费后怎么保证幂等性?

简而言之,一条数据重复发来两次,但是数据库里面只有一条数据,这就保证 了幂等性

常用方法:每次消费完以后,往一个地方去插入一条消息,可以是redis也可以是mysql数据库,下一次就看记录里面是不是已经存在了该条消息,用来去重,如果有,就说明已经消费过,不要再进行消费

如果是mysql,就查是否有过这条记录,如果是redis,每次都用set那么可以保证天然的幂等性

如果不是这两种场景,那就让生产者每次产生一个全局唯一id,订单id之类,先根据id去redis查看是否消费过。

如何保证消息可靠性传输(不丢失)?

有可能生产者还没给rabbitmq就丢了,也可能rabbitmq挂了 ,没存,也可能消费者还没处理,自己挂了

生产者->rabbitmq

1.生产者事务方案,失败重发,但是因为是同步的,影响吞吐量

2.confirm,异步机制。生产者每次发送消息都会给一个回调,告诉你成功还是失败,如果失败,你可以重刷消息  更推荐这一种

rabbitmq:

让他把接到的数据持久化到磁盘中去  1、在创建queue的时候将其设置为持久化,发送消息的时候将消息的deliveryMode设置为2,也是将消息设置为持久化。必须这两个同时设置才行

消费端丢失数据:

在消费者还在消费过程中的时候,消费者就自动autoACK了,告诉mq已经消费了,但是这时候不巧系统宕机,导致该条消息丢失

解决方案:将autoACK给关闭,每次自己确定已经处理完消息,再通知消费者确定,如果宕机,mq会将这条消息重新给其他的消费者去处理

kafka:

必须保证有足够多的follower 并且每个follower都同步到了数据才能返回成功的ACK

我该怎么保证从消息队列中拿到的数据按顺序执行?

比如一开始是增、改、删,结果顺序被打乱,变成了删增改,那么导致这条数据被保留下来了,跟需要的结果不符合

rabbitmq  保证同一个queue中的消息顺序

kafka  保证同一个patition中的消息顺序,在消费者这一部分,如果单线程比较慢得话,就开启多线程来处理

怎么解决消息队列延时,过期失效问题?

创建一个新的topic,新建原来十倍数量的partition,比如原来三个,现在三十个,然后让原来的消费者不直接写进数据库,而是写到三十个partition里面,再创建三十个消费者,来消费这些积压的消息

如果设置了过期时间呢?  一般是不会设置的  如果过期了  只能手动去把那丢失的消息查出了重新导进去

如果让你来开发一个消息队列中间件,你怎么设计他的架构?

结合前面的问题来回答

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值