00:00
接下来我们来学习一下rabbit MQ,首先我们来说什么是MQ,它的全称呢叫messageq,就是消息队列。队列这个东西呢,大家非常熟悉了,它类似于一种list结构,专门来存储数据的一个队列,那这个队列呢,数据可以从队列的头,比如我们这个队列,这是一个头从这里边进去,比如我们进一个一号数据,我们要想再进第二个数据,我们还是从对头里边,比如我们来进去二号数据,三号数据,那如果我们想取数据,我们可以从队列的尾,队尾来取出数据,那我们就取出了一号数据,这就是一个典型的队列,那这个呢,就是我们称为叫先进先出的队列,那一号先进来,我们从队尾取一号就先出来,那如果我们从对头入队,我们一个元素,一号放进去,二号放进去,三号放进去,而我们也从对头取数据,那这就是一个先进后出。
01:00
不的队列,我们一号先进去,但是呢,它最后才会被取出来,这其实就是一个典型的站结构了,如果我们两头都可以给队列里边放数据,两头也都可以取,那这就是我们说的双端队列,但这个队列呢,在我们Java里边也有对应的API,我们也有相应的Q,但是我们说我们Java里边带的APIQ也好,它都是基于内存级别的,如我们一个微服务,我们即使来创建出Q来保存消息,那最多只能在它的机器里边来使用,但在我们分布式系统下,那肯定呢需要一个公共的中间件,它呢能存储我们这些消息,而且可能也需要有序的取出这些消息,我们A服务存,D服务也要取,可能C服务也要往进,存D服务也要取,而且他们用的队列可能还有很多,各个都不一样,所以呢,我们在分布式系统开发里边,我们业务场景肯定需要一个,我们称为叫消息中间件。
02:00
这个中间件呢,那就是给我们服务器里边安装的一个这个中间件,然后我们消息呢,全部保存到这个服务器里边,那别的微服务可以从这一块来取消息,M rabbit MQ就是我们接下来要学习的这个消息中间件,那消息中间件在我们微服务中的这个使用场景,也是我们分布式系统里边的使用场景是什么呢?首先我们来说一下第一个最简单的场景,异步处理,假设我们以前的一个普通业务,我们以用户注册为例,我们这个用户呢,通过浏览器提交了账号密码,注册了信息,那注册用户信息呢,我们可能分为这三步,第一步我们将用户注册的这些信息我们先保存到数据库,假设们要花费50毫秒,那保存完了,接下来第二步,我们要给用户发送邮件,告诉他注册成功,诶那我们这个呢,假设花费50毫秒,好,我们第一个方法做完,我们调用第二个方法,那邮件呢,发完以后,我们还要给用户发送通知短信,告诉他注册。
03:00
成功,那我们这个短信呢,假设也要发送等候50毫秒,那我们以前呢,就是一方法做完调二方法调三方法,那这种呢是一个同步模式,那这种同步模式的话,我们用户注册完到他看到整个响应注册成功,那至少需要花费我们150毫秒的时间,但我们发现呢,这个是没必要的,因为这个注册邮件和发送短信,我们如果使用第二种模式,我们可以给他整一个异步,就是说如果我们这个用户把注册信息写入到数据库,只要数据库保存了,相当于注册成功了,那成功以后呢,加我们来new thread start,开一个异步,再来newread start,再开两个一步,第一个异步任务呢,给我们发邮件,第二个异步任务给我们来发短信,那接下来我们要等完整的返回,当然这两个异步任务我们现在呢,只需要等一个最长时间,假设都是50,那我们只需要等50毫秒,那么的异步任务就会有返回,那么现在呢,就可以响应100毫。
04:00
我们缩短了用户的这个处理时间,那这样看起来呢,好像注册更快了,但是其实实际上我们连一步都不需要,因为发现呢,注册邮件,发送这个邮件,以及发送这个注册成功的这个短信,这两个呢,让他后台慢慢发,那成功不成功我们也无需知道,只要他做了这件事儿就行,而且我们也经常会有收不到邮件,收不到短信的这种各种情况,所以呢,遇见这种情况,我们还可以使用第三种方式,我们如果把我们这个注册信息写入数据库成功了,接下来我们将注册成功的这个消息我们写入消息队列,像我们保存在我们的消息中间件这个服务器中,我们保存了一个一号用户注册成功的消息,然后呢,至此我们就直接给我们用户返回,因为这个给消息中间件来写消息的,这个是耗时是非常短的,数据库呢,要插入数据要持久化可能很慢,需要50毫秒写消息呢。
05:00
类似于直接操作red一样,假设呢,只花费了五毫秒超快,那么现在用户收到这个响应就55毫秒就直接收到了,但用户能不能收到短信和邮件呢?也可以,我们这个消息既然存到了消息队列里边,那别的服务呢,就可以从消息队列里边拿到我们这个消息,诶,拿到一号,用户注册成功了,然后呢,他自己在后台该去发短信发短信,该去发邮件发邮件,我们不关心他什么时候发短信发邮件,只要他干了这个事儿就行,但是我们用户呢,至此会立即响应成功,这是我们说的第一个异步处理。我们可以提升系统的异步处理能力,比我们以前做的异步任务更快,但异步任务呢,我们还必须等待返回,而我们这一块呢,我们就直接给他给一个消息,让他后台去慢慢来做就行了,就是我们说的第一个场景,异步处理消息队列的第二个场景,我们可以用于应用解偶,怎么会解偶呢?我们以下订单为例,比如我们下了一个订单,我们这个订单支付完了以后,我们库存呢,要进行出库操作,那我们以前的操作就是我们订单一支付,或者一下订单,我们订单下了,我们比如要减库存,我们要调用库存系统的减库存,假如下订单方法API呢,它传了三个参数,调库存的方法呢,它传了五个参数,那下订单执行完以后,调用我们的减库存,那如果我们这个库存系统不升级,我们这一块API不变,一直是这五个参数,那还好,当然我们库存系统假设经常会升级,那么这个减库存。
06:40
那接口呢,经常发生变化,那这样以前我们的这种调用方式,那下订单完了去来调减库存的五个接口的这个方法,那我们就会发现,只要库存系统一升级,我们的订单系统就必须来修改它的源代码,重新部署,只要库存系统一升级,我们就必须修改源代码,重新部署,这样呢就感觉会非常麻烦,所以呢,我们可以引入我们的消息队列,我们订单系统呢,只要下好订单,我们给消息队列里边写上一个消息,说我们哪个用户下了哪个订单,购买了哪些商品,把这个消息呢保存在队列里边。库存系统呢,我们不关心库存系统的接口是什么样,要五个参数,八个参数还是十个参数,我们只需要把我们的消息写进去,将来库存系统呢,它要实时的订阅我们这个队列里边的内容,只要有内容,我们库存系统就会收到我们刚才写的这个消息,然后呢,他分析我们这个消息都有哪些商品,哪个用户下了什么单,他自己去在这儿。
07:40
减库存也可以,所以我们此时呢,我们发现我们订单干完事以后,我们无需关心库存系统要调用什么接口,我们只需要写消息就行了,所以我们就实现了应用结果,以后无论什么系统想要知道我们订单成功以后要做什么,他呢都只需要订阅我们消息队列里边订单成功的消息,我们不关心别的系统接口设计成什么样子,因为我们根本就无需调用,所以这是我们的第二个场景叫应用结构。接下来我们还可以有第三种场景,比如流量控制,特别对于一些秒杀业务来说,瞬间流量呢会非常大,比如我们瞬间百万个请求,我们都要进来秒杀一个商品,那么这个商品要真正去来执行业务,就算我们前端服务器,我们可以接受了百万请求,我们要执行业务代码,因为我们要秒杀完要下订单,整个流程呢会非常慢,那后台一直阻塞,可能就会导致我们最终的资源耗尽,我们机器宕机。那此时我们。
08:40
诶,怎么做呢?我们将大并发量的请求全部进来,进来以后呢,别的不说,我们先给它存储到消息队列里边,那存到消息队列以后呢,我们就可以不用管我们这个请求该怎么做了,我们直接给他响应,诶我们这个秒杀成功了,或者怎么着,然后呢,我们接下来消息队列我们后台的真正业务处理,要下订单,要减库存等等,这些业务处理我们不着急立即调用,只要存到消息队列里边,我们这些业务呢,去来订阅我们消息队列里边进来的这些秒杀请求,我们接下来挨个进行处理下订单,挨个处理下订单,即使我们后台的处理能力一秒只有一个,那我们也不担心100万个,我们花花费上100万秒就行了,但我们永远都不会导致我们机器的资源耗尽而宕机,所以我们可以达到前端的流量控制,我们把所有的流量存到队列里边,后台根据它的能力去来进行消费和处理,我们不会导致我们机器宕机。
09:40
所以这是我们说的流量控制,我们也称为流量消峰,我们把它的峰值给它消下来,我们全部存到队列里边,这是我们消息中间件,咱们分布式系统里边最常用的一些场景。
我来说两句