技术架构(8)- 消息队列

消息队列本质上是一个队列,而队列中存放的是一个个消息。它利用高效可靠的消息传递机制进行平台无关的数据交换,基于数据通信来进行分布式系统的集成,是消息传输过程中保存消息的容器。

消息的发送方称为生产者,消息的接收方称为消费者。消息队列由 Broker(消息服务器,核心部分)、Producer(消息生产者)、Consumer(消息消费者)、Topic(主题)、Queue(队列)和Message(消息体)组成。

通俗地讲,消息队列就像你家楼下的快递柜。快递员把快递放柜里,你晚上回去取。

消息队列架构

 

这是RocketMQ的架构图,其他消息队列产品与之大体相似,只是Broker有所区别。

消息队列应用场景

异步通信

把业务流程中,与核心流程不相关的环节分出去,核心流程结束之后向消息队列发个消息,其他环节订阅主题、消费消息,异步完成非核心的业务。从网上找个图,大概就这意思。

应用解耦

上面这个图,还不够严谨。虽然把非核心环节转异步了,但看起来还是在主流程里调起的异步服务。真实情况是主流程根本不关心外挂了多少个环节,它只关心生产消息,至于谁去消费就是消费者自己的事了。

这就完成了流程解耦,我只关心我自己的流程。但它也有个问题,在主流程里增加了写消息队列的逻辑,对业务代码是有侵入的。

流量削峰

在秒杀、双11这样的场景中经常用到这个功能。短时间内,极大的流量如果全部压到系统里,就算应用扛得住,数据库也要垮。

如果把这些请求先存到消息队列里,系统根据处理能力主动消费这些请求,虽然处理时间会延长,但至少服务是正常的,撑过这几分钟,流量就下来了。

延时消息

下了单,15分钟不支付,就自动取消。收货之后,7天不确认,就自动确认。这些场景如果用定时任务轮询,效率太低了。这时会用到延时消息。

 

当一个消息被投递时,broker写入commitlog日志,在分发的时候,如果它带有延时消息等级,就写入延时消息文件。延时消息服务根据消息延时的时间,将消息再次投递,成为普通消息,它被消费后,自动完成后续流程。

消息队列带来的问题

系统更复杂

引入对业务有侵入性的消息队列之后,除了正常的业务逻辑,还需要考虑消息丢失、消息重复消费、消息的消费顺序这些麻烦事。原本写curd的兄弟把业务吃透就行了,现在还要搞明白这些技术问题,要么使用最严格的配置降低总体吞吐量,要么与订阅消息的开发人员约定补偿机制。

数据不一致

如果订阅方消费失败了,原本配套的业务流程只完成了一半,这就相当于分布式事务有一部分成功、一部分失败。虽然这种情况发生的概率很低,但我们都知道分布式事务会带来多大的麻烦,系统搞不定的时候还需要人工介入,这不坑爹吗?

单点故障

要是消息队列挂了,只有主流程成功,订阅方的流程没一个执行的,你就等着炸锅吧。消息队列集群部署可以避免这个问题。

消费顺序

我们知道,网络中传输的数据包,由于链路的原因,可能出现先发的包后到,后发的包先到。消息队列也会出现这个问题。通常几个订阅者之间并没有太大的联系,对于消费顺序不是那么关心。但是,如果多个订阅者有着严格的先后处理顺序,那就必须保证先发的先消费,后发的后消费。把这些有先后顺序的消息发送到同一个queue里,利用队列先进先出的特点,就能保证顺序消费。

重复消费

生产者发送消息的时候,如果返回的ACK丢失了,它就会重发一次。消费者收到两条同样的消息,必须要对消息消费做幂等,这也算是软件开发的基本功。

常用消息队列对比

posted on 2022-12-01 10:18  别样风景天  阅读(220)  评论(0编辑  收藏  举报

导航