日志

面试官:说出八种消息队列的应用场景。啊?八种?

 来源    2020-05-23    1  

本文来源于公众号:胖滚猪学编程。转载请注明出处!

一个风度翩翩,穿着格子衬衣的中年男子,拿着一个满是划痕的mac向她走来,看着铮亮的头,胖滚猪心想,这肯定是尼玛顶级架构师吧!完了要挂了。

结果面试官第一个问题,就让胖滚猪内心暗喜

面试官:消息队列这东西,你还熟悉吧?消息队列在企业中的应用场景有哪些?

(这么基础的问题,手到擒来好吗?原来阿里不过如此。)

胖滚猪:嗯嗯,还挺熟悉的,可以用于流量削峰、应用解耦、异步处理。

面试官:就这三种吗?能不能再多说几个应用。起码八种吧。

(胖滚猪火冒三丈,尼玛八种哪来的?玩我呢?但是出于礼貌,还是毕恭毕敬的回答面试官)

胖滚猪:额。。有这么多吗?不好意思,一时之间想不起来了呢。

面试官:哎。。大家都知道的我们不屑,就想听听不一样的。回家去吧

胖滚猪内心挫败,平时五毛钱都舍不得花的抠猪,豪掷100大洋打了飞车来到导师胖滚熊家里求助。

胖滚熊:我先给你归纳了消息队列八种场景,如图所示,接下来我们再仔细说说每种场景的应用方案。

首先还是要介绍一下流量削峰、应用解耦、异步处理的具体应用,虽然网上文章到处都有,不过毕竟它们是老大,老大不出场小二也不敢乱动。如果你很熟悉了,可以直接跳过!

应用解耦:

某电商系统架构如图,用户下单之后首先进入订单系统,之后订单系统又将订单信息发送给物流系统和短信系统:

码农胖滚猪很快就写完了相关代码:

OrderInfo orderInfo = new OrderInfo();
        //省略组装订单信息
        sendToMessage(orderInfo);//发送给短信系统
        sendToLogistics(orderInfo);//发送给物流系统

一切就这么平安无事过了大半月,领导又要搞啥实时大屏,实时展示当天订单量,于是订单系统又要将订单信息发送给实时大屏系统

也没关系,码农胖滚猪又改了订单系统的代码,重新上线:

OrderInfo orderInfo = new OrderInfo();
        //省略组装订单信息
        sendToMessage(orderInfo);//发送给短信系统
        sendToLogistics(orderInfo);//发送给物流系统
        sendToRealTimeSys();//发送给实时分析系统

随着公司业务的壮大,订单信息又要发送给监控系统、数据挖掘系统。。。这会胖滚猪不淡定了“到底何时是个头呀!”

不仅如此,一旦下游某个系统异常,直接导致订单系统也异常了,时常收到顾客的投诉 “你们这电商系统!不用了!”

嗨,胖滚猪,早知如此何必当初呢?在1.0版本你就不应该让系统之间相耦合呀!如图:

订单系统只管将订单信息发到消息队列中,其他系统都从消息队列中拿数据。这样一来:

1、订单系统再也不用关心谁要用了,即使增加、减少下游系统或是下游系统需求如何变化,订单服务都无需做任何更改,实现了订单服务与下游服务的解耦!可以一个人自由飞翔了~
2、其他系统即便挂了或者请求超时,都跟订单系统无关,只跟消息队列有关。

哇,这样真是太爽了!和花钱一样爽!

异步处理

最近胖滚猪负责的用户系统一直被投诉,原因是太慢了!点击确认注册之后要1s才返回结果。你看看人家阿里的系统,点击注册10ms就可以返回结果了!

可是胖滚猪表示很无能为力,注册之后要写数据库、要发短信、还要发邮件,你让我怎么快呢?阿里的机器比我们好,才比我们快的!

嗨,胖滚猪,你可别把锅甩给机器啊,明明是你自己的设计缺陷呐,看我给你改改:

这样是不是觉得清爽了很多呢??

注册是主要的业务,而发短信和邮件通知用户已经注册成功是非主要的业务,甚至无关紧要,何必让无关的东西影响主要的东西呢?
假设三个业务节点每个使用100ms,不考虑网络等其他开销,则串行方式的时间是300ms,并行的时间可能是150ms。
透心凉心飞扬,这回省了不少时间,可以用来撩妹了。

流量削峰

胖滚猪在公司平安无事的呆了大半年,睡觉从没被电话骚扰,直到2020.5.20这天,xx明星po出结婚照,瞬间几千万的流量,撑爆了微博,而明星同款520T恤的热卖,也瞬间压垮了胖滚猪的电商系统。

胖滚猪好吃好喝大半年,没想到好日子还是终结了,半夜爬起来处理服务器故障,第二天无精打采的,太难受了。。

嗨,胖滚猪,早知如此,当初就应该考虑仔细呀!一个电商系统,秒杀场景是迟早会出现的!

上下游对于事情的处理能力是不同的。比如,Web前端每秒承受上千万的请求,并不是什么神奇的事情。但数据库的处理能力却十分有限,即使使用SSD加分库分表,单机的处理能力仍然在万级。由于成本的考虑,我们不能奢求数据库的机器数量追上前端。所以,利用中间系统转储两个系统的通信内容,并在下游系统有能力处理这些消息的时候,再处理这些消息,是一套相对较通用的方式。

我们需要设计一套足够健壮的架构来将后端的服务保护起来。设计思路是,使用消息队列隔离网关和后端服务,以达到流量控制和保护后端服务的目的。

我再给你画张图吧:

这样一来,用户的请求,服务器接收后,首先写入消息队列。假如消息队列长度超过最大数量,则直接抛弃用户请求或跳转到错误页面。而业务系统根据消息队列中的请求信息,再做后续处理。

这种设计的优点是:能根据下游的处理能力自动调节流量,达到“削峰填谷”的作用

任务依赖

胖滚猪的公司有了高大上的数据中台,其中一个子系统叫做数据同步,只需要在前端页面勾选表,就可以自助化完成mysql到hive的同步。

但其中有个节点是工单审核。在同步系统中发起表同步申请,首先会调用工单系统,领导层在工单系统审核成功后,同步系统才可以完成接下来的同步任务。最开始,胖滚猪是这么设计的:

同步系统启了一个定时任务,每五分钟去查一下工单系统的接口,拿到审核结果。这种做法完全可行。

可是业务人员小甲不干了,小甲是个急性子,他觉得太慢了!提个需求:必须要准实时!即领导审核成功后你要马上给我同步!

这时候,胖滚猪又想到了消息队列,灵机一动,有了2.0优化版本:

这下,小甲这种急性子也不用不耐烦了,只要领导一批准,马上同步系统就会开始工作!

广播

胖滚猪加入产品中心的第一天,就给了它一个任务:产品中心需要频繁发布产品变更,而关心产品的系统多达10来个。每次变更,都要联调一次新接口,实在是太!麻!烦!了!

胖滚猪分析了一下,这就好像你妈喊你吃饭、还要喊你爸吃饭、喊你爷吃饭,她需要单独给你们每个人发微信通知,有点麻烦。可是如果她直接在家族群@你们,就把消息广播给大家了!

同理,产品系统相当于也要实现一个广播的功能,产品变动之后需要广播给其他系统。有了之前的经验,很快想到了可以用消息队列来实现。

在这里,消息队列就像我们的微信群一样,有了消息队列,我们只需要关心消息是否送达了队列,至于谁关心它谁希望去订阅,是下游的事情,无疑极大地减少了开发和联调的工作量。

数据采集

胖滚猪又接了个数据采集的活,1、需要实时收集日志、2、需要实时采集业务库binlog。

经过一番调研,胖滚猪明白了,采集binlog一般用到canal、采集日志一般可以用Flume和Logstash。

那么采集之后数据丢到哪儿呢?胖滚猪看了看官方架构图,咦,又有熟悉的消息队列,原来消息队列也可以用来数据采集呀!

所有主流的采集工具,都支持落地到Kafka等消息队列。也就是说,消息队列在数据采集这一块,也有举足轻重的作用。当然了,也不是必须要选择消息队列,要根据具体场景来选择。如果要对接流计算任务,或者多个系统都需要用到采集到的数据,那么选消息队列就没错了;如果只是想单纯存储起来,比如一些日志,那么可以不用消息队列。

连接流计算任务和数据

用消息队列(主要指Kafka)来连接流计算任务和数据,这在大数据领域是非常通用的一个架构了。火爆的流计算框架,Flink和Spark都优先选择Kafka作为数据源头并提供了完美的支持。

我们看一下oppo的架构图、简直了。三次用到Kafka!这地位无敌了!为啥oppo要三次用到Kafka呢?我相信根据上面的应用场景和优势你完全可以自行分析出来!

消息通讯

最后说一下消息通讯。。消息队列可以应用在消息通讯中,比如聊天室。

你可能会吐槽,你这不废话吗?凑数呢?我当然知道消息队列可用于消息通讯,小学生看名字都知道!

额,其实我只是想说明一下消息队列在消息通讯的两种场景罢了:点对点模型和发布订阅模型。

点对点通讯:系统 A 发送的消息只能被系统 B 接收,其他任何系统都不能读取 A 发送的消息。日常生活的例子比如电话客服就属于这种模型:同一个客户呼入电话只能被一位客服人员处理,第二个客服人员不能为该客户服务。

发布 / 订阅模型:与上面不同的是,它有一个主题(Topic)的概念,这个模型可能存在多个发布者向相同的主题发送消息,而订阅者也可能存在多个,它们都能接收到相同主题的消息。生活中的报纸订阅就是一种典型的发布 / 订阅模型。

劲酒虽好,可不要贪杯哦

消息队列确实有着非常广泛的应用,但它也有缺点!劲酒虽好,可不要贪杯哦,贪杯会出问题的哦!

  • 消息队列会带来一定的延迟问题;
  • 降低了数据的一致性;如果要保证强一致性则需要高代价的补偿,如分布式事务、对账。
  • 有数据丢失的风险;比如宕机重启,如果要保证高可用需要额外的机制如双活容灾。

因此:

  • 不适合要求实时响应的系统、
  • 不适合要求数据强一致性的系统(比如直接和钱有关系的系统 银行转账 第三方支付)、
  • 不适合不能容忍数据丢失的系统

本文来源于公众号:胖滚猪学编程。一枚集颜值与才华于一身的女程序媛。用漫画形式让编程so easy and interesting!求关注!
本文来源于公众号【胖滚猪学编程】一个集颜值与才华于一身的女程序媛。以漫画形式让编程so easy and interesting。

相关文章
RabbitMQ五种消息队列学习(三)–Work模式
日志由于在实际应用中,简单队列模型无法解决很多实际问题,而且生产者和消费者是一对一的关系.模型较为单一.故引入Work模式. 结构图 一个生产者.多个消费者. 一个消息只能被一个消费者获取. 测试实现:  ...
1
Rabbit五种消息队列学习(二) – 简单队列
日志队列结构图 P:消息的生产者 C:消息的消费者 红色:队列 生产者将消息发送到队列,消费者从队列中获取消息. 测试 1.连接MQ public static Connection getConnect ...
1
AMQP协议详解与RabbitMQ,MQ消息队列的应用场景,如何避免消息丢失等消息队列常见问题
日志什么是AMQP? 在异步通讯中,消息不会立刻到达接收方,而是被存放到一个容器中,当满足一定的条件之后,消息会被容器发送给接收方,这个容器即消息队列,而完成这个功能需要双方和容器以及其中的各个组件遵守统 ...
1
消息队列的应用场景总结
日志一.消息队列的应用场景 引入一个故事:该故事转载于:(https://www.zhihu.com/people/qi-da-fang/answers 祁达方的回答) 小红是小明的姐姐. 小红希望小明多 ...
1
storyboard三种sugue 和 跳转场景的三种方式 以及控制器之间的传值
日志Storyboard引入了2个概念:1. scene:一个场景,由一个viewController和相关的xib表示. 2. segue:在这是用于连接scenes,其有多种类型,iphone包括:P ...
[.NET领域驱动设计实战系列]专题八:DDD案例:网上书店分布式消息队列和分布式缓存的实现
日志一.引言   在上一专题中,商家发货和用户确认收货功能引入了消息队列来实现的,引入消息队列的好处可以保证消息的顺序处理,并且具有良好的可扩展性.但是上一专题消息队列是基于内存中队列对象来实现,这样实现 ...
(八)RabbitMQ消息队列-通过Topic主题模式分发消息
日志原文:(八)RabbitMQ消息队列-通过Topic主题模式分发消息 前两章我们讲了RabbitMQ的direct模式和fanout模式,本章介绍topic主题模式的应用.如果对direct模式下通过 ...
1
分布式消息队列,两种常规方案
日志官网 官方文档 文档 文档 Kafka Kafka是由Linkedin开发的一个分布式的消息队列系统(Message Queue) kafka开发的主要初衷目标是构建一个用来处理海量日志,用户行为和网 ...
1
RabbitMQ消息队列(八)-通过Topic主题模式分发消息(.Net Core版)
日志前两章我们讲了RabbitMQ的direct模式和fanout模式,本章介绍topic主题模式的应用.如果对direct模式下通过routingkey来匹配消息的模式已经有一定了解那fanout也很好 ...
ActiveMQ 持久化消息队列的三种方式
日志1.ActiveMQ消息持久化方式,分别是:文件.mysql数据库.oracle数据库 2.修改方式: a.文件持久化: ActiveMQ默认的消息保存方式,一般如果没有修改过其他持久化方式的话可以不 ...
1
Spring Boot 之 RabbitMQ 消息队列中间件的三种模式
日志开门见山(文末附有消息队列的几个基本概念) 1.直接模式( Direct)模式  直白的说就是一对一,生产者对应唯一的消费者(当然同一个消费者可以开启多个服务). 虽然使用了自带的交换器(Exchan ...
1
八.利用springAMQP实现异步消息队列的日志管理
日志经过前段时间的学习和铺垫,已经对spring amqp有了大概的了解.俗话说学以致用,今天就利用springAMQP来完成一个日志管理模块.大概的需求是这样的:系统中有很多地方需要记录操作日志,比如登 ...
程序猿面试宝典(第三版)--队列的建立,測长,打印,入队,出队
日志编程实现队列的建立,測长,打印,入队,出队. #include<iostream> #include<stdio.h> #include<string.h> #in ...
1
[程序员代码面试指南]第9章-一种消息接收并打印的结构(链表)
日志题意 数据流读入数字(保证>=1),i最初=0,当i+1出现时,输出i+1及其后连续的输入过的数字,否则什么也不输出. 例子: 输入:1 输出:1 输入:3 输出: 输入:4 输出: 输入:6 ...
1
一起talk C栗子吧(第九十八回:C语言实例--使用消息队列进行进程间通信二)
日志各位看官们,大家好,上一回中咱们说的是使用消息队列进行进程间通信的样例.这一回咱们接着上一回的内容继续说使用消息队列进行进程间通信.闲话休提.言归正转.让我们一起talk C栗子吧! 我们在上一回中介 ...
skynet源代码学习 - 从全局队列中弹出/压入一个消息队列过程
日志学习云风的skynet源代码,简单记录下. void skynet_globalmq_push(struct message_queue * queue) { struct global_queue ...
amazon-ec2 – 是否有提供Amazon SQS高可用性的FIFO消息队列服务?
问答如果它提供了一些类似于FIFO访问的东西,那么它会喜欢使用Amazon SQS,但是这个序列似乎完全是随机的. 有没有什么可以为我提供FIFO排队作为云服务与SQS的高可用性? 如果这是要求太多 – ...
1
无法创建从独立Java应用程序到JBoss AS 7消息队列的JMS连接
问答我已经使用standalone-full.xml作为配置文件配置了在JBoss AS 7.1.1.FINAL上运行的JMS队列. 然后我编写了一个独立的Java程序来连接队列并根据JBoss示例代码发 ...
1
如果在使用消息后有任何错误,如何在JMS消息队列中保存消息?
问答我的方案是 – 我将消息发送到队列,一旦消息被消耗,我将它发送到第三方中间件应用程序.如果该中间件应用程序已关闭,那么我发布的消息就会被删除.如果中间件应用程序关闭而我希望它处于保持状态或在队列中等待 ...
1
基于redis的延迟(优先级)消息队列 – 流程图
问答将Redis的ZSET作为优先队列,用list作为待消费列表,根据路由规则,一个可配置的消息队列,模拟rabbitmq的延迟消费::
1