精华内容
下载资源
问答
  • 什么是消息队列你了解过么?

    你知道的越多,你不知道的越多

    点赞再看,养成习惯

    GitHub上已经开源 https://github.com/JavaFamily 有一线大厂面试点脑图、个人联系方式,欢迎Star和完善

    面试开始

    一个风度翩翩,穿着格子衬衣的中年男子,拿着一个满是划痕的mac向你走来,看着铮亮的头,心想着肯定是尼玛顶级架构师吧!但是我们看过暖男敖丙的系列,腹有诗书气自华,虚都不虚。

    小伙子之前问了你这么多Redis的知识,你不仅对答如流,你还能把各自场景的解决方案,优缺点说得这么流畅,说你是不是看过敖丙写的《吊打面试官》系列呀?

    惊!!!老师你怎么知道的,我看了他的系列根本停不下来啊。

    呵呵,Redis没难住你,但是我问个新的技术栈我还怕难不住你?我问问你你项目中用过消息队列么?你为啥用消息队列?

    噗此,这也叫问题?别人用了我能不用么?别人用了我就用了呗,我就是为了用而用。

    你心里嘀咕就好了,千万别说出来哈,说出来了没拿到Offer别到时候就在那说,敖丙那个渣男教我说的!

    面试官你好:我们公司本身的业务体量很小,所以直接单机一把梭啥都能搞定了,但是后面业务体量不断扩大,采用微服务的设计思想分布式的部署方式,所以拆分了很多的服务,随着体量的增加以及业务场景越来越复杂了,很多场景单机的技术栈和中间件以及不够用了,而且对系统的友好性也下降了,最后做了很多技术选型的工作,我们决定引入消息队列中间件

    哦?你说到业务场景越来越复杂,你那说一下你都在什么场景用到了消息队列?

    嗯,我从三个方面去说一下我使用的场景吧。

    Tip:这三个场景也是消息队列的经典场景,大家基本上要烂熟于心那种,就是一说到消息队列你脑子就要想到异步、削峰、解耦,条件反射那种。

    异步:

    我们之前的场景里面有很多步骤都是在一个流程里面需要做完的,就比如说我的下单系统吧,本来我们业务简单,下单了付了钱就好了,流程就走完了。

    但是后面来了个产品经理,搞了个优惠券系统,OK问题不大,流程里面多100ms去扣减优惠券。

    后来产品经理灵光一闪说我们可以搞个积分系统啊,也行吧,流程里面多了200ms去增减积分。

    再后来后来隔壁的产品老王说:下单成功后我们要给用户发短信,也将就吧,100ms去发个短信。

    再后来。。。(敖丙你有完没完!!!)

    反正就流程有点像这样 ↓

    你们可以看到这才加了三个,我可以斩钉截铁的告诉你真正的下单流程涉及的系统绝对在10个以上(主流电商),越大的越多。

    这个链路这样下去,时间长得一批,用户发现我买个东西你特么要花几十秒,垃圾电商我不在你这里买了,不过要是都像并夕夕这么便宜,真香

    但是我们公司没有夕夕的那个经济实力啊,那只能优化系统了。

    Tip:我之前在的电商老东家要求所有接口的RtResponseTime响应时间)在200ms内,超出的全部优化,我现在所负责的系统QPS也是9W+就是抖动一下网络集群都可能炸锅那种,RT基本上都要求在50ms以内。

    大家感受一下这个QPS。

    嗯不错,链路长了就慢了,那你怎么解决的?

    那链路长了就慢了,但是我们发现上面的流程其实可以同时做的呀,你支付成功后,我去校验优惠券的同时我可以去增减积分啊,还可以同时发个短信啊。

    那正常的流程我们是没办法实现的呀,怎么办,异步

    你对比一下是不是发现,这样子最多只用100毫秒用户知道下单成功了,至于短信你迟几秒发给他他根本不在意是吧。

    小伙子我打断你一下,你说了异步,那我用线程,线程池去做不是一样的么?

    诶呀,面试官你不要急嘛,我后面还会说到的,骚等。

    解耦:

    既然面试官这么问了,我就说一下为啥我们不能用线程去做,因为用线程去做,你是不是要写代码?

    你一个订单流程,你扣积分,扣优惠券,发短信,扣库存。。。等等这么多业务要调用这么多的接口,每次加一个你要调用一个接口然后还要重新发布系统,写一次两次还好,写多了你就说:老子不干了!

    而且真的全部都写在一起的话,不单单是耦合这一个问题,你出问题排查也麻烦,流程里面随便一个地方出问题搞不好会影响到其他的点,小伙伴说我每个流程都try catch不就行了,相信我别这么做,这样的代码就像个定时炸弹💣,你不知道什么时候爆炸,平时不炸偏偏在你做活动的时候炸,你就领个P0故障收拾书包提前回家过年吧。

    Tip:P0—PN 是互联网大厂经常用来判定事故等级的机制,P0是最高等级了。

    但是你用了消息队列,耦合这个问题就迎刃而解了呀。

    哦,帅丙怎么说?

    且听我娓娓道来:

    你下单了,你就把你支付成功的消息告诉别的系统,他们收到了去处理就好了,你只用走完自己的流程,把自己的消息发出去,那后面要接入什么系统简单,直接订阅你发送的支付成功消息,你支付成功了我监听就好了

    那你的流程走完了,你不用管别人是否成功么?比如你下单了积分没加,优惠券没扣怎么办?

    问题是个好问题,但是没必要考虑,业务系统本身就是自己的开发人员维护的,你积分扣失败关我下单的什么事情?你管好自己下单系统的就好了。

    Tip:话是这么说,但是这其实是用了消息队列的一个缺点,涉及到分布式事务的知识点,我下面会提到。

    削峰:

    就拿我上一期写的秒杀来说(暗示新同学看我上一期),你平时流量很低,但是你要做秒杀活动00 :00的时候流量疯狂怼进来,你的服务器,RedisMySQL各自的承受能力都不一样,你直接全部流量照单全收肯定有问题啊,直接就打挂了。

    那怎么办?

    简单,把请求放到队列里面,然后至于每秒消费多少请求,就看自己的服务器处理能力,你能处理5000QPS你就消费这么多,可能会比正常的慢一点,但是不至于打挂服务器,等流量高峰下去了,你的服务也就没压力了。

    你看阿里双十一12:00的时候这么多流量瞬间涌进去,他有时候是不是会慢一点,但是人家没挂啊,或者降级给你个友好的提示页面,等高峰过去了又是一条好汉了。

    为了这个图特意打高一台服务的流量
    为了这个图特意打高一台服务的流量

    听你说了辣么多,怎么都是好处,那我问你使用了消息队列有啥问题么?

    诶,看过前面我写的文章的人才都知道,我经常说的就是,技术是把双刃剑

    没错面试官,我使用他是因为他带给我们很多好处,但是使用之后问题也是接踵而至

    同样的暖男我呀,也从三个点介绍他主要的缺点:

    系统复杂性

    本来蛮简单的一个系统,我代码随便写都没事,现在你凭空接入一个中间件在那,我是不是要考虑去维护他,而且使用的过程中是不是要考虑各种问题,比如消息重复消费消息丢失消息的顺序消费等等,反正用了之后就是贼烦。

    我插一句嘴,上面的问题(重复消费、消息丢失、顺序消费)你能分别介绍一下,并且说一下分别是怎么解决的么?

    不要!我都说了敖丙下一章写啥?

    其实不是暖男我不想在这里写,这三个问题我想了下,统统都是MQ重点问题,单独拿一个出来就是一篇文章了,篇幅实在太长了,我会在下一章挨个介绍一遍的。

    数据一致性

    这个其实是分布式服务本身就存在的一个问题,不仅仅是消息队列的问题,但是放在这里说是因为用了消息队列这个问题会暴露得比较严重一点。

    就像我开头说的,你下单的服务自己保证自己的逻辑成功处理了,你成功发了消息,但是优惠券系统,积分系统等等这么多系统,他们成功还是失败你就不管了?

    我说了保证自己的业务数据对的就好了,其实还是比较不负责任的一种说法,这样就像个渣男,没有格局这样呀你的路会越走越窄的

    所有的服务都成功才能算这一次下单是成功的,那怎么才能保证数据一致性呢?

    分布式事务:把下单,优惠券,积分。。。都放在一个事务里面一样,要成功一起成功,要失败一起失败。

    Tip:分布式事务在互联网公司里面实在常见,我也不在这里大篇幅介绍了,后面都会专门说的。

    可用性

    你搞个系统本身没啥问题,你现在突然接入一个中间件在那放着,万一挂了怎么办?我下个单MQ挂了,优惠券不扣了,积分不减了,这不是杀一个程序员能搞定的吧,感觉得杀一片。

    至于怎么保证高可用,还是那句话也不在这里展开讨论了,我后面一样会写,像写Redis那样写出来的。

    放心敖丙我不是渣男来的,我肯定会对你们负责的。点赞!

    看不出来啊,你有点东西呀,那我问一下你,你们是怎么做技术选型的?

    目前在市面上比较主流的消息队列中间件主要有,Kafka、ActiveMQ、RabbitMQ、RocketMQ 等这几种。

    不过敖丙我想说的是,ActiveMQRabbitMQ这两着因为吞吐量还有GitHub的社区活跃度的原因,在各大互联网公司都已经基本上绝迹了,业务体量一般的公司会是有在用的,但是越来越多的公司更青睐RocketMQ这样的消息中间件了。

    KafkaRocketMQ一直在各自擅长的领域发光发亮,不过写这篇文章的时候我问了蚂蚁金服,字节跳动和美团的朋友,好像大家用的都有点不一样,应该都是各自的中间件,可能做过修改,也可能是自研的,大多没有开源

    就像我们公司就是是基于KafkaRocketMQ两者的优点自研的消息队列中间件,吞吐量、可靠性、时效性等都很可观。

    我们回归正题,我这里用网上找的对比图让大家看看差距到底在哪里:

    大家其实一下子就能看到差距了,就拿吞吐量来说,早期比较活跃的ActiveMQRabbitMQ基本上不是后两者的对手了,在现在这样大数据的年代吞吐量是真的很重要

    比如现在突然爆发了一个超级热点新闻,你的APP注册用户高达亿数,你要想办法第一时间把突发全部推送到每个人手上,你没有大吞吐量的消息队列中间件用啥去推?

    再说这些用户大量涌进来看了你的新闻产生了一系列的附带流量,你怎么应对这些数据,很多场景离开消息队列基本上难以为继

    部署方式而言前两者也是大不如后面两个天然分布式架构的哥哥,都是高可用的分布式架构,而且数据多个副本的数据也能做到0丢失。

    我们再聊一下RabbitMQ这个中间件其实还行,但是这玩意开发语言居然是erlang,我敢说绝大部分工程师肯定不会为了一个中间件去刻意学习一门语言的,开发维护成本你想都想不到,出个问题查都查半天。

    至于RocketMQ(阿里开源的),git活跃度还可以。基本上你push了自己的bug确认了有问题都有阿里大佬跟你试试解答并修复的,我个人推荐的也是这个,他的架构设计部分跟同样是阿里开源的一个RPC框架是真的很像(Dubbo)可能是因为师出同门的原因吧。

    Tip:Dubbo等我写到RPC我会详细介绍的。

    Kafka我放到最后说,你们也应该知道了,压轴的这是个大哥,大数据领域,公司的日志采集,实时计算等场景,都离不开他的身影,他基本上算得上是世界范围级别的消息队列标杆了。

    以上这些都只是一些我自己的个人意见,真正的选型还是要去深入研究的,不然那你公司一天UV就1000你告诉我你要去用Kafka我只能说你吃饱撑的。

    记住,没有最好的技术,只有最适合的技术,不要为了用而用

    面试结束

    嗯,小伙子不错不错,分析得很到位,那你记得下期来说一下消息队列的高可用,重复消费、消息丢失、消息顺序、分布式事务等问题?

    嗯嗯好的面试官,不过不确定能不能一口气说完,毕竟敖丙还没开始写,而且读者还有可能白嫖,动力不一定够。

    嗯嗯这倒是个问题,不过啊在看的都是人才肯定会给你点赞👍的!

    我也这么认为。

    总结

    消息队列的基础知识我就先介绍这么多,消息队列在面试里面基本上也是跟我前面写的Redis一样必问的。

    面试的思路还是一样,要知其然,也要知其所以然,就是要知道为啥用,用了有啥好处,有啥坑。

    面试官不喜欢只知道用的,你只会用那哪天线上出问题怎么办?你难道在旁边拜佛?

    Tip:本来有很多我准备的资料的,但是都是外链,或者不合适的分享方式,博客的运营小姐姐提醒了我,所以大家去公众号回复【资料】好了。

    鸣谢

    之前的文章写了很多人加我,然后有个人才说是他蚂蚁金服的Leader推荐的我,我突然意识到我文章的受众好像慢慢变广了,之后不严谨的点要杜绝掉。

    所以之后我的文章经常会有大厂的小伙伴Review,也希望帮助我更好的监督自己的文章吧。

    这次是 某阿里系电商跟我一起做过活动小组的 佩恩 帮我Review的文章,感谢!

    絮叨

    另外,敖丙把自己的面试文章整理成了一本电子书,共 1630页!目录如下

    现在免费送给大家,在我的公众号三太子敖丙回复 【888】 即可获取。

    我是敖丙,一个在互联网苟且偷生的程序员。

    你知道的越多,你不知道的越多人才们的 【三连】 就是丙丙创作的最大动力,我们下期见!

    注:如果本篇博客有任何错误和建议,欢迎人才们留言!


    文章持续更新,可以微信搜索「 三太子敖丙 」第一时间阅读,回复【资料】有我准备的一线大厂面试资料和简历模板,本文 GitHub https://github.com/JavaFamily 已经收录,有大厂面试完整考点,欢迎Star。

    展开全文
  • 什么是消息队列

    2020-09-20 10:40:00
    一、什么是消息队列? 消息队列不知道大家看到这个词的时候,会不会觉得它是一个比较高端的技术,反正我是觉得它好像是挺牛逼的。 消息队列,一般我们会简称它为 MQ(Message Queue),嗯,就是很直白的简写。  ...

    一、什么是消息队列?

    • 消息队列不知道大家看到这个词的时候,会不会觉得它是一个比较高端的技术,反正我是觉得它好像是挺牛逼的。
      • 消息队列,一般我们会简称它为 MQ(Message Queue),嗯,就是很直白的简写。  
    • 我们先不管消息 (Message) 这个词,来看看队列 (Queue)。这一看,队列大家应该都熟悉吧。
      • 队列是一种 "先进先出" 的数据结构。  

    • 消息队列可以简单理解为:把要传输的数据放在队列中
    • 科普:

      • 把数据放到消息队列叫做 生产者
      • 从消息队列里边取数据叫做 消费者

    二、为什么要用消息队列?

    • 为什么要用消息队列,也就是在问:用了消息队列有什么好处。我们看看以下的场景
    • 2.1 解耦
      • 现在我有一个系统 A,系统 A 可以产生一个 userId      

      • 然后,现在有系统B和系统C都需要这个userId去做相关的操作  

      • 写成伪代码可能是这样的:
    public class SystemA {
    
        // 系统B和系统C的依赖
        SystemB systemB = new SystemB();
        SystemC systemC = new SystemC();
    
        // 系统A独有的数据userId
        private String userId = "Java3y";
    
        public void doSomething() {
    
            // 系统B和系统C都需要拿着系统A的userId去操作其他的事
            systemB.SystemBNeed2do(userId);
            systemC.SystemCNeed2do(userId);
    
        }
    }
    
      • 结构图如下:   

      • 某一天,系统 B 的负责人告诉系统 A 的负责人,现在系统 B 的 SystemBNeed2do(String userId) 这个接口不再使用了,让系统 A 别去调它了。于是,系统 A 的负责人说 "好的,那我就不调用你了。",于是就 把调用系统 B 接口的代码给删掉了:  
    public void doSomething() {
    
      // 系统A不再调用系统B的接口了
      //systemB.SystemBNeed2do(userId);
      systemC.SystemCNeed2do(userId);
    
    }
    
      • 又过了几天,系统 D 的负责人接了个需求,也需要用到系统 A 的 userId,于是就跑去跟系统 A 的负责人说:"老哥,我要用到你的 userId,你调一下我的接口吧" 于是系统 A 说:"没问题的,这就搞"  

      • 然后,系统A的代码如下:  
    public class SystemA {
    
        // 已经不再需要系统B的依赖了
        // SystemB systemB = new SystemB();
    
        // 系统C和系统D的依赖
        SystemC systemC = new SystemC();
        SystemD systemD = new SystemD();
    
        // 系统A独有的数据
        private String userId = "Java3y";
    
        public void doSomething() {
    
    
            // 已经不再需要系统B的依赖了
            //systemB.SystemBNeed2do(userId);
    
            // 系统C和系统D都需要拿着系统A的userId去操作其他的事
            systemC.SystemCNeed2do(userId);
            systemD.SystemDNeed2do(userId);
    
        }
    }
    
      • 时间飞逝:
        • 又过了几天,系统E的负责人过来了,告诉系统 A,需要 userId。    
        • 又过了几天,系统B的负责人过来了,告诉系统 A,还是重新掉那个接口吧。    
        • 又过了几天,系统F的负责人过来了,告诉系统 A,需要 userId。    
        • …...    
      • 于是系统 A 的负责人,每天都被这给骚扰着,改来改去,改来改去.......还有另外一个问题,调用系统 C 的时候,如果系统 C 挂了,系统 A 还得想办法处理。如果调用系统 D 时,由于网络延迟,请求超时了,那系统 A 是反馈 fail 还是重试??最后,系统 A 的负责人,觉得隔一段时间就改来改去,没意思,于是就跑路了。  
      • 然后,公司招来一个大佬,大佬经过几天熟悉,上来就说:将系统 A 的 userId 写到消息队列中,这样系统 A 就不用经常改动了。为什么呢?下面我们来一起看看:  

        • 系统 A 将 userId 写到消息队列中,系统 C 和系统 D 从消息队列中拿数据。这样有什么好处
          • 系统 A 只负责把数据写到队列中,谁想要或不想要这个数据(消息),系统A一点都不关心。      
          • 即便现在系统 D 不想要 userId 这个数据了,系统 B 又突然想要 userId 这个数据了,都跟系统 A 无关,系统 A 一点代码都不用改。  
          • 系统 D 拿 userId 不再经过系统 A,而是从消息队列里边拿。系统 D 即便挂了或者请求超时,都跟系统 A 无关,只跟消息队列有关。      
          • 这样一来,系统 A 与系统 B、C、D 都解耦了。      
    • 2.2 异步
      • 我们再来看看下面这种情况:系统 A 还是直接调用系统 B、C、D  

      • 代码如下:
    public class SystemA {
    
        SystemB systemB = new SystemB();
        SystemC systemC = new SystemC();
        SystemD systemD = new SystemD();
    
        // 系统A独有的数据
        private String userId ;
    
        public void doOrder() {
    
            // 下订单
            userId = this.order();
            // 如果下单成功,则安排其他系统做一些事  
            systemB.SystemBNeed2do(userId);
            systemC.SystemCNeed2do(userId);
            systemD.SystemDNeed2do(userId);
    
        }
    }
    
      • 假设系统 A 运算出 userId 具体的值需要 50ms,调用系统B的接口需要 300ms,调用系统 C 的接口需要 300ms,调用系统 D 的接口需要 300ms。那么这次请求就需要 50+300+300+300=950ms  
      • 并且我们得知,系统 A 做的是主要的业务,而系统 B、C、D 是非主要的业务。比如系统 A 处理的是订单下单,而系统 B 是订单下单成功了,那发送一条短信告诉具体的用户此订单已成功,而系统 C 和系统 D 也是处理一些小事而已。    
      • 那么此时,为了提高用户体验和吞吐量,其实可以异步地调用系统 B、C、D 的接口。所以,我们可以弄成是这样的:  

      • 系统A执行完了以后,将 userId 写到消息队列中,然后就直接返回了(至于其他的操作,则异步处理)。  
      • 本来整个请求需要用 950ms (同步)  
      • 现在将调用其他系统接口异步化,只需要 100ms (异步)  
    • 2.3削峰/限流

      • 我们再来一个场景,现在我们每个月要搞一次大促,大促期间的并发可能会很高的,比如每秒 3000 个请求。假设我们现在有两台机器处理请求,并且每台机器只能每次处理 1000 个请求。 

      • 那多出来的 1000 个请求,可能就把我们整个系统给搞崩了...所以,有一种办法,我们可以写到消息队列中:  

      • 系统 B 和系统 C 根据自己的能够处理的请求数去消息队列中拿数据,这样即便有每秒有 8000 个请求,那只是把请求放在消息队列中,去拿消息队列的消息由系统自己去控制,这样就不会把整个系统给搞崩。  
    • 3.1 数据丢失问题
      • 我们将数据写到消息队列上,系统 B 和 C 还没来得及取消息队列的数据,就挂掉了。如果没有做任何的措施,我们的数据就丢了。 
      • 学过 Redis 的都知道,Redis可以将数据持久化磁盘上,万一 Redis 挂了,还能从磁盘从将数据恢复过来。  

    • 3.2 消费者怎么得到消息队列的数据?
      • 消费者怎么从消息队列里边得到数据?有两种办法:
        • 生产者将数据放到消息队列中,消息队列有数据了,主动叫消费者去拿(俗称push)
        • 消费者不断去轮训消息队列,看看有没有新的数据,如果有就消费(俗称pull)
    展开全文
  • 本文将会介绍什么是消息队列,为什么会用到消息队列,以及用消息队列会产生哪些问题,可以怎样解决等等。也看了很多文章,写的都很好,好记性不如烂笔头,所以自己也归纳总结一下,从而加深理解,欢迎大家一起学习...

    前言

    本文将会介绍什么是消息队列,为什么会用到消息队列,以及用消息队列会产生哪些问题,可以怎样解决等等。也看了很多文章,写的都很好,好记性不如烂笔头,所以自己也归纳总结一下,从而加深理解,欢迎大家一起学习探讨。

    介绍

    一、什么是消息队列?(MQ)

    消息队列我们一般会简称它为MQ(Message Queue),队列(Queue)这个词大家都不陌生,类似于火车站排队进站,先排队的人先进站,这是一种典型的“先进先出,后进后出”的例子。所以其实消息队列就是基础数据结构中“先进先出”的一种数据结构,下图更好的解释了这一概念。
    在这里插入图片描述
    在这里插入图片描述

    上图可见,消息队列的基本架构很简单;有称为生产者的客户端应用程序可以创建消息并将其传递到消息队列。另一个称为使用者的应用程序连接到队列并获取要处理的消息。存储在队列中的消息将被存储,直到消费者检索到它们为止。

    消息队列提供异步通信协议,该协议是一种将消息放入消息队列并且不需要立即响应来继续处理的系统。电子邮件可能是异步通信的最佳示例。发送电子邮件后,发件人将继续处理其他事情,而无需接收者的立即响应。这种处理消息的方式使生产者与使用者脱钩,从而使他们不需要同时与消息队列进行交互。

    二、为什么会用到消息队列?

    那么为什么会用到消息队列呢,消息队列解决了什么问题,有什么好处呢,其实消息队列一直存在,随着微服务架构的流行,成为了解决微服务之间问题的常用工具,下面介绍一下消息队列所带来的一些好处。

    1、应用解耦合

    举例来讲,有这样一个应用场景。A系统需要通过调用B、C、D系统的接口来将数据发送到BCD,这时就需要A系统来编写发送到BCD的代码。那么如果突然多了一个E系统也需要A的数据怎么办,这时就需要A系统修改代码,将数据同时发送到BCDE中去。但是如果这时D系统不需要接受这个数据怎么办,就再次需要A来修改代码。如此反复,对于系统的可维护性极其不利,耦合性非常高。
    在这里插入图片描述
    在这个场景中,A 系统跟其它各种乱七八糟的系统严重耦合,A 系统产生一条比较关键的数据,很多系统都需要 A 系统将这个数据发送过来。A 系统要时时刻刻考虑 BCDE 四个系统如果挂了该咋办?要不要重发,要不要把消息存起来?

    如果使用 消息队列(MQ),A 系统产生一条数据,发送到 MQ 里面去,哪个系统需要数据自己去 MQ 里面消费。如果新系统需要数据,直接从 MQ 里消费即可;如果某个系统不需要这条数据了,就取消对 MQ 消息的消费即可。这样下来,A 系统压根儿不需要去考虑要给谁发送数据,不需要维护这个代码,也不需要考虑人家是否调用成功、失败超时等情况。
    在这里插入图片描述
    上述场景可以看出,当一个系统或者一个模块调用多个系统或者模块的时候,互相之间调用起来很复杂,需要考虑的问题很多,维护起来很麻烦,所以其实并不需要同步进行接口调用,使用消息队列给它异步解耦,则好处很多。

    2、异步

    以系统注册用户为例,正常情况下,注册用户信息需要查询数据库需要50ms,然后向用户发送邮件需要50ms,然后再向用户发送短息通知获取验证码又需要50ms,共计需要150ms,我们可以发现这些都是同步进行的,比较时间。
    如果采用mq之后,注册用户信息需要查询数据库需要50ms,然后其他操作写入到消息队列中,消息队列异步执行邮件以及短信服务,可能只需要20ms,这时共计需要70ms则可以完成任务,大大的缩短了任务的执行时间。
    在这里插入图片描述

    3、流量削峰

    举个例子,如果一个订单系统,每秒钟可以处理一万次下单,在平时正常的时候该系统可以应付正常的请求,正常时段我们下单之后就会收到结果。但是如果突然遇到高峰期,有十万次下单操作给到订单系统中,这时由于超出处理范围则会造成系统崩溃,如下图一所示。
    这时我们可以用到消息队列来做缓冲,将其流量削峰,将一秒内十万次下单存到消息队列中,然后订单系统每秒只拉取一万下单来做处理,将其他订单先积压在消息队列中,等高峰期过去后,系统就会慢慢把订单都处理完,如下图二所示。
    在这里插入图片描述
    在这里插入图片描述

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

    1、高可用问题

    无论是我们使用消息队列来做解耦、异步还是削峰,消息队列肯定不能是单机的。试着想一下,如果是单机的消息队列,万一这台机器挂了,那我们整个系统几乎就是不可用了。以下图为例
    在这里插入图片描述
    所以一点MQ挂掉了,则整个系统都崩溃了,所以消息队列一定是集群的分布式的。

    2、数据丢失问题

    我们将数据写到消息队列上,其他系统没来得及取消息队列的数据,就挂掉了。如果没有做任何的措施,我们的数据就丢了,还是以订单系统为例。
    在这里插入图片描述

    3、其他问题

    除了上述问题我们是用的时候还会考虑各种问题
    · 消息重复消费了怎么办?
    · 消息如何保证有序?
    · 系统的复杂性,消息的一致性等

    总结

    虽然消息队列给我们带来了那么多的好处,但同时我们发现引入消息队列也会提高系统的复杂性。市面上现在已经有不少消息队列轮子了,每种消息队列都有自己的特点,选取哪种MQ还得好好斟酌。
    所以消息队列实际是一种非常复杂的架构,你引入它有很多好处,但是也得针对它带来的坏处做各种额外的技术方案和架构来规避掉,做好之后,你会发现,妈呀,系统复杂度提升了一个数量级,也许是复杂了 10 倍。但是关键时刻,用,还是得用的。

    展开全文
  • 一、什么是消息队列? 消息队列,一般我们会简称它为MQ(Message Queue),它本质就是一个消息转发器,一个不赚差价的“中间商”。 先说一下队列,应该都很熟悉,队列 = 一种按顺序排好队的数据结构。 把数据放...

    一、什么是消息队列?

    消息队列,一般我们会简称它为MQ(Message Queue),它本质就是一个消息转发器,一个不赚差价的“中间商”。

    先说一下队列,应该都很熟悉,队列 = 一种按顺序排好队的数据结构。

    • 把数据放到消息队列叫做“生产者”
    • 从消息队列里边取数据叫做“消费者”

    二、为什么要用消息队列?

    主要解决了三个问题

    1. 异步
    2. 解耦
    3. 削峰

    1.首先异步,在我们平常接口和方法调用的时候,需要一个一个按顺序调用,那对于一个重要的业务功能来说,可能调用的链路特别长...

    链路长了就慢了...

    其实有些流程我们可以同时执行,我去执行保存支付明细的同时也可以执行保存会员卡积分信息,然后加个会员等级,加个业绩什么的,是吧。

    正常的流程我们似乎没办法同时执行,怎么办?异步

    收银后把结果推送到消息队列中,下游其它服务订阅这个消息,收到消息执行加积分,加等级,加业绩...

    2.解耦,像下图中收银订单流程,业绩、库存、欠款...这么多业务,每增加一个都需要改动代码,而且其中只要有一个出现报错,其它流程就无法正常流转,那使用体验是不是很差?

    而且排查问题的时候,一个方法调用一个方法,都得找到自闭好么。

    用了消息队列耦合问题迎刃而解。

    3.削峰,我们都知道,服务器有容纳请求的一个上限,redis、mysql,各自的容忍度不同,那如果全部一起接收,那肯定会把服务器打挂。

    redis能来十万,mysql两千就GG...

    咋办?把请求内容丢消息队列中呗,每次消费1000条,慢慢的保存到数据库中,这样,系统就能平稳的抗住了短时间的高峰请求!

    三、用消息队列会产生什么问题?

    消息队列是用爽了,那问题也随之而来,我们都知道,技术是把双刃剑,解决问题的同时也会产生很多问题,那我们攻城狮这个岗位就是解决问题的。所以,遇到问题不要方,一个个解决。

    可能会出现哪些问题呢?

    1. 消息丢失
    2. 重复消费
    3. 消息积压

    1.消息丢失有很多情况:

    怎么解决?

    2.同一条消息重复消费,可能导致很多问题产生,比如加积分,100加了十次...,扣款扣了十次...

    我们可以给消息加上唯一的编号,消费的时候进行判断,如果用了就剔除这条消息,没用就继续使用!

    3.消息发出去了,消费者挂了,mq队列中积压了大量的数据,怎么办?

    其实除了以上问题,可能还会出现很多问题。

    数据一致性(这么多个系统,如果某个系统出问题,其它系统数据也得回滚,分布式事务)

    可用性(系统本身可能没有问题,MQ挂了,积分不加了,扣款不扣了?祭天吧)

    ...

     

    展开全文
  • MQ消息队列学习之什么是消息队列,为什么使用消息队列,各MQ的对比 什么是消息队列: 消息队列,一般我们会简称它为MQ(Message Queue)。就是将消息放到队列中。 队列是一种先进先出的接口。 将消息放到队列中...
  • 什么是消息队列

    2019-05-29 10:11:41
    一、什么是消息队列? 二、为什么要用消息队列? 2.1 解耦 2.2 异步 2.3 削峰/限流 三、使用消息队列有什么问题? 3.1 高可用 3.2 数据丢失问题 3.3 消费者怎么得到消息队列的数据? 3.4 其他 最后 一、...
  • 1、什么是消息队列   消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。消息队列是消息的链接表,存放在内核中并由消息队列标识符标识。 每个数据块都被认为含有一个类型,接收进程可以独立地接收...
  • 什么是消息队列及消息队列原理和应用场景详解 转载 ...
  • [MQ]什么是消息队列?

    千次阅读 多人点赞 2019-06-22 22:18:58
    什么是消息队列MQ(Message Queue)? 消息(Message):传输的数据。 队列(Queue):队列是一种先进先出的数据结构。 消息队列从字面的含义来看就是一个存放消息的容器。 消息队列可以简单理解为:把要传输的数据...
  • 什么是消息队列啊?

    2020-07-03 14:42:49
    今天我们来聊一聊什么是消息队列,为什么要用消息队列,有什么好处呢?同样使用消息队列有什么坏处? 我们的项目要引入消息队列了,之前只是听说使用消息队列有什么什么好处,感觉挺高大上的,自己也只是看过各种...
  • 到底什么是消息队列

    2020-04-01 15:11:50
    一、什么是消息队列 消息(Message)是指在应用之间传送的数据,消息可以非常简单,比如只包含文本字符串,也可以更复杂,可能包含嵌入对象。 消息队列(Message Queue)是一种应用间的通信方式,消息发送后可以立即...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 9,192
精华内容 3,676
关键字:

什么是消息队列