阿里一面,说说你知道消息中间件的应用场景有哪些?

本文涉及的产品
性能测试 PTS,5000VUM额度
云原生网关 MSE Higress,422元/月
Serverless 应用引擎免费试用套餐包,4320000 CU,有效期3个月
简介: 阿里一面,说说你知道消息中间件的应用场景有哪些?

1、前言



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


消息中间件应用背景


提高系统性能首先考虑的是数据库的优化,但是数据库因为历史原因,横向扩展是一件非常复杂的工程,所有我们一般会尽量把流量都挡在数据库之前。不管是无限的横向扩展服务器,还是纵向阻隔到达数据库的流量,都是这个思路。阻隔直达数据库的流量,缓存组件和消息组件是两大杀器。


2、MQ简介



MQ:Message queue,消息队列,是指保存消息的一个容器。

现在常用的MQ组件有activeMQ、rabbitMQ、rocketMQ、kafka,虽然不同的MQ都有自己的特点和优势,但是,不管是哪种MQ,都有MQ本身自带的一些特点。


常用消息队列比较


image.png


3、MQ特点



先进先出


先进先出,是队列最明显的特点。消息队列的顺序在入队的时候就基本已经确定了,一般是不需人工干预的。而且,最重要的是,数据是只有一条数据在使用中。 这也是MQ在诸多场景被使用的原因。


发布订阅


发布订阅是一种很高效的处理方式,如果不发生阻塞,基本可以当做是同步操作。这种处理方式能非常有效的提升服务器利用率,这样的应用场景非常广泛。


持久化


持久化确保MQ的使用不只是一个部分场景的辅助工具,而是让MQ能像数据库一样存储核心的数据,保证MQ的可靠性。


分布式


在现在大流量、大数据的使用场景下,只支持单体应用的服务器软件基本是无法使用的,支持分布式的部署,才能被广泛使用。而且,MQ的定位就是一个高性能的中间件。


4、应用场景



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


4.1 应用解耦


场景说明:在一般购物场景中,用户下单后,订单系统一般需要通知库存系统,在以前是通过接口调用进行通知。


image.png


通过接口调用的缺点:订单系统与库存系统耦合度高,容易出现雪崩事故,假如库存系统无法访问,则订单减库存将失败,从而导致订单失败,当调用量到一定程度后,会导致订单系统集群访问时间变长。


引入应用消息队列后的方案


image.png


订单系统:在用户下单后,订单系统完成本地持久化处理后将消息写入消息队列,写入成功后返回用户订单下单成功。


库存系统:订阅MQ中下单的消息,获取下单信息,库存系统根据下单信息,进行库存增或减操作。


该方案的关键步骤:


在下单时库存系统即使不能正常使用,也不影响正常下单,因为下单后,订单系统写入消息队列就不再关心其他的后续操作了,只要达成最终一致性即可。实现订单系统与库存系统的应用解耦。


4.2 异步消息


场景说明:一般用户注册后,需要给用户发送注册邮件和短信。以前的步骤可分为:串行的方式、并行方式。


1.串行方式:将用户注册信息写入数据库,写入成功后先发送注册邮件,再发送注册短信。只有以上三个任务全部完成后,才返回给客户端成功信息。


image.png


2.并行方式:将用户注册信息写入数据库,写入成功后同时发送注册邮件和注册短信。以上三个任务完成后,才返回给客户端成功信息。相对于串行而言,并行的方式可以提高处理的时间。


image.png


问题分析:


假设三个业务节点每个使用50毫秒钟,不考虑网络等其他开销,则串行方式的时间是150毫秒,并行的时间可能是100毫秒。

因为CPU在单位时间内处理的请求数是一定的,假设CPU1秒内吞吐量是100次。则串行方式1秒内CPU可处理的请求量是7次(1000/150)。并行方式处理的请求量是10次(1000/100)

如以上案例描述,传统的方式系统的性能(并发量,吞吐量,响应时间)会有瓶颈。


将发送注册邮件和注册短信的步骤通过消息队列解耦:


image.png


由以上架构可知,用户的响应时间相当于是注册信息写入数据库的时间,也就是50毫秒。注册邮件,发送短信写入消息队列后,直接返回,因此写入消息队列的速度很快,基本可以忽略,因此用户的响应时间可能是50毫秒。因此架构改变后,系统的吞吐量提高到每秒20 QPS。比串行提高了3倍,比并行提高了两倍。


4.3 流量削锋


流量削锋消息队列中也是普遍应用,一般在秒杀或团抢活动中使用广泛。


场景说明:秒杀活动,一般会因为流量过大,导致流量暴增,应用或者数据库挂掉。为解决这个问题,一般需要在应用前端加入消息队列。


架构如下:


image.png



加入消息队列的好处:


1.可以控制活动的人数

2.可以缓解短时间内高流量压垮应用


用户的请求,服务器接收后,首先写入消息队列。假如消息队列长度超过最大数量,则直接抛弃用户请求或跳转到错误页面。

秒杀业务根据消息队列中的请求信息,再做后续处理。


4.4 海量日志数据同步


场景说明:在微服务体系下,项目往往是集群部署,那么就需要一个统一日志平台来查询各个实例的日志,但集群中的日志信息往往都是海量数据,单一的日志采集工具不能满足业务的需要,因此需要将消息队列用在日志处理中,比如Kafka的应用,解决大量日志传输的问题。


架构简化如下:


image.png


架构说明:


1.日志采集客户端,负责日志数据采集,定时写受写入Kafka队列

2.Kafka消息队列,负责日志数据的接收,存储和转发

3.日志处理应用:订阅并消费kafka队列中的日志数据


4.5 分布式事物


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


1.强一致


当更新操作完成之后,任何多个后续进程或者线程的访问都会返回最新的更新过的值。这种是对用户最友好的,就是用户上一次写什么,下一次就保证能读到什么。根据 CAP 理论,这种实现需要牺牲可用性。


2.弱一致


系统并不保证续进程或者线程的访问都会返回最新的更新过的值。系统在数据写入成功之后,不承诺立即可以读到最新写入的值,也不会具体的承诺多久之后可以读到。


3.最终一致


弱一致性的特定形式。系统保证在没有后续更新的前提下,系统最终返回上一次更新操作的值。在没有故障发生的前提下,不一致窗口的时间主要受通信延迟,系统负载和复制副本的个数影响。DNS 是一个典型的最终一致性系统。


在分布式系统中,同时满足“CAP定律”中的一致性、可用性和分区容错性三者是几乎不可能的。在互联网领域的绝大多数的场景,都需要牺牲强一致性来换取系统的高可用性,系统往往只需要保证“最终一致性”,只要这个最终时间是在用户可以接受的范围内即可,这时候我们只需要用短暂的数据不一致就可以达到我们想要效果。


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


远程调用最郁闷的地方就是,结果有3种,成功、失败和超时。 超时的话,成功失败都有可能。一般的解决方案,大多数的做法是借助mq来做最终一致。


实现最终一致


image.png


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


本地先执行事务,执行成功了就发个消息过去,消费端拿到消息执行自己的事务。

比如a,b两个服务,服务a异步调用服务b,如果服务b失败了,或者成功,或者超时,那么怎么用mq让他们最终一致呢?


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


1.第一种情况:假设a,b都正常执行,那整个业务正常结束;

2.第二种情况:假设b超时,那么需要MQ给b重发消息(b服务要做幂等),如果出现重发失败的话,需要看情况,是中断服务,还是继续重发,甚至人为干预;

3.第三种情况:假设a,b之中的一个失败了,失败的服务利用MQ给其他的服务发送消息,其他的服务接收消息,查询本地事务记录日志,如果本地也失败,删除收到的消息(表示消息消费成功),如果本地成功的话,则需要调用补偿接口进行补偿(需要每个服务都提供业务补偿接口)。


需要特别注意


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


5、总结



MQ在分布式系统开发的场景下使用的越来越多,处理的业务能力也越来越强,所以掌握MQ的使用场景是很要必要的。通过掌握MQ,即可解决大多数业务场景,也可在面试中加分,提高自己的核心竞争力。


最后,外出打工不易,希望各位兄弟找到自己心仪的工作,虎年发发发!

也希望兄弟们能关注、点赞、收藏、评论支持一波,非常感谢大家!


目录
相关文章
|
6月前
|
开发框架 JavaScript 中间件
中间件应用Koa.js(Node.js)
【5月更文挑战第3天】我们添加了两个中间件。第一个中间件记录请求的开始时间,并在下一个中间件执行完毕后计算并打印出请求的总时间。第二个中间件与之前的示例相同,它设置响应体为 "Hello World"
59 6
中间件应用Koa.js(Node.js)
|
2月前
|
中间件 API 开发者
深入理解Python Web框架:中间件的工作原理与应用策略
在Python Web开发中,中间件位于请求处理的关键位置,提供强大的扩展能力。本文通过问答形式,探讨中间件的工作原理、应用场景及实践策略,并以Flask和Django为例展示具体实现。中间件可以在请求到达视图前或响应返回后执行代码,实现日志记录、权限验证等功能。Flask通过装饰器模拟中间件行为,而Django则提供官方中间件系统,允许在不同阶段扩展功能。合理制定中间件策略能显著提升应用的灵活性和可扩展性。
40 4
|
3月前
|
中间件 数据库连接 UED
Django中间件秘籍:如何用几行代码让你的应用变得超级强大?
【8月更文挑战第31天】中间件是Django框架的核心特性,位于视图与HTTP服务器之间,允许全局处理请求和响应,增强Web应用功能。通过实现`MiddlewareMixin`类的方法,如`process_request`和`process_response`,可以轻松实现请求预处理或响应后处理。中间件应用场景广泛,包括用户认证、CSRF防护和数据库连接管理等。创建并配置中间件需将其加入`settings.py`的`MIDDLEWARE`列表,顺序决定执行优先级。合理利用中间件能提高代码重用性和应用性能,带来更好的用户体验。
53 0
|
5月前
|
设计模式 监控 中间件
PHP中的中间件模式及其应用
【6月更文挑战第24天】在PHP开发中,中间件是一种设计模式,它允许开发者在请求处理流程的不同阶段插入自定义的处理逻辑。本文将介绍PHP中间件的概念、实现方式以及如何利用中间件提高代码的可维护性和扩展性。通过实际案例,我们将探索中间件在身份验证、日志记录和性能监控等方面的应用,并讨论如何在Laravel框架中有效使用中间件。
|
5月前
|
设计模式 中间件 API
PHP中的中间件模式及其应用
【6月更文挑战第24天】在现代Web开发中,设计模式的应用是提高代码可维护性和扩展性的关键。本文将深入探讨PHP中中间件模式的概念、实现方式以及在实际项目中的应用案例,旨在为开发者提供一种灵活处理HTTP请求和响应的有效手段。
|
5月前
|
中间件 开发者 C++
Django中间件探索:揭秘中间件在Web应用中的守护角色与实战应用
Django中间件探索:揭秘中间件在Web应用中的守护角色与实战应用
|
4月前
|
缓存 监控 安全
中间件在Python Web框架中的角色与应用场景
【7月更文挑战第21天】中间件在Python Web开发中作为服务器与应用间的软件层,拦截、处理请求和响应,无需改动应用代码。它扩展框架功能,复用跨应用逻辑,加强安全,优化性能。如Django中间件处理请求/响应,Flask通过WSGI中间件实现类似功能,两者均在不触及核心代码前提下,灵活增强应用行为,是现代Web开发关键组件。
56 0
|
4月前
|
中间件 API 开发者
深入理解Python Web框架:中间件的工作原理与应用策略
【7月更文挑战第19天】Python Web中间件摘要:**中间件是扩展框架功能的关键组件,它拦截并处理请求与响应。在Flask中,通过`before_request`和`after_request`装饰器模拟中间件行为;Django则有官方中间件系统,需实现如`process_request`和`process_response`等方法。中间件用于日志、验证等场景,但应考虑性能、执行顺序、错误处理和代码可维护性。
81 0
|
6月前
|
中间件 Python
中间件应用Django Middleware(Python)
【5月更文挑战第3天】中间件应用Django Middleware(Python)
80 6
中间件应用Django Middleware(Python)
|
6月前
|
存储 缓存 监控
中间件应用合理使用缓存和数据结构
【5月更文挑战第4天】中间件应用合理使用缓存和数据结构
99 3
中间件应用合理使用缓存和数据结构
下一篇
无影云桌面