第十二期:面试官问你什么是消息队列?把这篇甩给他!

消息队列不知道大家看到这个词的时候,会不会觉得它是一个比较高端的技术,反正我是觉得它好像是挺牛逼的。

 

面试官问你什么是消息队列?把这篇甩给他!

一、什么是消息队列?

消息队列不知道大家看到这个词的时候,会不会觉得它是一个比较高端的技术,反正我是觉得它好像是挺牛逼的。

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

我们先不管消息(Message)这个词,来看看队列(Queue)。这一看,队列大家应该都熟悉吧。

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

在Java里边,已经实现了不少的队列了:

那为什么还需要消息队列(MQ)这种中间件呢???

  •  到这里,大家可以先猜猜为什么要用消息队列(MQ)这种中间件,下面会继续补充。

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

 

科普:

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

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

为什么要用消息队列,也就是在问:用了消息队列有什么好处。我们看看以下的场景

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);  }  
} 

结构图如下:

ok,一切平安无事度过了几个天。

某一天,系统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个请求,那只是把请求放在消息队列中,去拿消息队列的消息由系统自己去控制,这样就不会把整个系统给搞崩。

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

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

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

3.1高可用

无论是我们使用消息队列来做解耦、异步还是削峰,消息队列肯定不能是单机的。试着想一下,如果是单机的消息队列,万一这台机器挂了,那我们整个系统几乎就是不可用了。

所以,当我们项目中使用消息队列,都是得集群/分布式的。要做集群/分布式就必然希望该消息队列能够提供现成的支持,而不是自己写代码手动去实现。

3.2 数据丢失问题

我们将数据写到消息队列上,系统B和C还没来得及取消息队列的数据,就挂掉了。如果没有做任何的措施,我们的数据就丢了。

学过Redis的都知道,Redis可以将数据持久化磁盘上,万一Redis挂了,还能从磁盘从将数据恢复过来。同样地,消息队列中的数据也需要存在别的地方,这样才尽可能减少数据的丢失。

那存在哪呢?

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

同步存储还是异步存储?

3.3消费者怎么得到消息队列的数据?

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

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

3.4其他

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

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

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

***

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


阅读目录(置顶)(长期更新计算机领域知识)https://blog.csdn.net/weixin_43392489/article/details/102380691

阅读目录(置顶)(长期更新计算机领域知识)https://blog.csdn.net/weixin_43392489/article/details/102380882

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/424993.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第三章 随机变量的数字特征

数学期望 数学期望用来反映平均情况。 定义 设离散型随机变量X的分布律为P(Xxk)pk,k1,2,3...,若级数∑∞k1xkpk是收敛的,则称级数∑∞k1xkpk的值为随机变量X的数学期望。记为E(X)。E(X)∑k1∞xkpkpk可以理解为加权平均中的权值。数学期望又称为 均值。 …

python二进制、字符编码及文件操作

1. 二进制 bin()十进制转二进制 0b oct()十进制转八进制 0o hex()十进制转十六进制 0x,4个二进制对应1个16进制,用于网络编程,数据存储 print(int(110111,2)) 55 print(int(ffff,16)) 65535 p…

【数据结构与算法】【字符串匹配】Trie树

单模式串匹配 BF 算法和 RK 算法 BM 算法和 KMP 算法多模式串匹配算法 Trie 树和 AC 自动机 一、 什么是“Trie树”? 1. 他是一种树形结构,是一种专门处理字符串匹配的数据结构,解决在一组字符串集合中快速查找某个字符串的问题。 2. Trie…

第十三期:消灭 Java 代码的“坏味道”

代码中的"坏味道",如"私欲"如"灰尘",每天都在增加,一日不去清除,便会越累越多。如果用功去清除这些"坏味道",不仅能提高自己的编码水平,也能使代码变得"精白…

[Leetcode][第100题][JAVA][相同的树][二叉树][深度遍历][递归]

【问题描述】[中等] 【解答思路】 深度遍历/递归 终止条件与返回值: 当两棵树的当前节点都为 null 时返回 true 当其中一个为 null 另一个不为 null 时返回 false 当两个都不为空但是值不相等时,返回 false 执行过程:当满足终止条件时进…

第十四期:5 个 JS 不良编码习惯,你占几个呢?

在阅读JavaScript代码时,你是否有过这种感觉:你几乎不明白代码的作用?代码使用了很多 JavaScript 技巧?命名和编码风格太过随意? 这些都是不良编码习惯的征兆。 在阅读JavaScript代码时,你是否有过这种感觉…

第十五期:详解Java集合框架,让你全面掌握!

一、Java集合框架概述 集合可以看作是一种容器,用来存储对象信息。所有集合类都位于java.util包下,但支持多线程的集合类位于java.util.concurrent包下。 数组与集合的区别如下: 1)数组长度不可变化而且无法保存具有映射关系的…

[Leetcode][第98 450 700 701题][JAVA][二叉搜索树的合法性、增、删、查][递归][深度遍历]

【二叉搜索树定义】(BST) 二叉搜索树(Binary Search Tree,简称 BST)是一种很常用的的二叉树。它的定义是:一个二叉树中,任意节点的值要大于等于左子树所有节点的值,且要小于等于右边…

关于CNN的权重共享,CNN到底学到了什么?

CNN的fliter里的每个值都是学习出来的不是事先设定好的。 经过fliter处理后得到是特征图(feature map) 卷积减少权重参数的本质: 权重共享,不同的fliter会在某些神经元上权重共享。 到底fliter,到底CNN学到了什么? 底层的flite…

复盘二进制的习题(1)

本文是对近期二进制专题的leetcde习题的复盘。文中的解决思路来源于leetcode的讨论,以及一些网页。 342 判断一个整数(32bits)是否是4的次幂。  写出4i,i0,1,2,3,4...的二进制表示,查找规律。会发现这些数的特征是 a 都>0;b 只有一位是…

第十六期:简单的介绍一下大数据中最重要的MapReduce

MapReduce是分布式运行的,由两个阶段组成:Map和Reduce,Map阶段是一个独立的程序,有很多个节点同时运行,每个节点处理一部分数据。 MapReduce执行流程图 概述 MapReduce是一种分布式计算模型,由Google提出…

【数据结构与算法】快排、归并 O(nlogn) 基于比较

冒泡、插入、选择 O(n^2) 基于比较 快排、归并 O(nlogn) 基于比较 计数、基数、桶 O(n) 不基于比较 一、分治思想 1.分治思想:分治,顾明思意,就是分而治之,将一个大问题分解成小的子问题来解决,小的子问题解决了&…

第四章切比雪夫不等式、大数定理、中心极限定理

切比雪夫不等式 设随机变量X具有数学期望E(X)μ&#xff0c;方差D(X)σ2&#xff0c;对于任意ε>0&#xff0c;都有P{|X−μ|≥ε}≤σ2ε2方差越大&#xff0c;X落在区间外的概率越大&#xff0c;X的波动也就越大&#xff0c;与方差的意义统一了。等价公式P{|X−μ|<ε}…

第十七期:记一次生产环境SQL Server服务器卡顿问题解决--内存分配不当

概述 最近有台数据库做了迁移&#xff0c;然后运维人员过了一段时间发现这台服务器非常卡&#xff0c;连远程登录都要很久&#xff0c;下面记录下其中的解决过程。 1、查看资源情况 可以发现内存爆满了&#xff0c;而排名第一的正是sqlserver的进程 2、查看sqlserver内存分配…

leetcode 42 接雨水 单调栈

接雨水 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图&#xff0c;在这种情况下&#xff0c;可以接 6 个单位的雨水&#xff08;蓝色部分表示雨水…

第十八期:网页禁止复制粘贴怎么办?教你六招轻松搞定

经常在网上遇到一些无法复制的文章&#xff0c;那么问题来了&#xff0c;有什么办法可以绕开这种限制&#xff0c;将网页内容轻松下载回来呢&#xff1f; 经常在网上遇到一些无法复制的文章&#xff0c;那么问题来了&#xff0c;有什么办法可以绕开这种限制&#xff0c;将网页内…

[Leetcode][第99题][JAVA][恢复二叉搜索树][中序遍历]

【问题描述】[困难] 【解答思路】 1. 显示中序遍历 时间复杂度&#xff1a;O(N) 空间复杂度&#xff1a;O(N) class Solution {public void recoverTree(TreeNode root) {List<Integer> nums new ArrayList<Integer>();inorder(root, nums);int[] swapped find…

第四十一期:深度解析5G核心网建设难点和挑战

目前核心网处于架构转型和业务转型的关键期。在架构层面&#xff0c;NFV、CU分离、边缘计算等技术的成熟推动核心网络架构转型&#xff0c;控制面进一步集中&#xff0c;转发面进一步下沉。 目前核心网处于架构转型和业务转型的关键期。在架构层面&#xff0c;NFV、CU分离、边缘…

[Leetcode][第696题][JAVA][计算二进制子串][分组]

【问题描述】[简单] 【解答思路】 1. 按字符分组 将字符串 ss 按照 00 和 11 的连续段分组&#xff0c;存在counts 数组中&#xff0c;例如 s 00111011&#xff0c;可以得到这样的counts 数组&#xff1a;counts{2,3,1,2}。 这里counts 数组中两个相邻的数一定代表的是两种…

Scrapy安装报错

python3 pip 安装Scrapy在win10 安装报错error: Microsoft Visual C 14.0 is required. Get it with "Microsoft Visual C Build Tools": http://landinghub.visualstudio.com/visual-cpp-build-tools 问题描述 当前环境win10&#xff0c;python_3.6.1&#xff0c;64…