消息队列: 快速理解消息队列作用

一. 什么是消息队列

消息队列不知道大家看到这个词的时候,会不会觉着它是一个比较高端的技术,在我第一次听到这个词的时候,我对他是一无所知,觉着就像写普通业务代码一样,回想起来自己当时真的是一个小白,如初生牛犊一般

消息队列,一般我们会简称它为MQ(Message Queue),就是很直白的简写

我们先不管消息(Message)这个词,来看看队列(Queue)的定义。

队列 是一种先进先出的数据结构

队列
其实在java中已经有很多队列的实现了,那为什么还需要消息队列(MQ)这种中间件呢?其实这个问题,跟之前我学Redis的时候很像。Redis是一个以key-value形式存储的内存数据库,明明我们可以使用类似HashMap这种实现类就可以达到类似的效果了,那还为什么要Redis?

  • 到这里,大家可以先猜猜为什么要用消息队列(MQ)这种中间件呢?

消息队列可以简单理解为:把要传输的数据放在队列中,例如:生产者将数据放入消息队列中,然后消费者从队列中依次取队列中的消息

为什么要用消息队列

可能有小伙伴们会问,为何要将数据放入消息队列中,再由消费者去取数据这么麻烦呢?用了消息队列有什么好处呢?

2.1 解耦

加入我们有一个系统A(订单系统) B(物流系统) C(积分系统) ,三个系统,系统A产生一个订单编号, ,B和C都需要A系统中的订单编号去做自己的业务逻辑处理,业务流程就会是下面这个样子:
在这里插入图片描述
假如一切都像这样平稳运行就好了,这样会有几个问题,

  • 如果有一天系统B和系统C不再需要调用他们的接口了,又或者增加了系统D,需要你多调用系统D的接口,怎么办???
  • 系统A在调用B系统时,B系统挂掉了怎么办???
  • 系统A在调用C系统时,由于网络延迟,请求超时了,那A是反馈fail还是重试呢?

这时候你是不是就感到无助,无能为力,怎么办???答案:跑路吧

开玩笑~~~

这个时候就需要消息队列闪亮登场了,让我们看看他会给我们的系统带来什么样的改变
在这里插入图片描述

订单系统A将OrderNo写入到消息队列中,其他系统都从消息队列中那数据,这样有什么好处呢?

  • 订单系统A只负责把数据写到队列中,谁想要或不想要这个数据(消息),系统A并不关心
  • 即便其他系统不想要OrderNo数据了,或者又重新想要OrderNo数据了,都跟系统A无关,系统A的代码不需要改动
  • 其他系统不再是从系统A被动接收OrderNo,而是主动从消息对列中拿,需不需要OrderNo由自身去控制
  • 系统B或者D挂掉都跟A系统无关,只跟消息队列有关系

这样以来,系统A 与系统B C D 都解耦了

2.2 异步

我们再来看看下面这种情况:系统A还是直接调用系统B、C、D

在这里插入图片描述
假设:系统A执行完得到OrderNo值需要50ms,调用系统B接口需要执行300ms,调用系统C的接口需要300ms,调用系统D的接口需要300ms。那么这次请求就需要50+300+300+300=950ms

并且我们得知,订单系统A做的是主要的业务,而系统B、C、D是非主要的业务。那么此时,为了提高用户体验和吞吐量,其实可以异步地调用系统B、C、D的接口。所以,我们可以弄成是这样的:
在这里插入图片描述
系统A执行完了以后,将OrderNo写到消息队列中,然后就直接返回了(至于其他的操作,则异步处理)

  • 本来整个请求需要用950ms(同步)
  • 现在将调用其他系统接口异步化,从请求到返回只需要100ms(异步)

2.3 削峰/限流

我们再来一个场景,现在我们每个月要搞一次大促,大促期间的并发可能会很高的,比如每秒3000个请求。假设我们现在有两台机器处理请求,并且每台机器只能每次处理1000个请求。
削峰场景
那多出来的1000个请求,可能就把我们整个系统给搞崩了…所以,有一种办法,我们可以写到消息队列中:
写到消息队列中,系统从队列中拿请求
系统B和系统C根据自己的能够处理的请求数去消息队列中拿数据,这样即便有每秒有8000个请求,那只是把请求放在消息队列中,去拿消息队列的消息由系统自己去控制,这样就不会把整个系统给搞崩。

三 .使用消息队列有什么问题

经过我们上面的场景,我们已经可以发现,消息队列能做的事其实还是蛮多的。

说到这里,我们先回到文章的开头,"明明JDK已经有不少的队列实现了,我们还需要消息队列中间件呢?"其实很简单,JDK实现的队列种类虽然有很多种,但是都是简单的内存队列。为什么我说JDK是简单的内存队列呢?下面我们来看看要实现消息队列(中间件)可能要考虑什么问题。

3.1 高可用

无论是我们使用消息队列来做解耦、异步还是削峰,消息队列肯定不能是单机的。试着想一下,如果是单机的消息队列,万一这台机器挂了,那我们整个系统几乎就是不可用了。
万一单机的队列挂掉了
所以,当我们项目中使用消息队列,都是得集群/分布式的。要做集群/分布式就必然希望该消息队列能够提供现成的支持,而不是自己写代码手动去实现。

3.2 数据丢失问题

我们将数据写到消息队列上,系统B和C还没来得及取消息队列的数据,就挂掉了。如果没有做任何的措施,我们的数据就丢了。还是看刚才的图
万一单机的队列挂掉了
学过Redis的都知道,Redis可以将数据持久化磁盘上,万一Redis挂了,还能从磁盘从将数据恢复过来。同样地,消息队列中的数据也需要存在别的地方,这样才尽可能减少数据的丢失。

那存在哪呢?

  • 磁盘?
  • 数据库?
  • Redis?
  • 分布式文件系统?

同步存储还是异步存储?

3.3 消费者如何得到消息队列的数据?

消费者怎么从消息队列里边得到数据?有两种办法:

  • 生产者将数据放到消息队列中,消息队列有数据了,主动叫消费者去拿(俗称push)
  • 消费者不断去轮训消息队列,看看有没有新的数据,如果有就消费(俗称pull)

3.4 其他

除了这些,我们在使用的时候还得考虑各种的问题:

  • 消息重复消费了怎么办啊?
  • 我想保证消息是绝对有顺序的怎么做?

  • 我放弃

虽然消息队列给我们带来了那么多的好处,但同时我们发现引入消息队列也会提高系统的复杂性。市面上现在已经有不少消息队列轮子了,每种消息队列都有自己的特点,选取哪种MQ还得好好斟酌。

最后

本文主要讲解了什么是消息队列,消息队列可以为我们带来什么好处,以及一个消息队列可能会涉及到哪些问题。希望给大家带来一定的帮助,后续有机会会针对上面的问题单独讲解。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值