精华内容
下载资源
问答
  • 消息队列面试题

    2021-04-25 16:01:21
    消息队列面试题消息队列的应用场景各种消息队列的比较消息队列的优缺点如何保证消息队列的高可用如何保证消息不丢失如何保证消息不被重复消费(幂等性)如何保证消息的顺序性消息堆积如何处理消息过期如何处理 ...

    消息队列的应用场景

    数据结构:消息队列是一种先进先出的数据结构

    应用场景:解耦、异步、削峰

    解耦:各个系统之间耦合性高,如果某个子系统出现问题,会影响其他子系统和整个业务流程。这时引入消息队列,将子系统需要的数据放入消息队列,子系统出现异常,不会影响到其他子系统。

    异步:某个子系统不依赖于其他子系统的返回结果。

    流量削峰:秒杀系统请求流量瞬间激增,通过消息队列将请求缓存,可以提高系统的稳定性。

    各种消息队列的比较

    特性 ActiveMQ RabbitMQ RocketMQ Kafka
    开发语言 Java Erlang Java Scala
    单机吞吐量 万级别 万级别 十万级别 十万级别
    时效性 ms级 us级 ms级 ms级
    可用性 高、主从架构 高、主从架构 非常高、分布式架构 非常高、分布式架构

    ActiveMQ,早期使用的较多,没经过大规模吞吐量的验证,社区也不是很活跃,不推荐。

    RabbitMQ,开源、性能稳定,推荐使用。

    RocketMQ,开发语言是Java,推荐使用。

    Kafka,大数据领域应用较多,日志采集业务推荐使用。

    消息队列的优缺点

    优点:解耦、异步、削峰

    缺点:

    系统可用性降低

    ​ 保证消息队列高可用

    系统复杂度提高

    ​ 消息丢失

    ​ 消息重复消费

    ​ 消息传递顺序性

    一致性问题

    ​ 消息数据处理的一致性

    如何保证消息队列的高可用

    RabbitMQ高可用

    • 普通集群

      1.在多台机器上分别启动RabbitMQ实例

      2.多个实例之间可以相互通信

      3.创建的Queue只会放在一个RabbitMQ上,其他实例只同步queue元数据

      4.消费时,如果连接的RabbitMQ没有Queue,当前实例会通过queue元数据拉取数据

      特点:没有真正的做到高可用,数据拉取有时间开销,单实例的瓶颈问题。

    • 镜像集群

    ​ 1.在多台机器上分别启动RabbitMQ实例

    ​ 2.多个实例之间可以相互通信

    ​ 3.每次生产者写消息到queue的时候,都会自动把消息同步到多个实例的queue上,每个RabbitMQ节点上都有Queue的消息数据跟元数据。

    RocketMQ高可用(双主双从)

    ​ 1.生产者通过NameServer发现Broker

    ​ 2.生产者发送消息到Broker主节点

    ​ 3.Broker主节点跟从节点同步数据

    ​ 4.消费者从主节点或从节点订阅消息

    如何保证消息不丢失

    消息丢失的原因:

    ​ 1.消息生产者没有成功发送到MQ Broker

    ​ 2.消息发送给MQ Broker后,Broker宕机导致内存中的消息丢失

    ​ 3.消费者消费到了消息,但是没有处理完毕,客户端宕机

    ​ 保证消息不丢失方案:

    ​ 1.消息发送者发送给MQ Broker后,MQ Broker给生产者确认收到

    ​ 2.MQ收到消息后进行持久化

    ​ 3.消费者收到消息处理完毕后手动进行ack确认

    ​ 4.MQ收到消费者ack确认后删除持久化的消息

    如何保证消息不被重复消费(幂等性)

    产生原因:

    ​ 1.发送时消息重复:消息发送者发送给MQ Broker后,MQ Broker未给生产者发送确认收到消息,由于网络抖动,生产者未收到确认消息。

    ​ 2.消费时消息重复 : 消费者收到消息处理完毕后,手动进行ack确认,由于网络抖动,MQ Broker未收到应答消息。

    保证消息幂等性的方案:

    ​ 1.消息发送者发动消息时携带一个全局唯一的消息ID

    ​ 2.消费者获取消息后先根据id在redis/db中查询是否存在消费记录

    ​ 3.如果没有消费就正常消费,消费完毕后写入redis/db

    ​ 4.如果消息消费过就直接舍弃。

    如何保证消息的顺序性

    什么是消息的顺序性:消息有序是指按照消息发送的顺序消费。

    保证消息顺序性方案:

    ​ 全局顺序性:生产者、MQ Server、消费者按照1:1:1的配比,吞吐量比较低。

    ​ 局部顺序性:生产者根据消息ID将同一组消息发送到同一个Queue中,多个消费者同时获取Queue中的消息进行消费。MQ使用分段锁保证单个Queue中的有序消费。【RocketMQ的方案】

    消息堆积如何处理

    消息堆积产生的原因:

    ​ 1.由于网络抖动,消费者未及时消费消息

    ​ 2.消费方处理消息后没有给MQ Server进行ack确认。

    消息堆积处理方案:

    ​ 1.检查消费方的正常消费速度

    ​ 2.将堆积的消息转存到容量更大的MQ集群

    ​ 3.增加多个消费者节点进行消费堆积消息

    ​ 4.消费完毕后恢复原始架构

    消息过期如何处理

    什么是消息过期:为了保证消息不被积压,消息设置过期时间。

    消息过期的处理方案:

    ​ 1.过期消息放入死信队列

    ​ 2.启动专门的消费者消费死信队列消息,并写入到数据库记录日志

    ​ 3.查询数据库消息日志,重新发送消息到MQ

    展开全文
  • 面试题系列之消息队列面试题1、为什么使用MQ?MQ的优点1.1、解耦1.2、异步1.3、削峰2、消息队列有什么缺点?3、你们公司生产环境用的是什么消息中间件?4、MQ 有哪些常见问题?如何解决这些问题?4.1、消息的顺序...

    1、为什么使用MQ?MQ的优点

           主要是:解耦、异步、削峰。

    1.1、解耦

           A 系统发送数据到 BCD 三个系统,通过接口调用发送。如果 E 系统也要这个数据呢?那如果 C 系统现在不需要了呢?A 系统负责人几乎崩溃…A 系统跟其它各种乱七八糟的系统严重耦合,A 系统产生一条比较关键的数据,很多系统都需要 A 系统将这个数据发送过来。如果使用 MQ,A 系统产生一条数据,发送到 MQ 里面去,哪个系统需要数据自己去 MQ 里面消费。如果新系统需要数据,直接从 MQ 里消费即可;如果某个系统不需要这条数据了,就取消对 MQ 消息的消费即可。这样下来,A 系统压根儿不需要去考虑要给谁发送数据,不需要维护这个代码,也不需要考虑人家是否调用成功、失败超时等情况。
           就是一个系统或者一个模块,调用了多个系统或者模块,互相之间的调用很复杂,维护起来很麻烦。但是其实这个调用是不需要直接同步调用接口的,如果用 MQ 给它异步化解耦。

    1.2、异步

           A 系统接收一个请求,需要在自己本地写库,还需要在 BCD 三个系统写库,自己本地写库要 3ms,BCD 三个系统分别写库要 300ms、450ms、200ms。最终请求总延时是 3 + 300 + 450 + 200 = 953ms,接近 1s,用户感觉搞个什么东西,慢死了慢死了。用户通过浏览器发起请求。如果使用 MQ,那么 A 系统连续发送 3 条消息到 MQ 队列中,假如耗时 5ms,A 系统从接受一个请求到返回响应给用户,总时长是 3 + 5 = 8ms。

    1.3、削峰

           减少高峰时期对服务器压力。

    2、消息队列有什么缺点?

    1. 系统可用性降低:
      本来系统运行好好的,现在你非要加入个消息队列进去,那消息队列挂了,你的系统不是呵呵了。因此,系统可用性会降低;
    2. 系统复杂度提高:
      加入了消息队列,要多考虑很多方面的问题,比如:一致性问题、如何保证消息不被重复消费、如何保证消息可靠性传输等。因此,需要考虑的东西更多,复杂性增大。
    3. 一致性问题:
      A 系统处理完了直接返回成功了,人都以为你这个请求就成功了;但是问题是,要是 BCD 三个系统那里,BD 两个系统写库成功了,结果 C 系统写库失败了,咋整?你这数据就不一致了。

           所以消息队列实际是一种非常复杂的架构,你引入它有很多好处,但是也得针对它带来的坏处做各种额外的技术方案和架构来规避掉,做好之后,你会发现,妈呀,系统复杂度提升了一个数量级,也许是复杂了 10 倍。但是关键时刻,用,还是得用的。

    3、你们公司生产环境用的是什么消息中间件?

           这个首先你可以说下你们公司选用的是什么消息中间件,比如用的是RabbitMQ,然后可以初步给一些你对不同MQ中间件技术的选型分析。
           比如说ActiveMQ是老牌的消息中间件,国内很多公司过去运用的还是非常广泛的,功能很强大。但是问题在于没法确认ActiveMQ可以支撑互联网公司的高并发、高负载以及高吞吐的复杂场景,在国内互联网公司落地较少。而且使用较多的是一些传统企业,用ActiveMQ做异步调用和系统解耦。
           RabbitMQ的好处在于可以支撑高并发、高吞吐、性能很高,同时有非常完善便捷的后台管理界面可以使用。另外,他还支持集群化、高可用部署架构、消息高可靠支持,功能较为完善。而且经过调研,国内各大互联网公司落地大规模RabbitMQ集群支撑自身业务的case较多,国内各种中小型互联网公司使用RabbitMQ的实践也比较多。除此之外,RabbitMQ的开源社区很活跃,较高频率的迭代版本,来修复发现的bug以及进行各种优化,因此综合考虑过后,公司采取了RabbitMQ。但是RabbitMQ也有一点缺陷,就是他自身是基于erlang语言开发的,所以导致较为难以分析里面的源码,也较难进行深层次的源码定制和改造,毕竟需要较为扎实的erlang语言功底才可以。
           RocketMQ是阿里开源的,经过阿里的生产环境的超高并发、高吞吐的考验,性能卓越,同时还支持分布式事务等特殊场景。而且RocketMQ是基于Java语言开发的,适合深入阅读源码,有需要可以站在源码层面解决线上生产问题,包括源码的二次开发和改造。
           Kafka提供的消息中间件的功能明显较少一些,相对上述几款MQ中间件要少很多。但是Kafka的优势在于专为超高吞吐量的实时日志采集、实时数据同步、实时数据计算等场景来设计。因此Kafka在大数据领域中配合实时计算技术(比如Spark Streaming、Storm、Flink)使用的较多。但是在传统的MQ中间件使用场景中较少采用。

    4、MQ 有哪些常见问题?如何解决这些问题?

    4.1、消息的顺序问题

           消息有序指的是可以按照消息的发送顺序来消费。假如生产者产生了 2 条消息:M1、M2,假定 M1 发送到 S1,M2 发送到 S2,如果要保证 M1 先于 M2 被消费,怎么做?
    在这里插入图片描述
    解决方案:
    (1)保证生产者 - MQServer - 消费者是一对一对一的关系
    在这里插入图片描述
    缺陷:

    1. 并行度就会成为消息系统的瓶颈(吞吐量不够)
    2. 更多的异常处理,比如:只要消费端出现问题,就会导致整个处理流程阻塞,我们不得不花费更多的精力来解决阻塞的问题。 (2)通过合理的设计或者将问题分解来规避。
    3. 不关注乱序的应用实际大量存在
    4. 队列无序并不意味着消息无序 所以从业务层面来保证消息的顺序而不仅仅是依赖于消息系统,是一种更合理的方式。

    4.2、消息的重复问题

           造成消息重复的根本原因是:网络不可达。所以解决这个问题的办法就是绕过这个问题。那么问题就变成了:如果消费端收到两条一样的消息,应该怎样处理?
           消费端处理消息的业务逻辑保持幂等性。只要保持幂等性,不管来多少条重复消息,最后处理的结果都一样。保证每条消息都有唯一编号且保证消息处理成功与去重表的日志同时出现。利用一张日志表来记录已经处理成功的消息的 ID,如果新到的消息 ID 已经在日志表中,那么就不再处理这条消息。

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

           消息积压处理办法: 临时紧急扩容:

    1. 先修复 consumer 的问题,确保其恢复消费速度,然后将现有 cnosumer 都停掉。
    2. 新建一个 topic,partition 是原来的 10 倍,临时建立好原先 10 倍的 queue 数量。
    3. 然后写一个临时的分发数据的 consumer 程序,这个程序部署上去消费积压的数据,消费之后不做耗时的处理,直接均匀轮询写入临时建立好的 10 倍数量的 queue。
    4. 接着临时征用 10 倍的机器来部署 consumer,每一批 consumer 消费一个临时 queue 的数据。这种做法相当于是临时将 queue 资源和 consumer 资源扩大 10 倍,以正常的 10 倍速度来消费数据。
    5. 等快速消费完积压数据之后,得恢复原先部署的架构,重新用原先的 consumer 机器来消费消息。

           MQ中消息失效: 假设你用的是 RabbitMQ,RabbtiMQ 是可以设置过期时间的,也就是 TTL。如果消息在 queue 中积压超过一定的时间就会被 RabbitMQ 给清理掉,这个数据就没了。那这就是第二个坑了。这就不是说数据会大量积压在 mq 里,而是大量的数据会直接搞丢。我们可以采取一个方案,就是批量重导,这个我们之前线上也有类似的场景干过。就是大量积压的时候,我们当时就直接丢弃数据了,然后等过了高峰期以后,比如大家一起喝咖啡熬夜到晚上12点以后,用户都睡觉了。这个时候我们就开始写程序,将丢失的那批数据,写个临时程序,一点一点的查出来,然后重新灌入 mq 里面去,把白天丢的数据给他补回来。也只能是这样了。假设 1 万个订单积压在 mq 里面,没有处理,其中 1000 个订单都丢了,你只能手动写程序把那 1000 个订单给查出来,手动发到 mq 里去再补一次。
           mq消息队列块满了: 如果消息积压在 mq 里,你很长时间都没有处理掉,此时导致 mq 都快写满了,咋办?这个还有别的办法吗?没有,谁让你第一个方案执行的太慢了,你临时写程序,接入数据来消费,消费一个丢弃一个,都不要了,快速消费掉所有的消息。然后走第二个方案,到了晚上再补数据吧。

    5、设计MQ思路

           首先这个 mq 得支持可伸缩性吧,就是需要的时候快速扩容,就可以增加吞吐量和容量,那怎么搞?设计个分布式的系统呗,参照一下 kafka 的设计理念,broker -> topic -> partition,每个 partition 放一个机器,就存一部分数据。如果现在资源不够了,简单啊,给 topic 增加 partition,然后做数据迁移,增加机器,不就可以存放更多数据,提供更高的吞吐量了?
           其次你得考虑一下这个 mq 的数据要不要落地磁盘吧?那肯定要了,落磁盘才能保证别进程挂了数据就丢了。那落磁盘的时候怎么落啊?顺序写,这样就没有磁盘随机读写的寻址开销,磁盘顺序读写的性能是很高的,这就是 kafka 的思路。
           其次你考虑一下你的 mq 的可用性啊?这个事儿,具体参考之前可用性那个环节讲解的 kafka 的高可用保障机制。多副本 -> leader & follower -> broker 挂了重新选举 leader 即可对外服务。


    6、往期佳文

    6.1、面试系列

    1、吊打面试官之一面自我介绍
    2、吊打面试官之一面项目介绍
    3、吊打面试官之一面系统架构设计
    4、吊打面试官之一面你负责哪一块
    5、吊打面试官之一面试官提问
    6、吊打面试官之一面你有什么问题吗

    ······持续更新中······

    6.2、技术系列

    1、吊打面试官之分布式会话
    2、吊打面试官之分布式锁
    3、吊打面试官之乐观锁
    4、吊打面试官之幂等性问题
    5、吊打面试关之分布式事务
    6、吊打面试官之项目线上问题排查

    ······持续更新中······

    6.3、源码系列

    1、源码分析之SpringBoot启动流程原理
    2、源码分析之SpringBoot自动装配原理
    3、源码分析之ArrayList容器
    4、源码分析之LinkedList容器
    5、源码分析之HashMap容器
    6、源码分析之ConcurrentHashMap容器
    7、源码分析之五种Map容器的区别

    ······持续更新中······

    6.4、数据结构和算法系列

    1、数据结构之八大数据结构
    2、数据结构之动态查找树(二叉查找树,平衡二叉树,红黑树)

    ······持续更新中······

    6.5、并发系列

    1、并发系列之初识多线程
    2、并发系列之JMM内存模型
    3、并发系列之synchronized解析
    4、并发系列之volatile解析
    5、并发系列之synchronized与volatile的区别
    6、并发系列之Lock解析
    7、并发系列之synchronized与lock的区别
    8、并发系列之CAS与原子操作
    9、并发系列之AQS分析
    10、并发系列之线程池解析
    11、并发系列之锁的知识梳理

    ······持续更新中······

    6.6、面试题系列

    1、面试题系列之并发面试题
    2、面试题系列之网络面试题
    3、面试题系列之IO面试题

    ······持续更新中······

    5.7、JVM系列

    1、JVM系列之JVM介绍
    2、JVM系列之Class文件解析
    3、JVM系列之Java 类加载机制
    4、JVM系列之JVM内存结构

    ······持续更新中······


    展开全文
  • 常见消息队列面试题

    2021-02-19 12:36:50
    常见消息队列面试题 1.为什么要用消息队列?(消息队列的应用场景?) 消息队列的本质? 消息队列是一种“先进先出”的数据结构,一般用其作为数据的传递 常见的应用场景:解耦,异步以及削峰 解耦: 场景:双11是...

    常见消息队列面试题

    1.为什么要用消息队列?(消息队列的应用场景?)

    消息队列的本质?

    消息队列是一种“先进先出”的数据结构,一般用其作为数据的传递

    常见的应用场景:解耦,异步以及削峰

    解耦:

    场景:双11是购物狂节,用户下单后,订单系统需要通知库存系统,传统的做法就是订单系统调用库存系统的接口.
    在这里插入图片描述

    这种做法有一个缺点:

    当库存系统出现故障时,订单就会失败。 订单系统和库存系统高耦合. 引入消息队列

    在这里插入图片描述

    订单系统: 用户下单后,订单系统完成持久化处理,将消息写入消息队列,返回用户订单下单成功。

    库存系统订阅下单的消息,获取下单消息,进行库操作。 就算库存系统出现故障,消息队列也能保证消息的可靠投递,不会导致消息丢失.

    异步

    场景说明: 用户注册后,需要发注册邮件和注册短信,传统的做法有两种 1.串行的方式 2.并行的方式

    串行方式:将注册信息写入数据库后,发送注册邮件,再发送注册短信,以上三个任务全部完成后才返回给客户端。 这有一个问题是,邮件,短信并不是必须的,它只是一个通知,而这种做法让客户端等待没有必要等待的东西.

    在这里插入图片描述

    并行方式:将注册信息写入数据库后,发送邮件的同时,发送短信,以上三个任务完成后,返回给客户端,并行的方式能提高处理的时间。

    在这里插入图片描述

    消息队列:假设三个业务节点分别使用50ms,串行方式使用时间150ms,并行使用时间100ms。虽然并行已经提高的处理时间,但是,前面说过,邮件和短信对我正常的使用网站没有任何影响,客户端没有必要等着其发送完成才显示注册成功,应该是写入数据库后就返回.
    消息队列: 引入消息队列后,把发送邮件,短信不是必须的业务逻辑异步处理

    在这里插入图片描述

    由此可以看出,引入消息队列后,用户的响应时间就等于写入数据库的时间+写入消息队列的时间(可以忽略不计),引入消息队列后处理后,响应时间是串行的3倍,是并行的2倍。

    削峰

    场景:秒杀活动,一般因为流量过大,导致应用挂掉,为了解决这个问题,一般在应用前端加入消息队列。

    作用:
    1.可以控制活动人数,超过此一定阀值的订单直接丢弃

    2.可以缓解短时间的高流量压垮应用(应用程序按自己的最大处理能力获取订单)

    在这里插入图片描述

    1.用户的请求,服务器收到之后,首先写入消息队列,加入消息队列长度超过最大值,则直接抛弃用户请求或跳转到错误页面.

    2.秒杀业务根据消息队列中的请求信息,再做后续处理.

    2.各种消息队列产品的比较

    # 1.ActiveMQ
    		ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线。它是一个完全支持JMS规范的的消息中间件。丰富的API,多种集群架构模式让ActiveMQ在业界成为老牌的消息中间件,在中小型企业颇受欢迎!
    
    # 2.Kafka
    		Kafka是LinkedIn开源的分布式发布-订阅消息系统,目前归属于Apache顶级项目。Kafka主要特点是基于Pull的模式来处理消息消费,追求高吞吐量,一开始的目的就是用于日志收集和传输。0.8版本开始支持复制,不支持事务,对消息的重复、丢失、错误没有严格要求,适合产生大量数据的互联网服务的数据收集业务。
    
    # 3.RocketMQ
    		RocketMQ是阿里开源的消息中间件,它是纯Java开发,具有高吞吐量、高可用性、适合大规模分布式系统应用的特点。RocketMQ思路起源于Kafka,但并不是Kafka的一个Copy,它对消息的可靠传输及事务性做了优化,目前在阿里集团被广泛应用于交易、充值、流计算、消息推送、日志流式处理、binglog分发等场景。
    
    # 4.RabbitMQ
    		RabbitMQ是使用Erlang语言开发的开源消息队列系统,基于AMQP协议来实现。AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。AMQP协议更多用在企业系统内对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在,其次,RabbitMQ比Kafka可靠,Kafka更适合IO高吞吐的处理,一般应用在大数据日志处理或对实时性(少量延迟),可靠性(少量丢数据)要求稍低的场景使用,比如ELK日志收集。
    		
    

    3.消息队列的优点和缺点

    缺点:

    1)系统可用性降低

    外部依赖的系统多了,增加了消息队列系统。

    答案 问题4

    2)系统复杂度提高

    你怎么保证消息没有重复消费?

    答案 问题6

    怎么处理消息丢失的情况?

    答案 问题5

    怎么保证消息传递的顺序性?

    答案 问题7

    3)一致性问题

    数据可能不一致。

    答案 : 使用分布式事务实现消息一致性

    优点:解耦,异步,削峰

    4.如何保证消息队列的高可用

    保证消息队列的高可用, 集群

    RabbitMQ集群分为普通集群和镜像集群

    普通集群:

    创建的Queue只会放在一个RabbitMQ上,其他实例都同步元数据,如果实际数据宕机,元数据无法访问实际数据,其他实例也就无法同步,他并不能做到高可用,只不过是对Quene中信息,进行备份,缓解访问压力

    镜像集群:

    每次生产者写消息到queue的时候,都会自动把消息同步到多个实例的queue上,每个RabbitMq节点上都有Queue的消息数据和元数据,某一个节点宕机,其他节点依然保存完整数据,不影响客户端消费,类似于redis中的哨兵模式

    上面说的是rabbitMQ集群 ,那RocketMQ如何保证高可用呢?

    双主双从

    5.如何保证消息不丢失

    消息丢失原因?

    情况一:消息生产者没有成功发送到MQ(发送过程成丢失)

    情况二:消息发送给了MQ后,MQ宕机导致内存中的消息数据丢失

    情况三:消费者消费到了消息,但是没有处理完毕就出现异常导致丢失

    如何保证消息不丢失?

    1.消息发送者发送给MQ后,MQ给生产者确认收到

    2.MQ收到消息后进行消息持久化

    3.消费者收到消息处理完毕后手动ack确定,不要自动ack确认

    4.MQ收到消费者ack确认后删除持久化的消息

    6.如何保证消息不被重复消费?(如何保证消息消费的幂等性?)

    产生重复消息的原因:

    根本原因: 网络不可达

    发送时消息重复:当生产者发送消息给MQ 中途出现网络的抖动等其他原因,导致服务端对客户端应答失败。如果此时生产者意识到消息发送失败,再次发送,消费者会收到两条内容相同的消息

    消费是消息重复: 消息已经投递到了消费者并完成业务处理,当消费方给MQ服务端反馈应答的时候网络闪断。为了保证消息至少被消费一次,MQ服务端将在网络恢复后再次尝试投递之前已被消费方处理过的消息,此时消费者就会收到两条内容相同的消息

    我们不能保证网络100%通畅,所有必定会存在重复消息

    解决办法:

    1.消息发送者发送消息时携带一个全局唯一id

    2.消费者获取消费后先根据id在redis/db中查询是否存在消费记录

    3.如果没有消费过就正常消费,消费完毕后写入redis/db

    4.如果消息消费过就直接舍弃

    7.如何保证消息消费的顺序性?

    消息有序指的是可以按照消息的发送顺序来消费

    分为全局顺序消息和局部顺序消息,常见的是局部顺序消息

    RabbitMQ

    全局顺序消息

    生产者:MQ:消费者=1:1:1

    这种消费能保证消息顺序到达MQ,也可以保证消息顺序消费

    但是,他的吞吐量会下降,容错性降低,全局的顺序消费,不常见

    RocketMQ

    局部顺序消费:

    1.生产者根据消息ID将同一组消息发送到一个Queue中。

    2.多个消费者同时获取Queue中的消息进行消费。

    3.MQ使用分段锁保证单个Queue中的有序消费

    8.大量消息堆积处理怎么处理?

    消费方出现了故障导致消息没有正常消费:

    1.网络故障

    2.消费方处理消息后没有给MQ Server正常应答

    消息堆积的处理方案

    1.检查并修复消费方的正常消费速度

    2.将堆积消息转存到容量更大的MQ集群

    3.增加多个消费者节点并行消费堆积消息

    4.消费完毕后,恢复原始架构

    9.消息过期怎么处理?

    消息过期的原因:

    消息设置了过期时间,如果超时还未被消费,则视为消息过期,过期消息可以转存到死信队列(如果没有配置死信队列,则该消息被删了)

    消息过期的处理方案:

    1.设置死信队列,接收过期消息

    2.启动专门的消费者消费死信队列消息

    3.查询数据库消息日志,重新发送消息到MQ

    展开全文
  • 消息队列面试题要点

    2020-09-17 23:47:10
    消息队列面试题要点 复习要点 本文主要围绕如下几点进行阐述: 为什么使用消息队列? 使用消息队列有什么缺点? 消息队列如何选型? 如何保证消息队列是高可用的? 如何保证消息不被重复消费? 如何保证...

    消息队列面试题要点

    复习要点

    本文主要围绕如下几点进行阐述:

    1. 为什么使用消息队列?
    2. 使用消息队列有什么缺点?
    3. 消息队列如何选型?
    4. 如何保证消息队列是高可用的?
    5. 如何保证消息不被重复消费?
    6. 如何保证消费的可靠性传输?
    7. 如何保证消息的顺序性?

    下面围绕以上七点进行阐述。需要说明一下,本文不是《消息队列从入门到精通》这种教程,因此只是提供一个复习思路,而不是去教你们怎么调用消息队列的API。建议对消息队列不了解的人,去找点消息队列的博客看看,再看本文,收货更新。

    正文

    1.为什么要使用消息队列

    分析:一个用消息队列的人,不知道为啥用,这就有点尴尬、没有复习这点,很容易被问蒙,然后就开始胡扯了。

    回答:这个问题,咱只答三个最主要的应用场景(不可否认还有掐的,但是只答三个主要的),即以下六个字:解耦、异步、削峰

    (1)解耦
    传统模式:

     

    传统模式的缺点:

    • 系统间耦合性太强,如上图所示,系统A在代码中直接调用系统B和系统C的代码,如果将来D系统接入,系统A还需要修改代码,过于麻烦!

    中间件模式:

     

    中间件模式的优点:

    • 将消息写入消息队列,需要消息的系统自己从消息队列中订阅,从而系统A不需要做任何修改。

    (2)异步
    传统模式:

     


    传统模式的缺点:

    • 一些非必要的业务逻辑以同步的方式运行,太耗费时间。

    中间件模式:

     

    中间件模式的优点:

    • 将消息写入消息队列,非必要的业务逻辑以异步的方式运行,加快相应速度

    (3)削峰
    传统模式:

     

     

    传统模式的缺点:

    • 并发量大的时间,所有的请求直接怼到数据库,造成数据库连接异常

    中间件模式:

     

    中间件模式的优点:

    • 系统A慢慢的按照数据库能处理的并发量,从消息队列中慢慢拉取消息。在生产中,这个短暂的高峰期积压是允许的。

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

    分析:一个使用了MQ的项目,如果连这个问题都没有考虑过,就把MQ引进来了,那就给自己的项目带来了风险。我们引入一个技术,要对这个技术的弊端有充分的认识,才能做好预防。要记住,不要给公司挖坑!

    回答:可以从连个角度来思考

    • 系统可用性降低:你想呀,本来其他系统只要运行好好的,那你的系统就是正常的。现在你非要加入个消息队列进去,那消息队列挂了,你的系统不是呵呵了。因此,系统可用性会降低
    • 系统复杂性增加:加入了消息队列,要多考虑很多方面的问题,比如:一致性问题、如何保证消息不被重复消费、如何保证消息可靠性传输等。因此,需要考虑的东西更多,刺痛复杂性增大。

    但是,我们该用的还是要用的。

    3.消息队列如何选型?

    先交个底,博主只会ActiveMQ,RabbitMQ,RocketMQ,Kafka,对什么ZeroMQ或其他的MQ没啥理解,因此只能基于这四种MQ给出回答。

    分析:既然在项目中用了MQ,肯定事先要对业界流行的MQ进行调研,如果连每种MQ的优缺点都没没了解清楚,就拍脑袋依据喜好来选用某种MQ,这是给项目挖坑。如果面试官问:你为什么用这种MQ?你直接回答:领导决定的。这种回答就是很LOW。还是那句话,不要给公司挖坑。

    回答:首先,咱先上ActiveMQ的社区,看看该MQ的更新频率:

    Apache ActiveMQ 5.15.3 Release
    Christopher L. Shannon posted on Feb 12, 2018
    Apache ActiveMQ 5.15.2 Released
    Christopher L. Shannon posted on Oct 23, 2017
    Apache ActiveMQ 5.15.0 Released
    Christopher L. Shannon posted on Jul 06, 2017
    省略以下记录

    我们可以看出,ActiveMQ几个月才发一次版本,据说研究重心在他们的下一代产品Apollo。

    接下来,我们再去RabbitMQ的社区去看一下,RabbitMQ的更新频率

    RabbitMQ 3.7.3 release  30 January 2018
    RabbitMQ 3.6.15 release  17 January 2018
    RabbitMQ 3.7.2 release23 December 2017
    RabbitMQ 3.7.1 release21 December 2017
    省略以下记录
    ...

    我们可以看出,RabbitMQ版本发布比ActiveMq频繁很多。至于RocketMQ和kafka就不带大家看了,总之也比ActiveMQ活跃的多。详情,可自行查阅。

    特性 ActiveMQ RabbitMQ RocketMQ kafka
    开发语言 java erlang java scala
    单机吞吐量 万级 万级 10万级 10万级
    时效性 ms级 us级 ms级 ms级以内
    可用性 高(主从架构) 高(主从架构) 非常高(分布式架构) 非常高(分布式架构)
    功能特性 成熟的产品,在很多公司得到应用;有较多的文档;各种协议支持较好 基于erlang开发,所以并发能力很强,性能极其好,延时很低;管理界面较丰富 MQ功能比较完备,扩展性佳 只支持主要的MQ功能,像一些消息查询,消息回溯等功能没有提供,毕竟是为大数据准备的,在大数据领域应用广。

    综合上面的材料得出以下两点:
    (1)中小型软件公司,建议选RabbitMQ.一方面,erlang语言天生具备高并发的特性,而且他的管理界面用起来十分方便。正所谓,成也萧何,败也萧何!他的弊端也在这里,虽然RabbitMQ是开源的,然而国内有几个能定制化开发erlang的程序员呢?所幸,RabbitMQ的社区十分活跃,可以解决开发过程中遇到的bug,这点对于中小型公司来说十分重要。不考虑rocketmq和kafka的原因是,一方面中小型软件公司不如互联网公司,数据量没那么大,选消息中间件,应首选功能比较完备的,所以kafka排除。不考虑rocketmq的原因是,rocketmq是阿里出品,如果阿里放弃维护rocketmq,中小型公司一般抽不出人来进行rocketmq的定制化开发,因此不推荐。

    (2)大型软件公司,根据具体使用在rocketMq和kafka之间二选一。一方面,大型软件公司,具备足够的资金搭建分布式环境,也具备足够大的数据量。针对rocketMQ,大型软件公司也可以抽出人手对rocketMQ进行定制化开发,毕竟国内有能力改JAVA源码的人,还是相当多的。至于kafka,根据业务场景选择,如果有日志采集功能,肯定是首选kafka了。具体该选哪个,看使用场景。

    4.如何保证消息队列是高可用的

    分析:在第二点说过了,引入消息队列后,系统的可用性下降。在生产中,没人使用单机模式的消息队列。因此,一个合格的程序员,应该对消息队列的高可用有很深刻的了解。如果面试的时候,面试官问,你们的消息队列是如何保证高可用的?你的回答只是表明自己只会订阅和发布消息,面试官就会怀疑你是不是只是自己搭着完,压根没在生产用过。请做一个爱思考,会思考,懂思考的程序员。

    回答:这问题,其实要对消息队列的集群模式要有深刻了解,才好回答。

    以RocketMQ为例:他的集群就有多master模式、多master多slave异步复制模式、多master多slave同步双写模式。多master多slave模式部署架构图(图网上找的,偷个懒,懒得画):

     

    其实博主第一眼看到这个图,就觉得和Kafka好像,只是NameServer集群,就在Kafka中是用zookeeper代替,都是用来保存和发现master和slave用的。通信过程如下:

    Producer 与 NameServer集群中的其中一个节点(随机选择)建立长连接,定期从 NameServer 获取 Topic 路由信息,并向提供 Topic 服务的 Broker Master 建立长连接,且定时向 Broker 发送心跳。Producer 只能将消息发送到 Broker master,但是 Consumer 则不一样,它同时和提供 Topic 服务的 Master 和 Slave建立长连接,既可以从 Broker Master 订阅消息,也可以从 Broker Slave 订阅消息。

    那么kafka呢,为了对比说明,直接上kafka的拓扑架构图(也是找的,懒得画)

     

    如上图所示,一个典型的Kafka集群中包含若干Producer(可以是web前端产生的Page View,或者是服务器日志,系统CPU、Memory等),若干broker(Kafka支持水平扩展,一般broker数量越多,集群吞吐率越高),若干Consumer Group,以及一个Zookeeper集群。Kafka通过Zookeeper管理集群配置,选举leader,以及在Consumer Group发生变化时进行rebalance。Producer使用push模式将消息发布到broker,Consumer使用pull模式从broker订阅并消费消息。
    至于rabbitMQ,也有普通集群和镜像集群模式,自行去了解,比较简单,两小时即懂。

    要求,在回答高可用的问题时,应该能逻辑清晰的画出自己的MQ集群架构或清晰的叙述出来。

    5.如何保证消息不被重复消费

    分析:这个问题其实换一种问法就是,如何保证消息队列的幂等性?这个问题可以认为是消息队列领域的基本问题。换句话来说,是在考察你的设计能力,这个问题的回答可以根据具体的业务场景来答,没有固定的答案。

    回答:先来说一下为什么会造成重复消费?
    其实无论是哪种消息队列,造成重复消费原因其实都是类似的。正常情况下,消费者在消费消息的时候,消费完毕后,会发送一个确认消息给消息队列,消息队列就知道该消息被消费了,就会将该消息从消息队列中删除。只是不同的消息队列发出的确认消息形式不同,例如RabbitMQ是发送一个ACK确认消息,RocketMQ是返回一个CONSUME_SUCCESS成功标志,kafka实际上有个offet的概念,简单说一下,就是每一个消息都有一个offset,kafka消费过消息后,需要提交offset,让消息队列知道自己已经消费过了。

    那造成重复消费的原因?,就是因为网络传输等等故障,确认信息没有传送到消息队列,导致消息队列不知道自己已经消费过该消息了,再次将消息分发给其他的消费者。

    如何解决?这个问题针对业务场景来答,分以下三种情况:

    (1)比如,你拿到这个消息做数据库的insert操作,那就容易了,给这个消息做一个唯一的主键,那么就算出现重复消费的情况,就会导致主键冲突,避免数据库出现脏数据。

    (2)再比如,你拿到这个消息做redis的set的操作,那就容易了,不用解决,因为你无论set几次结果都是一样的,set操作本来就算幂等操作。

    (3)如果上面两种情况还不行,上大招。准备一个第三方介质,来做消费记录。以redis为例,给消息分配一个全局id,只要消费过该消息,将<id,message>以K-V形式写入redis.那消费者开始消费前,先去redis中查询有没有消费记录即可。

    6.如何保证消费的可靠性传输?

    分析:我们在使用消息队列的过程中,应该做到消息不能多消费,也不能少消费。如果无法做到可靠性传输,可能给公司带来千万级别的财产损失。同样的,如果可靠性传输在使用过程中,没有考虑到,这不是给公司挖坑麽,你可以拍拍屁股走人,公司损失的钱,谁承担。还是那句话,认真对待每一个项目,不要给公司挖坑。

    回答:其实这个可靠性传输,每种MQ都要从三个角度来分析:

    • 生产者弄丢数据
    • 消息队列弄丢数据
    • 消费者弄丢数据

    (1)生产者丢数据
    从生产者弄丢数据这个角度来看,RabbitMQ提供transaction和confirm模式来确保生产者不丢消息。

    transaction机制就是说,发送消息前,开启事务(channel.txSelect()),然后发送消息,如果发送过程中出现什么异常,事务就会回滚(channel.txRollback()),如果发送成功则提交事务(channel.txCommit())。

    然而,这种方式有个缺点:吞吐量下降。因为,按照经验,生产上用confirm模式的居多。一旦channel进入confirm模式,所有在该信道上发布的消息都将会被指派一个唯一的ID(从1开始),一旦消息被投递到所有匹配的队列之后,rabbitMQ就会发送一个ACK给生产者(包含消息的唯一ID),这就使得生产者知道消息已经正确到达目的队列了。如果rabbitMQ没能处理该消息,则会发送一个Nack消息给你,你可以进行重试操作。处理Ack和Nack的代码如下所示:

    channel.addConfirmListener(new ConfirmListener() {  
                    @Override  
                    public void handleNack(long deliveryTag, boolean multiple) throws IOException {  
                        System.out.println("nack: deliveryTag = "+deliveryTag+" multiple: "+multiple);  
                    }  
                    @Override  
                    public void handleAck(long deliveryTag, boolean multiple) throws IOException {  
                        System.out.println("ack: deliveryTag = "+deliveryTag+" multiple: "+multiple);  
                    }  
                });  

    (2)消息队列丢数据

    处理消息队列丢数据的情况,一般是开启持久化磁盘的配置。这个持久化配置可以和confirm机制配合使用,你可以在消息持久化磁盘后,再给生产者发送一个Ack信号。这样,如果消息持久化磁盘之前,rabbitMQ阵亡了,那么生产者收不到Ack信号,生产者会自动重发。

    那么如何持久化呢,这里顺便说一下吧,其实也很容易,就下面两步

    1. 将queue的持久化标识durable设置为true,则代表是一个持久的队列
    2. 发送消息的时候将deliveryMode=2

    这样设置以后,即使rabbitMQ挂了,重启后也能恢复数据

    (3)消费者丢数据

    消费者丢数据一般是因为采用了自动确认消息模式。这种模式下,消费者会自动确认收到信息。这时rabbitMQ会立即将消息删除,这种情况下,如果消费者出现异常而未能处理消息,就会丢失该消息。

    至于解决方案,采用手动确认消息即可。

    7.如何保证消息的顺序性

    分析:其实并非所有的公司都有这种业务需求,但是还是对这个问题要有所复习。

    回答:针对这个问题,通过某种算法,将需要保持先后顺序的消息放到同一个消息队列中(kafka中就是partition,rabbitMq中就是queue)。然后只用一个消费者去消费该队列。
    有的人会问:那如果为了吞吐量,有多个消费者去消费怎么办?

    这个问题,没有固定回答的套路。比如我们有一个微博的操作,发微博、写评论、删除微博,这三个异步操作。如果是这样一个业务场景,那只要重试就行。比如你一个消费者先执行了写评论的操作,但是这时候,微博都还没发,写评论一定是失败的,等一段时间。等另一个消费者,先执行写评论的操作后,再执行,就可以成功。

    总之,针对这个问题,我的观点是保证入队有序就行,出队以后的顺序交给消费者自己去保证,没有固定套路。

    展开全文
  • 消息队列面试题汇总

    2020-02-08 08:25:06
    消息队列面试题汇总 1.消息队列的应用场景有哪些? 答:消息队列的应用场景如下。 应用解耦,比如,用户下单后,订单系统需要通知库存系统,假如库存系统无法访问,则订单减库存将失败,从而导致订单失败。订单系统...
  • 消息队列面试题详解

    2020-05-09 15:18:09
    消息队列面试题详解 1.为什么要使用消息队列?(消息队列的应用场景) 解耦,异步(可以提高响应请求),削峰(经济实用性的考量) 2.各种消息产品的比较 ActiveMQ,早起使用的较多,没经过大规模吞吐量场景的验证,...
  • Java笔试面试-消息队列面试题总结

    万次阅读 多人点赞 2019-09-26 15:10:12
    1.消息队列的应用场景有哪些? 答:消息队列的应用场景如下。 应用解耦,比如,用户下单后,订单系统需要通知库存系统,假如库存系统无法访问,则订单减库存将失败,从而导致订单失败。订单系统与库存系统耦合,这...
  • 消息队列面试题及答案

    万次阅读 2019-11-27 15:48:36
    1、为什么使用消息队列消息队列使用的场景和中间件有很多,但解决的核心问题主要是:异步、解耦、消峰填谷。 2、消息队列的优缺点 异步、解耦、消峰填谷这是消息队列最大的优点,除了这些消息队列还可以会解决...
  • 消息队列面试题分析

    2019-10-05 01:25:17
    1、面试题 (1)为什么使用消息队列啊? (2)消息队列有什么优点和缺点啊? (3)kafka、activemq、rabbitmq、rocketmq都有什么区别以及适合哪些场景? 2、面试官心理分析 (1)第一,你知道不知道你们系统里...
  • 我是如何回答的2.1 你用过消息中间件么2.2 你为什么使用MQ2.3 使用了消息队列会有什么优缺点2.4 kafka、activemq、rabbitmq、rocketmq都有什么区别以及适合哪些场景5. 如何保证消息不被重复消费&&如何解决丢...
  • 面试题 为什么使用消息队列消息队列有什么优点和缺点? Kafka、ActiveMQ、RabbitMQ、RocketMQ 都有什么区别,以及适合哪些场景? 面试官心理分析 其实面试官主要是想看看: 第一,你知不知道你们系统里为...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,584
精华内容 633
关键字:

消息队列面试题