1。前言当又是金银银的时候,所有人都按耐不住心中的躁动。在这里和大家分享一下我在之前面试中遇到的一个知识点(MQ的应用场景)。不足之处,欢迎指点。消息中间件的应用背景要提高系统性能,首先要考虑的是优化数据库,但是由于历史原因,数据库的水平扩展是一个非常复杂的工程,所以我们一般会尽量把流量挡在前面数据库。无论是无限横向扩展服务器还是垂直阻塞数据库流量,都是这个想法。阻塞直接到数据库的流量,缓存组件和消息组件是两大杀手。2、MQ简介MQ:Messagequeue,消息队列,指的是一种存储消息的容器。现在常用的MQ组件有activeMQ、rabbitMQ、rocketMQ。当然,近几年流行的Kafka,在某些场景下也是MQ,只是Kafka更强大。虽然不同的MQ有各自的特点和优势,但是,不管是哪种MQ,都有MQ本身的一些特点。常用消息队列比较特性ActiveMQRabbitMQRocketMQKafka生产者消费者模式支持支持支持支持发布订阅模式支持支持支持请求-响应模式支持支持不支持不支持API完备性highhigh多语言支持支持java支持单机吞吐量万10000、10000、100000消息延迟,无微秒、毫秒、毫秒,高可用(主从),高(主从),非常高(分布式),非常高(分布式),低消息丢失,理论上无丢失理论文档的完整性不会在Internet上丢失。高学历。高学历。提供快速启动。是的。是的。是的。社区活动。高,高,高,高的业务支持。.消息队列的顺序基本在入队时就确定了,一般不需要人工干预。而且,最重要的是,数据只是使用中的一个数据。这也是为什么在很多场景下都会用到MQ的原因。发布-订阅发布-订阅是一种非常高效的处理方式。如果没有阻塞,基本上可以认为是同步操作。这种处理方式可以有效提高服务器的利用率,这样的应用场景非常广泛。PersistencePersistence保证了MQ的使用不仅仅是一些场景的辅助工具,而是让MQ像数据库一样存储核心数据,保证MQ的可靠性。分布式在目前大流量、大数据的使用场景下,只支持单体应用的服务器软件基本无法使用,只有支持分布式部署才能得到广泛应用。而且,MQ的定位是一个高性能的中间件。4.应用场景消息队列中间件是分布式系统中的一个重要组件。主要解决应用程序解耦、异步消息、流量剃须、海量日志数据同步、分布式事务等问题,实现高性能、高可用、可扩展。和最终一致的架构。4.1应用解耦场景说明:用户下单后,订单系统需要通知库存系统。传统上,订单系统调用库存系统的接口。传统模式的缺点:如果库存系统无法访问,订单将无法减少库存,导致订单失败。订单系统和库存系统耦合度高,容易出现雪崩事故。引入应用消息队列后的解决方案:缩放:200%;"/>订单系统:用户下单后,订单系统完成持久化过程,将消息写入消息队列,成功返回用户的订单。库存系统:订阅订单消息,通过pull/push方式获取订单信息。盘点系统根据订单信息进行盘点操作。解决问题的关键步骤:下单时库存系统无法正常使用,不影响正常下单,因为下单后,订单系统写入消息队列,不再关心其他后续操作,只要达到最终一致性即可。实现订单系统和库存系统的应用解耦。4.2异步消息场景说明:用户注册后,需要发送注册邮件和注册短信。有两种传统方法:串行和并行。串口模式:注册信息成功写入数据库后,发送注册邮件,然后发送注册短信。以上三项工作全部完成后,返回给客户端。并行方式:注册信息写入数据库成功后,在发送注册邮件的同时发送一条注册短信。以上三项工作完成后,返回给客户端。与串行的区别在于并行方式可以提高处理时间。问题分析:假设三个服务节点各使用50毫秒,不考虑网络等其他开销,串行时间为150毫秒,并行时间可能为100毫秒。因为单位时间内CPU处理的请求数是一定的,假设1秒内CPU的吞吐量是100次。那么在串口模式下CPU可以在1秒内处理7个请求(1000/150)。并行处理的请求数是10倍(1000/100)。如上案例所述,传统方式下系统的性能(并发、吞吐量、响应时间)会出现瓶颈。通过消息队列将发送注册邮件和注册短信的步骤解耦:20220301194204361"style="缩放:150%;"/>根据上面的结构,用户的响应时间相当于注册信息写入数据库的时间,为50毫秒。注册邮箱,发送短信写入消息队列后,直接返回,所以写入消息队列的速度很快,基本可以忽略不计,所以用户的响应时间可能是50毫秒。因此,架构变更后,系统的吞吐量提升至每秒20QPS。比串行高3倍,比并行高2倍。4.3TrafficSlashingTrafficshaling在消息队列中也是很常见的场景,一般用在秒杀或者抢群活动中。场景描述:在秒杀活动中,一般由于流量过大,导致流量激增,导致应用或数据库挂掉。为了解决这个问题,一般需要在应用的前端添加一个消息队列。结构如下:加入消息队列的好处:可以控制活动的人数,可以缓解短时间内高流量的请求让应用用户不堪重负。服务器收到后,先写入消息队列。如果消息队列长度超过最大数量,则直接丢弃用户请求或重定向错误页面。秒杀业务根据消息队列中的请求信息进行后续处理。4.4海量日志数据同步场景描述:微服务系统下,项目往往集群部署,需要一个统一的日志平台查询各个实例的日志,但集群中的日志信息往往是海量数据,一个单一的日志采集工具无法满足业务需求,所以需要在日志处理中使用消息队列,比如Kafka的应用,解决海量日志传输的问题。架构简化如下:150%;"/>架构说明:日志采集客户端,负责日志数据采集,定时写入和接收到Kafka队列Kafka消息队列,负责接收日志数据,存储转发日志处理应用:在kafka中订阅和消费日志数据队列4.5分布式事物分布式事务分为强一致性、弱一致性和最终一致性:更新操作完成后,后续多个进程或线程的任何访问都会返回最新的更新值。这是最人性化的,就是保证用户上次写的东西下次能看得到。根据CAP理论,这种实现需要牺牲可用性。弱一致性:系统不保证延续进程或线程的访问返回最新的更新值。数据写入成功后,系统不承诺立即读取最新写入的值,也不承诺需要多长时间读取。最终一致性:一种特定形式的弱一致性。系统保证在没有后续更新的情况下,系统最终返回上次更新操作的值。在不发生故障的前提下,不一致窗口的时间主要受通信延迟、系统负载和副本数的影响。DNS是一个典型的最终一致性系统。在分布式系统中,几乎不可能同时满足“CAP法则”中的一致性、可用性和分区容错性。在互联网领域的绝大多数场景下,都需要牺牲强一致性来换取系统的高可用性。系统往往只需要保证“最终一致性”,只要最终时间在用户可接受的范围内即可。有时我们只需要利用短期的数据不一致就可以达到预期的效果。场景描述:比如有订单和库存两个数据,下订单的过程简化为加订单减库存。而订单和库存是独立的服务,那么如何保证数据的一致性。远程调用最郁闷的是有三种结果,成功,失败,超时。如果超时,则可能成功或失败。一般的解决方案,大部分的方式是使用mq来做最终一致性。实现最终一致性:通过上面的架构,你可能会想到这些问题:先在本地执行事务,执行成功后发送消息过去,消费者收到消息执行自己的事务。比如两个服务a和b,服务a异步调用服务b,如果服务b失败,成功,超时,如何使用mq让他们最终一致?参考本地事务的概念,场景可以分为三种情况:第一种情况:假设a和b正常执行,则整个业务正常结束;第二种情况:假设b超时,那么需要MQ给b重新发送消息(b服务需要幂等)。如果重发失败,看情况,是中断服务,继续重发,甚至人为干预;第三种情况:假设a和b其中一个失败了,失败的服务使用MQ向其他服务发送消息,其他服务收到消息,查询本地事务日志,如果本地也失败,删除收到的消息(说明消息消费成功),如果本地成功,则需要调用补偿接口进行补偿(每个服务都需要提供业务补偿接口)。需要特别注意的是:MQ这里有一个坑,通常只适用于只有第一次操作失败的场景,即第一次操作成功后,必须保证后续操作在业务上没有障碍,不然后面失败了就不容易回到前面了。滚,只允许系统异常故障,不允许业务故障。通常,企业失败后,基本不可能成功。如果是网络或者宕机导致的失败,可以重试解决。如果业务不正常,那只能发消息给a服务,让他们赔偿吧?补偿通常通过第三方完成,每个服务都需要提供补偿接口,设计范式通常不允许消费下游业务故障。5.小结在分布式系统开发的背景下,MQ的使用越来越多,处理业务的能力也越来越强,所以掌握MQ的使用场景是很有必要的。掌握MQ,可以解决大部分业务场景,也可以在面试中加分,提升核心竞争力。最后,出去打工也不容易。希望各位兄弟都能找到自己喜欢的工作,虎年大吉大利!也希望兄弟们多多关注、点赞、收藏、评论支持一波,万分感谢!