1、前言

又到了金三银四的时候,大家都按耐不住心田的躁动,我在这里给大家分享下之前面试中遇到的一个知识点(MQ的利用场景),如有有余,欢送大佬们指导指导。

消息中间件利用背景

进步零碎性能首先思考的是数据库的优化,然而数据库因为历史起因,横向扩大是一件非常复杂的工程,所有咱们个别会尽量把流量都挡在数据库之前。不论是有限的横向扩大服务器,还是纵向阻隔达到数据库的流量,都是这个思路。阻隔中转数据库的流量,缓存组件和音讯组件是两大杀器。

2、MQ简介

MQ:Message queue,音讯队列,就是指保留音讯的一个容器。

当初罕用的MQ组件有activeMQ、rabbitMQ、rocketMQ,当然近年来炽热的kafka,从某些场景来说,也是MQ,不过kafka的性能更加弱小,尽管不同的MQ都有本人的特点和劣势,然而,不论是哪种MQ,都有MQ自身自带的一些特点。

罕用音讯队列比拟

个性ActiveMQRabbitMQRocketMQKafka
生产者消费者模式反对反对反对反对
公布订阅模式反对反对反对反对
申请回应模式反对反对不反对不反对
Api齐备性
多语言反对反对反对java反对
单机吞吐量万级万级万级十万级
音讯提早微秒级毫秒级毫秒级
可用性高(主从)高(主从)十分高(分布式)十分高(分布式)
音讯失落实践上不会失落实践上不会失落
文档的齐备性教高
提供疾速入门
社区活跃度
商业反对商业云商业云

3、MQ特点

先进先出

先进先出,是队列最显著的特点。音讯队列的程序在入队的时候就根本曾经确定了,个别是不需人工干预的。而且,最重要的是,数据是只有一条数据在应用中。 这也是MQ在诸多场景被应用的起因。

公布订阅

公布订阅是一种很高效的解决形式,如果不产生阻塞,根本能够当做是同步操作。这种解决形式能十分无效的晋升服务器利用率,这样的利用场景十分宽泛。

长久化

长久化确保MQ的应用不只是一个局部场景的辅助工具,而是让MQ能像数据库一样存储外围的数据,保障MQ的可靠性。

分布式

在当初大流量、大数据的应用场景下,只反对单体利用的服务器软件根本是无奈应用的,反对分布式的部署,能力被宽泛应用。而且,MQ的定位就是一个高性能的中间件。

4、利用场景

音讯队列中间件是分布式系统中重要的组件,次要解决利用解耦,异步音讯,流量削锋、海量日志数据同步、分布式事务等问题,实现高性能,高可用,可伸缩和最终一致性架构。

4.1 利用解耦

场景阐明:用户下单后,订单零碎须要告诉库存零碎。传统的做法是,订单零碎调用库存零碎的接口。

<img src="https://gitee.com/yinfeng-code/study-image/raw/master/image-20220301193157985.png" alt="image-20220301193157985" style="zoom:200%;" />

传统模式的毛病:如果库存零碎无法访问,则订单减库存将失败,从而导致订单失败,订单零碎与库存零碎耦合度高,容易呈现雪崩事变。

引入利用音讯队列后的计划

<img src="https://gitee.com/yinfeng-code/study-image/raw/master/image-20220301193421703.png" alt="image-20220301193421703" style="zoom:200%;" />

订单零碎:用户下单后,订单零碎实现长久化解决,将音讯写入音讯队列,返回用户订单下单胜利。
库存零碎:订阅下单的音讯,采纳pull/push的形式,获取下单信息,库存零碎依据下单信息,进行库存操作。
解决问题关键步骤:在下单时库存零碎不能失常应用,也不影响失常下单,因为下单后,订单零碎写入音讯队列就不再关怀其余的后续操作了,只有达成最终一致性即可。实现订单零碎与库存零碎的利用解耦。

4.2 异步音讯

场景阐明:用户注册后,须要发注册邮件和注册短信。传统的做法有两种:串行的形式、并行形式。

  1. 串行形式:将注册信息写入数据库胜利后,发送注册邮件,再发送注册短信。以上三个工作全副实现后,返回给客户端。

    <img src="https://gitee.com/yinfeng-code/study-image/raw/master/image-20220301193824700.png" alt="image-20220301193824700" style="zoom:150%;" />

  2. 并行形式:将注册信息写入数据库胜利后,发送注册邮件的同时,发送注册短信。以上三个工作实现后,返回给客户端。与串行的差异是,并行的形式能够进步解决的工夫。

    <img src="https://gitee.com/yinfeng-code/study-image/raw/master/image-20220301193912473.png" alt="image-20220301193912473" style="zoom:150%;" />

    问题剖析

    假如三个业务节点每个应用50毫秒钟,不思考网络等其余开销,则串行形式的工夫是150毫秒,并行的工夫可能是100毫秒。
    因为CPU在单位工夫内解决的申请数是肯定的,假如CPU1秒内吞吐量是100次。则串行形式1秒内CPU可解决的申请量是7次(1000/150)。并行形式解决的申请量是10次(1000/100)
    如以上案例形容,传统的形式零碎的性能(并发量,吞吐量,响应工夫)会有瓶颈。

    将发送注册邮件和注册短信的步骤通过音讯队列解耦

    <img src="https://gitee.com/yinfeng-code/study-image/raw/master/image-20220301194204361.png" alt="image-20220301194204361" style="zoom:150%;" />

    由以上架构可知,用户的响应工夫相当于是注册信息写入数据库的工夫,也就是50毫秒。注册邮件,发送短信写入音讯队列后,间接返回,因而写入音讯队列的速度很快,根本能够疏忽,因而用户的响应工夫可能是50毫秒。因而架构扭转后,零碎的吞吐量进步到每秒20 QPS。比串行进步了3倍,比并行进步了两倍。

4.3 流量削锋

流量削锋也是音讯队列中的罕用场景,个别在秒杀或团抢流动中应用宽泛。

场景阐明:秒杀流动,个别会因为流量过大,导致流量暴增,利用或者数据库挂掉。为解决这个问题,个别须要在利用前端退出音讯队列。

架构如下

<img src="https://gitee.com/yinfeng-code/study-image/raw/master/image-20220301194437969.png" alt="image-20220301194437969" style="zoom:150%;" />

退出音讯队列的益处

  1. 能够管制流动的人数
  2. 能够缓解短时间内高流量压垮利用

用户的申请,服务器接管后,首先写入音讯队列。如果音讯队列长度超过最大数量,则间接摈弃用户申请或跳转到谬误页面。
秒杀业务依据音讯队列中的申请信息,再做后续解决。

4.4 海量日志数据同步

场景阐明:在微服务体系下,我的项目往往是集群部署,那么就须要一个对立日志平台来查问各个实例的日志,但集群中的日志信息往往都是海量数据,繁多的日志采集工具不能满足业务的须要,因而须要将音讯队列用在日志解决中,比方Kafka的利用,解决大量日志传输的问题。

架构简化如下

<img src="https://gitee.com/yinfeng-code/study-image/raw/master/image-20220301195357808.png" alt="image-20220301195357808" style="zoom:150%;" />

架构阐明

  1. 日志采集客户端,负责日志数据采集,定时写受写入Kafka队列
  2. Kafka音讯队列,负责日志数据的接管,存储和转发
  3. 日志解决利用:订阅并生产kafka队列中的日志数据

4.5 分布式事物

分布式事务又分为强统一,弱统一,和最终一致性

  1. 强统一

    当更新操作实现之后,任何多个后续过程或者线程的拜访都会返回最新的更新过的值。这种是对用户最敌对的,就是用户上一次写什么,下一次就保障能读到什么。依据 CAP 实践,这种实现须要就义可用性。
  2. 弱统一

    零碎并不保障续过程或者线程的拜访都会返回最新的更新过的值。零碎在数据写入胜利之后,不承诺立刻能够读到最新写入的值,也不会具体的承诺多久之后能够读到。
  3. 最终统一

    弱一致性的特定模式。零碎保障在没有后续更新的前提下,零碎最终返回上一次更新操作的值。在没有故障产生的前提下,不统一窗口的工夫次要受通信提早,零碎负载和复制正本的个数影响。DNS 是一个典型的最终一致性零碎。
在分布式系统中,同时满足“CAP定律”中的一致性、可用性和分区容错性三者是简直不可能的。在互联网畛域的绝大多数的场景,都须要就义强一致性来换取零碎的高可用性,零碎往往只须要保障“最终一致性”,只有这个最终工夫是在用户能够承受的范畴内即可,这时候咱们只须要用短暂的数据不统一就能够达到咱们想要成果。

场景阐明:比方有订单,库存两个数据,一个下单过程简化为,加一个订单,减一个库存。 而订单和库存是独立的服务,那怎么保证数据一致性。

近程调用最郁闷的中央就是,后果有3种,胜利、失败和超时。 超时的话,成功失败都有可能。个别的解决方案,大多数的做法是借助mq来做最终统一。

实现最终统一

通过下面的架构可能会想到这些问题

本地先执行事务,执行胜利了就发个音讯过来,生产端拿到音讯执行本人的事务。
比方a,b两个服务,服务a异步调用服务b,如果服务b失败了,或者胜利,或者超时,那么怎么用mq让他们最终统一呢?

参照于本地事务的概念可将该场景分为三种状况解决

  1. 第一种状况:假如a,b都失常执行,那整个业务失常完结;
  2. 第二种状况:假如b超时,那么须要MQ给b重发消息(b服务要做幂等),如果呈现重发失败的话,须要看状况,是中断服务,还是持续重发,甚至人为干涉;
  3. 第三种状况:假如a,b之中的一个失败了,失败的服务利用MQ给其余的服务发送音讯,其余的服务接管音讯,查问本地事务记录日志,如果本地也失败,删除收到的音讯(示意音讯生产胜利),如果本地胜利的话,则须要调用弥补接口进行弥补(须要每个服务都提供业务弥补接口)。

须要特地留神

MQ这里有个坑,通常只实用于只容许第一个操作失败的场景,也就是第一个胜利之后必须保障前面的操作在业务上没阻碍,不然前面失败了后面不好回滚,只容许零碎异样的失败,不容许业务上的失败,通常业务上失败一次前面基本上也不太可能胜利了,要是因为网络或宕机引起的失败能够通过重试解决,如果业务异样,那就只能发消息给服务a让他们做弥补了吧?通常是通过第三方进行弥补,各个服务须要提供弥补接口,设计范式里通常不容许生产上游业务失败。

5、总结

MQ在分布式系统开发的场景下应用的越来越多,解决的业务能力也越来越强,所以把握MQ的应用场景是很要必要的。通过把握MQ,即可解决大多数业务场景,也可在面试中加分,进步本人的外围竞争力。

最初,外出打工不易,心愿各位兄弟找到本人心仪的工作,虎年发发发

也心愿兄弟们能关注、点赞、珍藏、评论反对一波,非常感谢大家!