Mr. Cappuccino的第27杯咖啡——金三银四面试题之消息中间件篇

金三银四面试题之消息中间件篇

        • 1. 常用的消息中间件有哪些?
        • 2. 消息中间件可以解决哪些问题?
        • 3. 为什么MQ可以解决流量削峰问题?
        • 4. RabbitMQ常用的队列模型有哪些?
        • 5. RabbitMQ有哪几种交换器类型?
        • 6. MQ宕机的情况下,消息是否会丢失?
        • 7. MQ的应用场景有哪些?
        • 8. MQ如何保证消息不丢失?
        • 9. MQ 如何保证消息幂等问题?
        • 10. MQ如何避免消息堆积的问题?
        • 11. 生产者投递消息,MQ宕机了(满了)如何处理?
        • 12. 消费者消费消息时报错了,如何处理?
        • 13. MQ如何保证消息顺序一致性问题?

1. 常用的消息中间件有哪些?

  1. ActiveMQ 的社区算是比较成熟,但是较目前来说,ActiveMQ 的性能比较差,而且版本迭代很慢,不推荐使用。
  2. RabbitMQ 在吞吐量方面虽然稍逊于 Kafka 和 RocketMQ ,但是由于它基于 erlang 开发,所以并发能力很强,性能极其好,延时很低,达到微秒级。但是也因为 RabbitMQ 基于 erlang 开发,所以国内很少有公司有实力做erlang源码级别的研究和定制。如果业务场景对并发量要求不是太高(十万级、百万级),那这四种消息队列中,RabbitMQ 一定是你的首选。如果是大数据领域的实时计算、日志采集等场景,用 Kafka 是业内标准的,绝对没问题,社区活跃度很高,绝对不会黄,何况几乎是全世界这个领域的事实性规范。
  3. RocketMQ 阿里出品,Java 系开源项目,源代码我们可以直接阅读,然后可以定制自己公司的MQ,并且 RocketMQ 有阿里巴巴的实际业务场景的实战考验。RocketMQ 社区活跃度相对较为一般,不过也还可以,文档相对来说简单一些,然后接口这块不是按照标准 JMS 规范走的有些系统要迁移需要修改大量代码。还有就是阿里出台的技术,你得做好这个技术万一被抛弃,社区黄掉的风险,那如果你们公司有技术实力我觉得用RocketMQ 挺好的
  4. Kafka 的特点其实很明显,就是仅仅提供较少的核心功能,但是提供超高的吞吐量,ms 级的延迟,极高的可用性以及可靠性,而且分布式可以任意扩展。同时 kafka 最好是支撑较少的 topic 数量即可,保证其超高吞吐量。kafka 唯一的一点劣势是有可能消息重复消费,那么对数据准确性会造成极其轻微的影响,在大数据领域中以及日志采集中,这点轻微影响可以忽略这个特性天然适合大数据实时计算以及日志收集。

2. 消息中间件可以解决哪些问题?

  1. 解耦;
  2. 流量削峰;
  3. 自带重试策略;
  4. 保证消息不丢失;
  5. 分布式事务的问题;

3. 为什么MQ可以解决流量削峰问题?

因为MQ服务端在接收消息时,设置了队列最大的阈值,如果超出了队列容量的情况下, 生产者投递的消息会被拒绝接收(被拒绝接收的消息存放在死信队列中)。消费者不会一次性将所有的消息全部消费完毕,会根据自己的能力实现消费。

4. RabbitMQ常用的队列模型有哪些?

  1. 点对点(简单)的队列
  2. 工作(公平性)队列模式
  3. 发布订阅模式(广播)
  4. 路由模式Routing
  5. 通配符(主题)模式Topic

5. RabbitMQ有哪几种交换器类型?

Direct exchange(直连交换器):当交换机类型为direct类型时,根据队列绑定的路由建转发到具体的队列中存放消息;
Mr. Cappuccino的第27杯咖啡——金三银四面试题之消息中间件篇_第1张图片

Topic exchange(主题交换器):当交换机类型为topic类型时,根据队列绑定的路由建模糊转发到具体的队列中存放。#号表示支持匹配多个词;*号表示只能匹配一个词
Mr. Cappuccino的第27杯咖啡——金三银四面试题之消息中间件篇_第2张图片

Fanout exchange(扇型交换器):fanout 类型的Exchange路由规则非常简单,它会把所有发送到该Exchange的消息路由到所有与它绑定的Queue中,不需要做任何判断操作,所以 fanout 类型是所有的交换机类型里面速度最快的。fanout 类型常用来广播消息。
Headers exchange(头交换器):headers 类型的交换器不依赖于路由键的匹配规则来路由消息,而是根据发送的消息内容中的 headers 属性进行匹配。在绑定队列和交换器时制定一组键值对,当发送消息到交换器时,RabbitMQ会获取到该消息的 headers(也是一个键值对的形式)'对比其中的键值对是否完全匹配队列和交换器绑定时指定的键值对,如果完全匹配则消息会路由到该队列,否则不会路由到该队列。headers 类型的交换器性能会很差,而且也不实用,基本上不会看到它的存在。(不推荐)

6. MQ宕机的情况下,消息是否会丢失?

不会丢失,因为消息会持久化在硬盘上。

7. MQ的应用场景有哪些?

  1. 使用MQ异步发送优惠券;
  2. 使用MQ异步发送短信;
  3. 使用MQ异步扣库存;

8. MQ如何保证消息不丢失?

  1. 生产者必须确认我们的消息一定投递到MQ服务器中存放 消息确认机制(confirm);
  2. MQ服务器会将我们消息持久化到硬盘存放;
  3. 消费者一定要确保我们的消息一定要消费成功,采用手动ACK形式,确定我们消息消费成功的情况下,在通知给我们的MQ服务器端将该消息从队列中移除。

9. MQ 如何保证消息幂等问题?

消费者获取消息,如果消费消息失败,MQ服务器则会间隔的形式 实现重试策略,重试过程中,需要保证业务幂等性问题,保证业务不能够重复执行。
解决方式:

  1. 可以通过全局的消息id,提前查询如果该业务逻辑已经执行过,则不会重复执行。
  2. 也需要在数据库的db层面需要保证幂等性问题,唯一主键约束、乐观锁等。

10. MQ如何避免消息堆积的问题?

产生背景:生产者投递消息的速率与我们消费者消费的速率完全不匹配。生产者投递消息的速率>消费者消费的速率,导致消息会堆积在MQ服务器端中,没有及时的被消费者消费,所以就会产生消息堆积的问题;
注意的是:RabbitMQ消费者消费消息如果成功的话,消息会被立即删除。kafka或者RocketMQ消息消费如果成功的话,消息是不会立即被删除。
解决办法:
A. 提高消费者消费的速率;(对消费者实现集群);
B. 消费者应该批量形式获取消息 减少网络传输的次数;

11. 生产者投递消息,MQ宕机了(满了)如何处理?

生产者投递消息失败,可以将消息内容(日志)记录下来,根据日志记录实现补偿机制(获取到该日志的消息内容实现重试)。(采用定时Job自动化补偿)

12. 消费者消费消息时报错了,如何处理?

分析消费者报错的原因:如果是空指针、类型转换异常,需要消费者发布版本才能解决的问题,MQ不能一直重试,应该放入消息日志表,后期定时补偿或者定时健康检查;如果是抛连接数据库异常、接口超时等原因,需要MQ服务器端不断的做重试。

13. MQ如何保证消息顺序一致性问题?

大多数情况下是不需要保证MQ消息顺序一致性的,只有在一些特定的场景可能会需要,比如MySQL与Redis实现异步同步数据;所有消息需要投递到同一个MQ服务器,同一个分区模型中存放,最终被同一个消费者消费,核心原理:设定相同的消息key,根据相同的消息key计算hash存放在同一个分区中。如果保证了消息顺序一致性有可能降低消费者消费的速率。

你可能感兴趣的:(金三银四,mr,kafka,java,rabbitmq)