Java高频面试之消息队列与分布式篇

有需要互关的小伙伴,关注一下,有关必回关,争取今年认证早日拿到博客专家

Java高频面试之总纲篇

Java高频面试之集合篇

Java高频面试之异常篇

Java高频面试之并发篇

Java高频面试之SSM篇

Java高频面试之Mysql篇

Java高频面试之Redis篇

Java高频面试之消息队列与分布式篇

50道SQL面试题

奇奇怪怪的面试题

五花八门的内存溢出

消息队列的基本作用?

  1. 异步通信:消息队列提供了异步通信的能力,发送方可以将消息发送到队列中,而无需等待接收方立即处理。发送方和接收方可以解耦,彼此不需要直接交互,从而实现解耦和异步处理。例如im
  2. 解耦应用程序:消息队列使得不同的应用程序之间可以通过消息进行通信,而不需要直接调用或知道对方的存在。每个应用程序只需关注自己的业务逻辑,将消息发送到队列中,由其他应用程序异步地处理这些消息。这样可以降低应用程序之间的依赖性,提高系统的可维护性和扩展性。
  3. 缓冲和削峰填谷:消息队列可以作为一个缓冲区,当生产者发送消息的速度快于消费者处理消息的速度时,消息可以暂时存储在队列中。这样可以平衡生产者和消费者之间的速度差异,避免系统的过载和性能问题。
  4. 数据分发:消息队列可以将消息广播给多个订阅者或消费者。这对于实现发布-订阅模式或者广播通知非常有用,一个消息可以同时被多个订阅者接收并处理。
  5. 重试和错误处理:消息队列可以处理消息传递过程中的错误情况。当消息发送失败时,消息队列可以自动进行重试,并保证消息的可靠传递。此外,可以将处理失败的消息放入死信队列中进行后续的错误处理和分析。
  6. 顺序性保证:某些消息队列支持按照特定的顺序发送和处理消息,确保消息的有序性。这对于需要按照特定顺序处理消息的场景非常重要,例如订单处理、事件日志等。

消息队列的基本作用是提供可靠、高效、异步的消息通信机制,实现系统之间的解耦、异步处理、削峰填谷、数据分发和错误处理等功能。它在分布式系统、微服务架构和大规模应用中发挥着重要的作用。

消息队列的优缺点有哪些?

优点:

  1. 异步通信:消息队列支持异步通信,发送方将消息发送到队列中,无需等待接收方的即时响应,提高了系统的并发处理能力和响应速度。
  2. 解耦应用程序:通过消息队列,应用程序之间的耦合度降低。每个应用程序只需关注自己的业务逻辑,通过发送和接收消息进行通信,从而提高了系统的可维护性和扩展性。
  3. 缓冲和削峰填谷:消息队列作为一个缓冲区,可以平衡生产者和消费者之间的速度差异,避免系统的过载和性能问题。它可以处理突发的请求量,实现削峰填谷的效果。
  4. 数据分发和广播:消息队列支持将消息广播给多个订阅者,实现发布-订阅模式,方便实现数据分发和广播通知。
  5. 可靠性和持久性:消息队列通常具有可靠的消息传递机制,可以确保消息的可靠性和持久性。即使在消息传递过程中出现故障,消息队列也可以保证消息的传递和处理。

缺点:

  1. 复杂性:使用消息队列需要引入额外的组件和技术,增加了系统的复杂性和维护成本。需要考虑消息的序列化、消息传递协议、消息队列的配置等问题。
  2. 一致性问题:由于消息队列的异步特性,消息的发送和处理可能存在一定的时间延迟,因此在一些场景下可能需要额外的机制来处理一致性问题。
  3. 部署和维护成本:引入消息队列需要部署和维护额外的中间件,涉及到部署、监控、故障排查等工作,增加了系统的运维成本和学习成本。
  4. 数据一致性和顺序性问题:某些消息队列无法保证消息的严格顺序性,对于一些场景需要保证严格顺序的消息处理可能会有一定挑战。
  5. 引入单点故障:消息队列本身可能成为系统中的单点故障,如果消息队列出现故障,会影响整个系统的正常运行。

在选择是否使用消息队列时,需要综合考虑系统的需求、复杂性和可靠性等因素,权衡利弊。消息队列在很多场景下是非常有用的,但也需要根据

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

  1. 集群部署:将消息队列部署在多台服务器上形成集群,通过负载均衡的方式将请求分发到不同的节点。这样可以提高系统的吞吐量和可用性,并且在某个节点故障时仍然能够正常提供服务。
  2. 数据复制和同步:对于主从架构的消息队列,需要将数据进行复制和同步,以实现数据的冗余备份和容错。在主节点写入消息后,通过数据同步机制将数据复制到备份节点,确保数据的可靠性和持久性。
  3. 故障自动转移:配置故障自动转移机制,当消息队列节点出现故障时,自动将请求转移到备份节点上,以保证服务的连续性。可以使用类似于主备切换、选举机制或者自动发现机制来实现故障转移。
  4. 监控和报警:建立监控系统,实时监测消息队列的运行状态、吞吐量、延迟等指标。设置报警机制,及时发现并处理潜在的问题,确保问题得到及时解决,提高可用性。
  5. 数据备份和恢复:定期对消息队列中的数据进行备份,确保在数据丢失或损坏的情况下能够进行数据恢复。备份数据可以存储在独立的存储介质或者其他节点上,以提供数据的冗余和可靠性。
  6. 消息队列监控和管理工具:使用专业的消息队列监控和管理工具,可以对消息队列进行实时监控、性能分析、故障排查和性能调优。这些工具提供了丰富的指标和图表,帮助管理员更好地了解系统状态并采取相应措施。
  7. 容量规划和水平扩展:根据系统的负载和需求进行容量规划,预估消息队列的并发请求量、存储容量等。当负载增加时,通过水平扩展的方式增加节点数量,以提供更好的性能和可用性。

通过以上策略的综合应用,可以提高消息队列的可用性,确保系统能够在故障情况下保持正常运行,并且具备数据的可靠性和持久性。根据具体的需求和系统架构,还可以采用其他高可用技术,如多活部署、数据分片等来进一步提高消息队列的可用性。

如何保证消息消费的幂等性?

其他问法:如何保证消息不被重复消费?

  1. 关系型数据库主键或唯一键+事务

    弊端:

    1. 性能问题(对整个消息消费逻辑加事务,如果消费逻辑太负责,再有数据库本身的性能并不是很高)
    2. 不支持事务的部分回滚(除了事务部分还调用了第三方系统,修改了redis)
  2. 拆解方案

    将没一步都做成幂等性的,例如库存系统减完库存后,发一条消息给订单系统对应的消息队列,订单系统单独实现幂等性,订单系统消费成功后给下游系统发消息队列,下游系统单独实现幂等性…

    缺点:麻烦

  3. 通用解决方案(去事务方案)

    1. 查询有没有消费(可以用关系型数据库,也可以用redis等)
    2. 记录状态
    3. 修改状态
    4. 通知消息队列消费成功了

dedupflow.png

需要考虑的三个问题

  1. 消息已经消费成功了,第二条消息将被直接幂等处理掉(消费成功)。
  2. 并发场景下的消息,依旧能满足不会出现消息重复,即穿透幂等挡板的问题。
  3. 支持上游业务生产者重发的业务重复的消息幂等问题。

为啥要加延迟消费?

​ 解决并发问题

为啥要加过期时间?

​ 防止第一条消息因为特殊原因消费失败(也没删掉),后续的延迟消费一直重试,最后进入死信队列

参考文章:https://jaskey.github.io/blog/2020/06/08/rocketmq-message-dedup/

https://github.com/Jaskey/RocketMQDedupListener

主要分两方面:一方面是生产者加一个唯一标识,两一方面消费者检查唯一标识,可以借助数据库的主键索引或者唯一键索引,缓存记录消费掉的消息,必要时添加回退机制,防止消费到一半时异常.

无论是何种消息队列,造成重复消费原因其实都是类似的。正常情况下,消费者在消费消息时候,消费完毕后,会发送一个确认信息给消息队列,消息队列就知道该消息被消费了,就会将该消息从消息队列中删除。
只是不同的消息队列发送的确认信息形式不同,例如RabbitMQ是发送一个ACK确认消息,RocketMQ是返回一个CONSUME_SUCCESS成功标志,kafka实际上有个offset的概念,每一个消息都有一个offset,kafka消费过消息后,需要提交offset,让消息队列知道自己已经消费过了。
那造成重复消费的原因? 就是因为网络传输等等故障,确认信息没有传送到消息队列,导致消息队列不知道自己已经消费过该消息了,再次将该消息分发给其他的消费者。
如何解决?这个问题针对业务场景来答分以下几点
(1)给这个消息做一个唯一主键,做数据库insert,如果出现重复消费情况,会导致主键冲突,避免数据库出现脏数据。
(2)update 和 delete 支持天然幂等性,拿到这个消息做redis的set的操作,那就容易了,不用解决,set操作天然幂等操作。
(3)第三方介质,来做消费记录。以redis为例,给消息分配一个全局id,只要消费过该消息,将<id,message>以K-V形式写入redis。那消费者开始消费前,先去redis中查询有没消费记录即可。

  1. 唯一标识符:为每个消息生成一个唯一的标识符,并将其与消息一起存储在消费端。在处理消息之前,先检查是否已经处理过具有相同标识符的消息,如果已经处理过,则直接跳过,避免重复处理。
  2. 幂等标识字段:在消息中添加一个幂等标识字段,用于标识消息的唯一性。消费端在处理消息时,先检查该字段的值,如果已经处理过具有相同标识字段值的消息,则跳过处理。
  3. 乐观锁:对于并发环境下的消息消费,可以使用乐观锁来保证幂等性。在消费端处理消息时,先获取并锁定消息的相关资源,然后再检查是否已经处理过。如果已经处理过,则直接释放资源,避免重复处理。
  4. 数据库约束:在消费端的数据库表中,可以添加唯一约束或者主键约束来保证数据的唯一性。当消费端尝试将消息写入数据库时,如果违反了约束条件,则表明消息已经被处理过,可以忽略该消息。
  5. 日志记录:在消费端处理消息时,记录消息的处理状态和结果。如果后续收到相同消息,可以先查询日志记录,判断是否已经处理过。
  6. 幂等性检查和处理:在消费端处理消息时,先进行幂等性检查。可以通过查询数据库、查看缓存状态或者调用特定接口来检查消息是否已经处理过。如果已经处理过,则直接返回成功,否则继续处理消息。
  7. 事务性操作:在消费端进行消息处理时,将消息处理过程放在一个事务中。通过使用数据库事务或者分布式事务,可以保证消息的处理是原子性的,即使在处理过程中出现异常或者重试,也能保证幂等性。

通过以上方法的应用,可以保证消息的消费是幂等的,即使在重复消费或者异常情况下,也能保证处理的结果是一致的。根据具体的业务场景和系统架构,可以选择合适的方式来实现消息消费的幂等性。

如何保证消息的可靠性传输?

其他问法:如何处理消息丢失的问题?

https://zhuanlan.zhihu.com/p/59759422

image.png

如何保证消息的顺序性?

乱序的原因之一:

Consumer从MQ里面读取数据是有序的,但是每个Consumer的执行时间是不固定的,无法保证先读到消息的Consumer一定先完成操作,这样就会出现消息并没有按照顺序执行,造成数据顺序错误。

rabbitmq

  1. 全局有序

    将所有消息发送到同一个队列里,队列只有一个消费者,预取值设置为1

    缺点:性能问题

  2. 局部有序

    多建几个队列

    讲需要保持顺序的一批数据发送到一个队列里面(例如根据订单号hash求模)

image.png

大量消息在 MQ 里长时间积压,该如何解决?

找原因:是生产者突增还是消费者故障?

如果消费者故障先修消费者

增加队列,增加消费者,快速消费

image.png

MQ 中的消息过期失效了怎么办?

查找原因:为什么过期了?过期时间设置的太短了?消费者端出问题了,导致消息挤压了?

如果消费者端出问题了先修复问题,然后查询过期的数据,找流量不高的时候导入

只能重新查询数据,手动灌入消息队列

RabbitMQ 有哪些重要的角色?

  1. 生产者

  2. 消费者

  3. 代理:就是RabbitMQ本身,用于扮演快递的角色,本身并不生产消息

RabbitMQ 有哪些重要的组件?

  1. ConnectionFactory(连接管理器):应用程序与RabbitMQ之间建立连接的管理器
  2. Channel(信道):消息推送使用的通道
  3. Exchange(交换器):用于接受、分配消息
  4. Queue(队列):用于存储生产者的消息
  5. RoutingKey(路由键)

image.png

RabbitMQ 有几种广播类型?

  1. fanout(扇出):所有 bind 到此 exchange 的 queue 都可以接收消息;
  2. direct(直连):通过 routingKey 和 exchange 中的 bindingKey 决定的那个唯一的 queue 可以接收消息;
  3. topic(主体):所有符合 routingKey 所 bind 的 queue 可以接收消息。

Kafka 可以脱离 zookeeper 单独使用吗?为什么?

Kafka 不能脱离 zookeeper 单独使用,因为 Kafka 使用 zookeeper 管理和协调 Kafka 的节点服务器。

补充:最新版本的 Kafka 2.8.0 版本实现了 Raft 分布式一致性机制,意味着可以脱离 ZooKeeper 独立运行

Kafka 有几种数据保留的策略?

1、按照过期时间保留(到时见就删除)

2、按照存储的消息大小保留(占用指定大小的磁盘后删除老消息)

Kafka 的分区策略有哪些?

谈下你对 Zookeeper 的认识?

Zookeeper 都有哪些功能?

谈下你对 ZAB 协议的了解?

Zookeeper 怎么保证主从节点的状态同步?

Zookeeper 有几种部署模式?

说一下 Zookeeper 的通知机制?

集群中为什么要有主节点?

集群中有 3 台服务器,其中一个节点宕机,这个时候 Zookeeper 还可以使用吗?

说一下两阶段提交和三阶段提交的过程?分别有什么问题?

Zookeeper 宕机如何处理?

说下四种类型的数据节点 Znode?

Zookeeper 和 Dubbo 的关系?

Java高频面试之总纲篇

Java高频面试之集合篇

Java高频面试之异常篇

Java高频面试之并发篇

Java高频面试之SSM篇

Java高频面试之Mysql篇

Java高频面试之Redis篇

Java高频面试之消息队列与分布式篇

50道SQL面试题

奇奇怪怪的面试题

五花八门的内存溢出

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值