1、前言
又到了金三银四的时候,大家都按耐不住心田的躁动,我在这里给大家分享下之前面试中遇到的一个知识点(MQ 的利用场景),如有有余,欢送大佬们指导指导。
消息中间件利用背景
进步零碎性能首先思考的是数据库的优化,然而数据库因为历史起因,横向扩大是一件非常复杂的工程,所有咱们个别会尽量把流量都挡在数据库之前。不论是有限的横向扩大服务器,还是纵向阻隔达到数据库的流量,都是这个思路。阻隔中转数据库的流量,缓存组件和音讯组件是两大杀器。
2、MQ 简介
MQ:Message queue,音讯队列,就是指保留音讯的一个容器。
当初罕用的 MQ 组件有 activeMQ、rabbitMQ、rocketMQ,当然近年来炽热的 kafka,从某些场景来说,也是 MQ,不过 kafka 的性能更加弱小,尽管不同的 MQ 都有本人的特点和劣势,然而,不论是哪种 MQ,都有 MQ 自身自带的一些特点。
罕用音讯队列比拟
个性 | ActiveMQ | RabbitMQ | RocketMQ | Kafka |
---|---|---|---|---|
生产者消费者模式 | 反对 | 反对 | 反对 | 反对 |
公布订阅模式 | 反对 | 反对 | 反对 | 反对 |
申请回应模式 | 反对 | 反对 | 不反对 | 不反对 |
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 异步音讯
场景阐明:用户注册后,须要发注册邮件和注册短信。传统的做法有两种:串行的形式、并行形式。
-
串行形式:将注册信息写入数据库胜利后,发送注册邮件,再发送注册短信。以上三个工作全副实现后,返回给客户端。
<img src=”https://gitee.com/yinfeng-code/study-image/raw/master/image-20220301193824700.png” alt=”image-20220301193824700″ style=”zoom:150%;” />
-
并行形式:将注册信息写入数据库胜利后,发送注册邮件的同时,发送注册短信。以上三个工作实现后,返回给客户端。与串行的差异是,并行的形式能够进步解决的工夫。
<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%;” />
退出音讯队列的益处:
- 能够管制流动的人数
- 能够缓解短时间内高流量压垮利用
用户的申请,服务器接管后,首先写入音讯队列。如果音讯队列长度超过最大数量,则间接摈弃用户申请或跳转到谬误页面。
秒杀业务依据音讯队列中的申请信息,再做后续解决。
4.4 海量日志数据同步
场景阐明:在微服务体系下,我的项目往往是集群部署,那么就须要一个对立日志平台来查问各个实例的日志,但集群中的日志信息往往都是海量数据,繁多的日志采集工具不能满足业务的须要,因而须要将音讯队列用在日志解决中,比方 Kafka 的利用,解决大量日志传输的问题。
架构简化如下:
<img src=”https://gitee.com/yinfeng-code/study-image/raw/master/image-20220301195357808.png” alt=”image-20220301195357808″ style=”zoom:150%;” />
架构阐明:
- 日志采集客户端,负责日志数据采集,定时写受写入 Kafka 队列
- Kafka 音讯队列,负责日志数据的接管,存储和转发
- 日志解决利用:订阅并生产 kafka 队列中的日志数据
4.5 分布式事物
分布式事务又分为强统一,弱统一,和最终一致性
-
强统一:
当更新操作实现之后,任何多个后续过程或者线程的拜访都会返回最新的更新过的值。这种是对用户最敌对的,就是用户上一次写什么,下一次就保障能读到什么。依据 CAP 实践,这种实现须要就义可用性。
-
弱统一:
零碎并不保障续过程或者线程的拜访都会返回最新的更新过的值。零碎在数据写入胜利之后,不承诺立刻能够读到最新写入的值,也不会具体的承诺多久之后能够读到。
-
最终统一:
弱一致性的特定模式。零碎保障在没有后续更新的前提下,零碎最终返回上一次更新操作的值。在没有故障产生的前提下,不统一窗口的工夫次要受通信提早,零碎负载和复制正本的个数影响。DNS 是一个典型的最终一致性零碎。
在分布式系统中,同时满足“CAP 定律”中的一致性、可用性和分区容错性三者是简直不可能的。在互联网畛域的绝大多数的场景,都须要就义强一致性来换取零碎的高可用性,零碎往往只须要保障“最终一致性”,只有这个最终工夫是在用户能够承受的范畴内即可,这时候咱们只须要用短暂的数据不统一就能够达到咱们想要成果。
场景阐明:比方有订单,库存两个数据,一个下单过程简化为,加一个订单,减一个库存。而订单和库存是独立的服务,那怎么保证数据一致性。
近程调用最郁闷的中央就是,后果有 3 种,胜利、失败和超时。超时的话,成功失败都有可能。个别的解决方案,大多数的做法是借助 mq 来做最终统一。
实现最终统一:
通过下面的架构可能会想到这些问题:
本地先执行事务,执行胜利了就发个音讯过来,生产端拿到音讯执行本人的事务。
比方 a,b 两个服务,服务 a 异步调用服务 b,如果服务 b 失败了,或者胜利,或者超时,那么怎么用 mq 让他们最终统一呢?
参照于本地事务的概念可将该场景分为三种状况解决:
- 第一种状况:假如 a,b 都失常执行,那整个业务失常完结;
- 第二种状况:假如 b 超时, 那么须要 MQ 给 b 重发消息(b 服务要做幂等),如果呈现重发失败的话,须要看状况,是中断服务,还是持续重发,甚至人为干涉;
- 第三种状况:假如 a,b 之中的一个失败了,失败的服务利用 MQ 给其余的服务发送音讯,其余的服务接管音讯,查问本地事务记录日志,如果本地也失败,删除收到的音讯(示意音讯生产胜利),如果本地胜利的话,则须要调用弥补接口进行弥补(须要每个服务都提供业务弥补接口)。
须要特地留神:
MQ 这里有个坑,通常只实用于只容许第一个操作失败的场景,也就是第一个胜利之后必须保障前面的操作在业务上没阻碍,不然前面失败了后面不好回滚,只容许零碎异样的失败,不容许业务上的失败,通常业务上失败一次前面基本上也不太可能胜利了,要是因为网络或宕机引起的失败能够通过重试解决,如果业务异样,那就只能发消息给服务 a 让他们做弥补了吧?通常是通过第三方进行弥补,各个服务须要提供弥补接口,设计范式里通常不容许生产上游业务失败。
5、总结
MQ 在分布式系统开发的场景下应用的越来越多,解决的业务能力也越来越强,所以把握 MQ 的应用场景是很要必要的。通过把握 MQ,即可解决大多数业务场景,也可在面试中加分,进步本人的外围竞争力。
最初,外出打工不易,心愿各位兄弟找到本人心仪的工作,虎年发发发!
也心愿兄弟们能关注、点赞、珍藏、评论反对一波,非常感谢大家!