前言
上一次写了一篇 那些年,面试官问你的消息队列 没有深入概念,今天总结一下。
1、什么是消息队列?
消息队列:也就是MQ(Message Queue),是基础数据结构中“先进先出”的一种数据结构。一般用来解决应用解耦,异步消息,流量削锋等问题,实现高性能,高可用,可伸缩和最终一致性架构。
指把要传输的数据(消息)放在队列中,用队列机制来实现消息传递——生产者产生消息并把消息放入队列,然后由消费者去处理。消费者可以到指定队列拉取消息,或者订阅相应的队列,由MQ服务端给其推送消息。
概念:
- 把数据放到消息队列叫做 生产者
- 从消息队列里边去数据叫做 消费者
2、为什么要使用消息队列
解耦: 一个业务需要多个模块共同实现,或者一条消息有多个系统需要对应处理,只需要主业务完成以后,发送一条MQ,其余模块消费MQ消息,即可实现业务,降低模块之间的耦合。
场景描述: 系统A产生 userId
,现在系统B和C需要用这个 userId
做相关操作,过几天说,系统B使用 userId
的接口不用了,让A别去调用它。 然后又说D系统也需要用A的 userId
,得调用接口 ......
那么,系统A将 userId
写到消息队列中,系统 C 和 D 从消息队列中拿数据。无论谁用都和系统A没关系。且即使其他系统挂掉或者请求超时都不会影响到系统A,只和消息队列有关。 这样就完成了解耦。
异步: 主业务执行结束后从属业务通过MQ,异步执行,减低业务的响应时间,提高用户体验。
场景描述: 系统A直接调用系统B、C、D,有上图得出这次请求需要 50+300+300+300=950ms
, 系统A做的主要业务,而系统B、C、D不是。比如系统A处理的是订单下单,而系统B是订单下单成功了,那发送一条短信告诉具体的用户此订单已成功,系统C和D也是处理小事。
为了提高用户体验和吞吐量,异步地调用系统B、C、D的接口。系统A执行完了以后,将 userId
写到消息队列中,然后直接返回(其它操作,异步处理)。现在只需要 100ms
削峰: 高并发情况下,业务异步处理,提供高峰期业务处理能力,避免系统瘫痪。
场景描述: 假设每个月要搞一次大促,大促期间的并发可能会很高的,比如每秒3000个请求。假设我们现在有两台机器处理请求,并且每台机器只能每次处理1000个请求。
多出的1000个请求可能会把整个系统搞崩了,所以我们可以写到消息队列中:系统B和系统C根据自己的能够处理的请求数去消息队列中拿数据,这样即便有每秒有8000个请求,那只是把请求放在消息队列中,去拿消息队列的消息由系统自己去控制,这样就不会把整个系统给搞崩。
3、使用消息队列的问题
1、系统可用性降低。依赖服务也多,服务越容易挂掉。需要考虑MQ瘫痪的情况。
2、系统复杂性提高。需要考虑消息丢失、消息重复消费、消息传递的顺序性。
我们将数据写到消息队列上,系统B和C还没来得及取消息队列的数据,就挂掉了。如果没有做任何的措施,我们的数据就丢了。
3、业务一致性。主业务和从属业务一致性的处理。