乐趣区

关于java:阿里三面MQ-消息丢失重复积压问题如何解决

面试官在面试候选人时,如果发现候选人的简历中写了在我的项目中应用了 MQ 技术(如 Kafka、RabbitMQ、RocketMQ),根本都会抛出一个问题:在应用 MQ 的时候,怎么确保音讯 100% 不失落?

这个问题在理论工作中很常见,既能考查候选者对于 MQ 中间件技术的把握水平,又能很好地区分候选人的能力程度。接下来,咱们就从这个问题登程,探讨你应该把握的基础知识和答题思路,以及延长的面试考点。

案例背景

以京东零碎为例,用户在购买商品时,通常会抉择用京豆抵扣一部分的金额,在这个过程中,交易服务和京豆服务通过 MQ 音讯队列进行通信。在下单时,交易服务发送“扣减账户 X 100 个京豆”的音讯给 MQ 音讯队列,而京豆服务则在生产端生产这条命令,实现真正的扣减操作。

那在这个过程中你会遇到什么问题呢?

案例剖析

要晓得,在互联网面试中,引入 MQ 消息中间件最间接的目标是:做零碎解耦合流量管制,追其本源还是为了解决互联网零碎的高可用和高性能问题。

  • 零碎解耦:用 MQ 音讯队列,能够隔离零碎上下游环境变动带来的不稳固因素,比方京豆服务的零碎需要无论如何变动,交易服务不必做任何扭转,即便当京豆服务呈现故障,主交易流程也能够将京豆服务降级,实现交易服务和京豆服务的解耦,做到了零碎的高可用。
  • 流量管制:遇到秒杀等流量突增的场景,通过 MQ 还能够实现流量的“削峰填谷”的作用,能够依据上游的解决能力主动调节流量。

不过引入 MQ 尽管实现了零碎解耦合流量管制,也会带来其余问题。

引入 MQ 消息中间件实现零碎解耦,会影响零碎之间数据传输的一致性。 在分布式系统中,如果两个节点之间存在数据同步,就会带来数据一致性的问题。同理,在这一讲你要解决的就是:音讯生产端和音讯生产端的音讯数据一致性问题(也就是如何确保音讯不失落)。

而引入 MQ 消息中间件解决流量管制 ,会使生产端解决能力有余从而导致音讯积压,这也是你要解决的问题。

所以你能发现,问题与问题之间往往是环环相扣的,面试官会借机考查你解决问题思路的连贯性和常识体系的把握水平。

那面对“在应用 MQ 音讯队列时,如何确保音讯不失落”这个问题时,你要怎么答复呢?首先,你要剖析其中有几个考点,比方:

  • 如何晓得有音讯失落?
  • 哪些环节可能丢音讯?
  • 如何确保音讯不失落?

候选人在答复时,要先让面试官晓得你的剖析思路,而后再提供解决方案 :网络中的数据传输不牢靠,想要解决如何不丢音讯的问题,首先要晓得哪些环节可能丢音讯,以及咱们如何晓得音讯是否失落了,最初才是解决方案(而不是上来就间接说本人的解决方案)。就好比“架构设计”“架构”体现了架构师的思考过程,而“设计”才是最初的解决方案,两者缺一不可。

案例解答

咱们首先来看音讯失落的环节,一条音讯从生产到生产实现这个过程,能够划分三个阶段,别离为音讯生产阶段,音讯存储阶段和音讯生产阶段。

  • 音讯生产阶段: 从音讯被生产进去,而后提交给 MQ 的过程中,只有能失常收到 MQ Broker 的 ack 确认响应,就示意发送胜利,所以只有解决好返回值和异样,这个阶段是不会呈现音讯失落的。
  • 音讯存储阶段: 这个阶段个别会间接交给 MQ 消息中间件来保障,然而你要理解它的原理,比方 Broker 会做正本,保障一条音讯至多同步两个节点再返回 ack。
  • 音讯生产阶段: 生产端从 Broker 上拉取音讯,只有生产端在收到音讯后,不立刻发送生产确认给 Broker,而是等到执行完业务逻辑后,再发送生产确认,也能保障音讯的不失落。

计划看似十拿九稳,每个阶段都能保障音讯的不失落,但在分布式系统中,故障不可避免,作为音讯生产端,你并不能保障 MQ 是不是弄丢了你的音讯,消费者是否生产了你的音讯,所以,本着 Design for Failure 的设计准则,你还是须要一种机制,来 Check 音讯是否失落了。

紧接着,你还能够向面试官论述怎么进行音讯检测? 总体方案解决思路为:在音讯生产端,给每个收回的音讯都指定一个全局惟一 ID,或者附加一个间断递增的版本号,而后在生产端做对应的版本校验。

具体怎么落地实现呢?你能够利用拦截器机制。 在生产端发送音讯之前,通过拦截器将音讯版本号注入音讯中(版本号能够采纳间断递增的 ID 生成,也能够通过分布式全局惟一 ID 生成)。而后在生产端收到音讯后,再通过拦截器检测版本号的连续性或生产状态,这样实现的益处是音讯检测的代码不会侵入到业务代码中,能够通过独自的工作来定位失落的音讯,做进一步的排查。

这里须要你留神:如果同时存在多个音讯生产端和音讯生产端,通过版本号递增的形式就很难实现了,因为不能保障版本号的唯一性,此时只能通过全局惟一 ID 的计划来进行音讯检测,具体的实现原理和版本号递增的形式统一。

当初,你曾经晓得了哪些环节(音讯存储阶段、音讯生产阶段)可能会出问题,并有了如何检测音讯失落的计划,而后就要给出解决避免音讯失落的设计方案。

答复完“如何确保音讯不会失落?”之后,面试官通常会诘问“怎么解决音讯被反复生产的问题?

比方:在音讯生产的过程中,如果呈现失败的状况,通过弥补的机制发送方会执行重试,重试的过程就有可能产生反复的音讯,那么如何解决这个问题?

这个问题其实能够换一种说法,就是如何解决生产端幂等性问题(幂等性,就是一条命令,任意屡次执行所产生的影响均与一次执行的影响雷同),只有生产端具备了幂等性,那么反复生产音讯的问题也就解决了。

咱们还是来看扣减京豆的例子,将账户 X 的金豆个数扣减 100 个,在这个例子中,咱们能够通过革新业务逻辑,让它具备幂等性。

最简略的实现计划,就是在数据库中建一张消息日志表 ,这个表有两个字段:音讯 ID 和音讯执行状态。这样,咱们生产音讯的逻辑能够变为:在消息日志表中减少一条音讯记录,而后再依据音讯记录,异步操作更新用户京豆余额。

因为咱们每次都会在插入之前查看是否音讯已存在,所以就不会呈现一条音讯被执行屡次的状况,这样就实现了一个幂等的操作。当然,基于这个思路,不仅能够应用关系型数据库,也能够通过 Redis 来代替数据库实现惟一束缚的计划。

在这里我多说一句,想要解决“音讯失落”和“音讯反复生产”的问题,有一个前提条件就是要实现一个全局惟一 ID 生成的技术计划。这也是面试官喜爱考查的问题,你也要把握。

在分布式系统中,全局惟一 ID 生成的实现办法有数据库自增主键、UUID、Redis,Twitter-Snowflake 算法,我总结了几种计划的特点,你能够参考下。

我揭示你留神,无论哪种办法,如果你想同时满足简略、高可用和高性能,就要有取舍,所以你要站在理论的业务中,阐明你的选型所思考的平衡点是什么。我集体在业务中比拟偏向于抉择 Snowflake 算法,在我的项目中也进行了肯定的革新,次要是让算法中的 ID 生成规定更加合乎业务特点,以及优化诸如时钟回拨等问题。

当然,除了“怎么解决音讯被反复生产的问题?”之外,面试官还会问到你“音讯积压”。 起因在于音讯积压反映的是性能问题,解决音讯积压问题,能够阐明候选者有能力解决高并发场景下的生产能力问题。

你在解答这个问题时,仍旧要传递给面试官一个这样的思考过程: 如果呈现积压,那肯定是性能问题,想要解决音讯从生产到生产上的性能问题,就首先要晓得哪些环节可能呈现音讯积压,而后在思考如何解决。

因为音讯发送之后才会呈现积压的问题,所以和音讯生产端没有关系,又因为绝大部分的音讯队列单节点都能达到每秒钟几万的解决能力,绝对于业务逻辑来说,性能不会呈现在中间件的音讯存储下面。毫无疑问,出问题的必定是音讯生产阶段, 那么从生产端动手,如何答复呢?

如果是线上突发问题,要长期扩容,减少生产端的数量,与此同时,降级一些非核心的业务。通过扩容和降级承当流量,这是为了表明你对应急问题的解决能力。

其次,才是排查解决异样问题,如通过监控,日志等伎俩剖析是否生产端的业务逻辑代码呈现了问题,优化生产端的业务解决逻辑。

最初,如果是生产端的解决能力有余,能够通过程度扩容来提供生产端的并发解决能力, 但这里有一个考点须要特地留神 ,那就是在扩容消费者的实例数的同时,必须同步扩容主题 Topic 的分区数量,确保消费者的实例数和分区数相等。如果消费者的实例数超过了分区数,因为分区是单线程生产,所以这样的扩容就没有成果。

比方在 Kafka 中,一个 Topic 能够配置多个 Partition(分区),数据会被写入到多个分区中,但在生产的时候,Kafka 约定一个分区只能被一个消费者生产,Topic 的分区数量决定了生产的能力,所以,能够通过减少分区来进步消费者的解决能力。

总结

至此,咱们解说了 MQ 音讯队列的热门问题的解决方案,无论是初中级还是高级研发工程师,本篇文章的内容都是你须要把握的,你都能够从这几点登程,与面试官进行敌对的交换。我来总结一下明天的重点内容。

  • 如何确保音讯不会失落? 你要晓得一条音讯从发送到生产的每个阶段,是否存在丢音讯,以及如何监控音讯是否失落,最初才是如何解决问题,计划能够基于“MQ 的可靠消息投递”的形式。
  • 如何保障音讯不被反复生产? 在进行音讯弥补的时候,肯定会存在反复音讯的状况,那么如何实现生产端的幂等性就这道题的考点。
  • 如何解决音讯积压问题? 这道题的考点就是如何通过 MQ 实现真正的高性能,答复的思路是,本着解决线上异样为最高优先级,而后通过监控和日志进行排查并优化业务逻辑,最初是扩容生产端和分片的数量。

在答复问题的时候,你须要特地留神的是, 让面试官理解到你的思维过程,这种解决问题的能力是面试官更为看中的,比你间接答复一道面试题更有价值。

另外,如果你应聘的部门是基础架构部,那么除了要把握本讲中的常见问题的主线常识以外,还要把握消息中间件的其余常识体系,如:

  • 如何选型消息中间件?
  • 消息中间件中的队列模型与公布订阅模型的区别?
  • 为什么音讯队列能实现高吞吐?
  • 序列化、传输协定,以及内存治理等问题
  • … >
退出移动版