别找了,Java面试还愁被问RabbitMQ?看完这22道问题解析就够了!

来分享一下面试必备的RabbitMQ问题解析!用XMind画了一张导图记录RabbitMQ的学习笔记和一些面试解析(源文件对部分节点有详细备注和参考资料,已经完善更新):

  1. 先修复consumer的问题,确保其恢复消费速度,然后将现有consumer都停掉;
  2. 新建⼀个topic,partition是原来的10倍,临时建⽴好原先10倍或者20倍的queue数量;
  3. 然后写⼀个临时的分发数据的consumer程序,这个程序部署上去消费积压的数据;消费之后不做耗时的处理,直接均匀轮询写⼊临时建⽴好的10倍数量的queue;
  4. 接着临时征⽤10倍的机器来部署consumer,每⼀批consumer消费⼀个临时queue的数据;
  5. 这种做法相当于是临时将queue资源和consumer资源扩⼤10倍,以正常的10倍速度来消费数据;
  6. 等快速消费完积压数据之后,得恢复原先部署架构,重新⽤原先的consumer机器来消费消息。

总结:

  1. 修复并停掉consumer;
  2. 新建⼀个topic,partition是原来的10倍,建⽴临时queue,数量是原来的10倍或20倍;
  3. 写临时consumer程序,临时征⽤10倍的机器去消费数据;
  4. 消费完成之后,恢复原先consumer;

采取批量重导⽅法:将丢失的那批数据查询导⼊到mq⾥⾯。

3、RabbitMQ 上的⼀个 queue 中存放的 message 是否有数量限制?

可以认为是⽆限制,因为限制取决于机器的内存,但是消息过多会导致处理效率的下降。

RabbitMQ⽆法容忍不同数据中⼼之间⽹络延迟,但是可以通过3种⽅式实现分布式部署:Federation和Shovel。

RabbitMQ使⽤发送⽅确认模式,确保消息正确地发送到RabbitMQ。

发送⽅确认模式:将信道设置成confirm模式(发送⽅确认模式),则所有在信道上发布的消息

都会被指派⼀个唯⼀的ID。⼀旦消息被投递到⽬的队列后,或者消息被写⼊磁盘后(可持久化

的消息),信道会发送⼀个确认给⽣产者(包含消息唯⼀ID)。如果RabbitMQ发⽣内部错误

从⽽导致消息丢失,会发送⼀条nack(not acknowledged,未确认)消息。

发送⽅确认模式是异步的,⽣产者应⽤程序在等待确认的同时,可以继续发送消息。当确认消息到达⽣产者应⽤程序,⽣产者应⽤程序的回调⽅法就会被触发来处理确认消息。

接收⽅消息确认机制:消费者接收每一条消息后都必须进行确认(消息接收和消息确认是两个不同操作)。只有消费者确认了消息,RabbitMQ才能安全地把消息从队列中删除。

这⾥并没有⽤到超时机制,RabbitMQ仅通过Consumer的连接中断来确认是否需要重新发送消息。也就是说,只要连接不中断,RabbitMQ给了Consumer⾜够⻓的时间来处理消息。

特殊情况:

  1. 如果消费者接收到消息,在确认之前断开了连接或取消订阅,RabbitMQ会认为消息没有被分发,然后重新分发给下一个订阅的消费者。(可能存在消息重复消费的隐患,需要根据bizId去重)
  2. 如果消费者接收到消息却没有确认消息,连接也未断开,则RabbitMQ认为该消费者繁忙,将不会给该消费者分发更多的消息。

在消息⽣产时,MQ内部针对每条⽣产者发送的消息⽣成⼀个inner-msg-id,作为去重和幂等的依据(消息投递失败并重传),避免重复的消息进⼊队列;在消息消费时,要求消息体中必须要有⼀个bizId(对于同⼀业务全局唯⼀,如⽀付ID、订单ID、帖⼦ID等)作为去重和幂等的依据,避免同⼀条消息被重复消费。

由于TCP连接的创建和销毁开销较⼤,且并发数受系统资源限制,会造成性能瓶颈。

RabbitMQ使⽤信道的⽅式来传输数据。信道是建⽴在真实的TCP连接内的虚拟连接,且每条

TCP连接上的信道数量没有限制。

  1. RabbitMQ采⽤类似NIO(Non-blocking I/O)做法,选择TCP连接复⽤,不仅可以减少性能开销,同时也便于管理。
  2. 每个线程把持⼀个信道,所以信道服⽤了Connection的TCP连接。同时RabbitMQ可以确保每个线程的私密性,就像拥有独立的连接一样。

若该队列⾄少有⼀个消费者订阅,消息将以循环(round-robin)的方式发送给消费者。每条消息只会分发给⼀个订阅的消费者(前提是消费者能够正常处理消息并进行确认)。

从概念上来说,消息路由必须有三部分:交换器、路由、绑定。⽣产者把消息发布到交换器上;绑定决定了消息如何从交换器路由到特定的队列;消息最终到达队列,并被消费者接收。

  1. 消息发布到交换器时,消息将拥有⼀个路由键(routing key),在消息创建时设定。
  2. 通过队列路由键,可以把队列绑定到交换器上。
  3. 消息到达交换器后,RabbitMQ会将消息的路由键与队列的路由键进行匹配(针对不同的交换器有不同的路由规则)。
  4. 如果能够匹配到队列,则消息会投递到相应队列中;如果不能匹配到任何队列,消息将进⼊ “⿊洞”。

消息持久化的前提是:将交换器/队列的durable属性设置为true,表示交换器/队列是持久交换器/队列,在服务器崩溃或重启之后不需要重新创建交换器/队列(交换器/队列会⾃动创建)。

如果消息想要从Rabbit崩溃中恢复,那么消息必须:

  1. 在消息发布前,通过把它的 “投递模式” 选项设置为2(持久)来把消息标记成持久化
  2. 将消息发送到持久交换器
  3. 消息到达持久队列

RabbitMQ确保持久性消息能从服务器重启中恢复的⽅式是,将它们写⼊磁盘上的⼀个持久化⽇志⽂件,当发布⼀条持久性消息到持久交换器上时,Rabbit会在消息提交到⽇志⽂件后才发送响应(如果消息路由到了⾮持久队列,它会⾃动从持久化⽇志中移除)。⼀旦消费者从持久队列中消费了⼀条持久化消息,RabbitMQ会在持久化⽇志中把这条消息标记为等待垃圾收集。如果持久化消息在被消费之前RabbitMQ重启,那么Rabbit会⾃动重建交换器和队列(以及绑定),并重播持久化⽇志⽂件中的消息到合适的队列或者交换器上。

  1. 应⽤解耦(系统拆分)
  2. 异步处理(预约挂号业务处理成功后,异步发送短信、推送消息、⽇志记录等,可以⼤⼤减⼩响应时间)
  3. 消息分发
  4. 流量削峰:将请求发送到队列中,短暂的⾼峰期积压是允许的。
  5. 消息缓冲
  1. 系统可⽤性降低:消息队列出问题影响业务;
  2. 系统复杂性增加:加⼊消息队列,需要考虑很多⽅⾯的问题,⽐如:⼀致性问题、如何保证消息不被重复消费、如何保证消息可靠性传输等。
  1. 中⼩型公司⾸选RabbitMQ:管理界⾯简单,⾼并发。
  2. ⼤型公司可以选择RocketMQ:更⾼并发,可对rocketmq进⾏定制化开发。
  3. ⽇志采集功能,⾸选kafka,专为⼤数据准备。

1. 集群:

  • 集群可以扩展消息通信的吞吐量,但是不会备份消息,备份消息要通过镜像队列的⽅式解决。
  • 队列存储在单个节点、交换器存储在所有节点。

2. 镜像队列:将需要消费的队列变为镜像队列,存在于多个节点,这样就可以实现RabbitMQ

的HA⾼可⽤性。作⽤就是消息实体会主动在镜像节点之间实现同步,⽽不是像普通模式那样,

在consumer消费数据时临时读取。缺点就是,集群内部的同步通讯会占⽤⼤量的⽹络带宽。

  1. 通过某种算法,将需要保持先后顺序的消息放到同⼀个消息队列中(kafka中就是partition,rabbitMq中就是queue)。然后只⽤⼀个消费者去消费该队列。
  2. 可以在消息体内添加全局有序标识来实现。
  • fanout交换器:它会把所有发送到该交换器的消息路由到所有与该交换器绑定的队列中;
  • direct交换器:direct类型的交换器路由规则很简单,它会把消息路由到哪些BindingKey和RoutingKey完全匹配的队列中;
  • topic交换器:匹配规则⽐direct更灵活。
  • headers交换器:根据发送消息内容的headers属性进⾏匹配(由于性能很差,不实⽤)

常⽤的交换器主要分为以下三种:

  • direct:如果路由键完全匹配,消息就被投递到相应的队列
  • fanout:如果交换器收到消息,将会⼴播到所有绑定的队列上
  • topic:可以使来⾃不同源头的消息能够到达同⼀个队列。 使⽤topic交换器时,可以使⽤通配符,⽐如:“*” 匹配特定位置的任意⽂本, “.” 把路由键分为了⼏部分,“#” 匹配所有规则等。特别注意:发往topic交换器的消息不能随意的设置选择键(routing_key),必须是由\”.\”隔开的⼀系列的标识符组成

19、RabbitMQ如何保证数据⼀致性?

  1. ⽣产者确认机制:消息持久化后异步回调通知⽣产者,保证消息已经发出去;
  2. 消息持久化:设置消息持久化;
  3. 消费者确认机制:消费者成功消费消息之后,⼿动确认,保证消息已经消费。

SimpleMessageListenerContainer可根据RabbitMQ消息堆积情况⾃动扩展消费者数量。

  • Broker:简单来说就是消息队列服务器实体。
  • Exchange:消息交换机,它指定消息按什么规则,路由到哪个队列。
  • Queue:消息队列载体,每个消息都会被投⼊到⼀个或多个队列。
  • Binding:绑定,它的作⽤就是把exchange和queue按照路由规则绑定起来。
  • Routing Key:路由关键字,exchange根据这个关键字进⾏消息投递。
  • vhost:虚拟主机,⼀个broker⾥可以开设多个vhost,⽤作不同⽤户的权限分离。
  • producer:消息⽣产者,就是投递消息的程序。
  • consumer:消息消费者,就是接受消息的程序。
  • channel:消息通道,在客户端的每个连接⾥,可建⽴多个channel,每个channel代表⼀个会话任务。
  1. ⼀个队列可以绑定多个消费者;
  2. 消息默认以循环的⽅式发送给消费者;
  3. 消费者收到消息默认⾃动确认,也可以改成⼿动确认。

彩蛋

2020年面试必备的Java后端进阶面试题总结了一些学习文档笔记和面试解析,共2000页,有需要的朋友麻烦转发后关注私信回复【面试】获取资料免费领取方式吧!

这份Java面试题含答案解析竟然真的让你不用在面试上“如履薄冰”

  1. 一、Core Java: 1 — 95 题1 — 24 页
  2. 基础及语法: 1 — 61 题1 — 13 页
  3. 异常: 62 — 69 题13 — 15 页
  4. 集合: 70 — 80 题15 — 18 页
  5. 线程: 81 — 90 题18 — 21 页
  6. IO & Socket: 91 — 95 题21 — 24 页
  7. 二、OOAD & UML: 96 — 101 题24 — 25 页
  8. 三、XML: 102 — 105 题26 — 29 页
  9. 四、SQL: 106 — 109 题29 — 31 页
  10. 五、JDBC & Hibernate: 110 — 121 题31 — 35 页
  11. 六、Web: 122 — 161 题35 — 44 页
  12. 七、EJB & Spring: 162 — 179 题44 — 47 页
  13. 八、数据结构& 算法& 计算机基础: 180 — 187 题47 — 51 页
  14. 九、C++: 188 — 201 题51 — 55 页
  15. 十、Weblogic 及其它(附加部分) 1 —— 13 题55 — 57 页
  16. 一、CoreJava 部分:(共95 题:基础91 道,中等难度4 道)
  17. 基础及语法部分:(共61 题:基础60 道、中等难度1 道)

答:面向对象的特征主要有以下几个方面:

1)抽象:抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节。抽象包括两个方面,一是过程抽象,二是数据抽象。

2)继承:继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。对象的一个新类可以从现有的类中派生,这个过程称为类继承。新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)。派生类可以从它的基类那里继承方法和实例变量,并且类可以修改或增加新的方法使之更适合特殊的需要。

3)封装:封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。

4)多态性:多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。

2、作用域public,private,protected,以及不写时的区别?【基础

3、String 是最基本的数据类型吗? 【基础】

4、float 型float f=3.4是否正确? 【基础】

5、语句float f=1.3;编译能否通过?【基础】

6、short s1 = 1; s1 = s1 + 1;有什么错?short s1 = 1; s1 += 1;有什么错? 【基础】

7、Java 有没有goto? 【基础】

8、int 和Integer 有什么区别? 【基础】

9、&和&&的区别?【基础】

10、简述逻辑操作(&,|,^)与条件操作(&&,||)的区别?【基础】

11、heap 和stack 有什么区别?【基础】

12、Math.round(11.5) 等于多少? Math.round(-11.5)等于多少? 【基础】

13、swtich 是否能作用在byte 上,是否能作用在long 上,是否能作用在String上? 【基础】

14、编程题: 用最有效率的方法算出2 乘以8 等於几? 【基础】

15、有没有length()这个方法? String 有没有length()这个方法?【基础】

16、在JAVA 中,如何跳出当前的多重嵌套循环?【基础】

17、构造器Constructor 是否可被override? 【基础】

18、两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对? 【基础】

19、是否可以继承String 类? 【基础】

20、以下二条语句返回值为true 的有

21、当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递? 【基础】

22、我们在web 应用开发过程中经常遇到输出某种编码的字符,如iso8859-1等,如何输出一个某种编码的字符串?【基础】

23、String 和StringBuffer 的区别? 【基础】

24、String, StringBuffer StringBuilder 的区别。【基础】

25、Overload 和Override 的区别。Overloaded 的方法是否可以改变返回值的类型? 【基础】

26、定义类A 和类B 如下:【基础】

27、描述一下JVM 加载class 文件的原理机制? 【基础】

28、char 型变量中能不能存贮一个中文汉字?为什么? 【基础】

29、abstract class 和interface 有什么区别? 【基础】

30、Static Nested Class 和Inner Class 的不同?【基础】

31、java 中会存在内存泄漏吗,请简单描述。【基础】

32、abstract 的method 是否可同时是static,是否可同时是native,是否可同时是synchronized? 【基础】

33、静态变量和实例变量的区别?【基础】

34、是否可以从一个static 方法内部发出对非static 方法的调用?【基础】

35、写clone()方法时,通常都有一行代码,是什么?【基础】

36、GC 是什么? 为什么要有GC? 【基础】

37、垃圾回收的优点和原理。并考虑2 种回收机制。【基础】

38、垃圾回收器的基本原理是什么?垃圾回收器可以马上回收内存吗?有什么办法主动通知虚拟机进行垃圾回收?【基础】

39、String s=new String(“xyz”);创建了几个String Object? 【基础】

40、接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承实体类(concrete class)? 【基础】

41、Java 的接口和C++的虚类的相同和不同处。【基础】

42、一个“.java”源文件中是否可以包含多个类(不是内部类)?有什么限制?【基础】

43、说出一些常用的类,包,接口,请各举5 个。【基础】

44、Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类?是否可以implements(实现)interface(接口)? 【基础】

45、内部类可以引用他包含类的成员吗?有没有什么限制?【基础】

46、java 中实现多态的机制是什么?【基础】

47、在java 中一个类被声明为final 类型,表示了什么意思?【基础】

48、下面哪些类可以被继承? 【基础】

49、指出下面程序的运行结果: 【基础】

50、继承时候类的执行顺序问题,一般都是选择题,问你将会打印出什么?【基础】

51、内部类的实现方式? 【基础】

52、关于内部类: 【基础】

53、数据类型之间的转换

54、字符串操作:如何实现字符串的反转及替换?【基础】

55、编码转换:怎样将GB2312 编码的字符串转换为ISO-8859-1 编码的字符串?【基础】

56、写一个函数,要求输入一个字符串和一个字符长度,对该字符串进行分隔。【基础】

57、写一个函数,2 个参数,1 个字符串,1 个字节数,返回截取的字符串,要求字符串中的中文不能出现乱码:如(“我ABC”,4)应该截为“我AB”,输入(“我ABC 汉DEF”,6)应该输出为“我ABC”而不是“我ABC+汉的半个”。【基础】

58、日期和时间:

1)如何取得年月日、小时分秒?

2)如何取得从1970 年到现在的毫秒数?

3)如何取得某个日期是当月的最后一天?

4)如何格式化日期?【基础】

59、Java 编程,打印昨天的当前时刻。【基础】

60、java 和javasciprt 的区别。【基础】

61、什么时候用assert?【中等难度】

62、Java 中的异常处理机制的简单原理和应用?【基础】

63、error 和exception 有什么区别? 【基础】

64、try {}里有一个return 语句,那么紧跟在这个try 后的finally {}里的code会不会被执行,什么时候被执行,在return 前还是后? 【基础】

65、JAVA 语言如何进行异常处理,关键字:throws,throw,try,catch,finally分别代表什么意义?在try 块中可以抛出异常吗?【基础】

66、运行时异常与一般异常有何异同?【基础】

67、给我一个你最常见到的runtime exception?【基础】

68、final, finally, finalize 的区别? 【基础】

69、类Example A 继承Exception,类ExampleB 继承Example A;【基础】

70、介绍JAVA 中的Collection FrameWork(及如何写自己的数据结构)【基础】

71、List,Set,Map 是否继承自Collection 接口?【基础】

72、你所知道的集合类都有哪些?主要方法?【基础】

73、说出ArrayList,Vector, LinkedList 的存储性能和特性?【基础】

74、Collection 和Collections 的区别?【基础】

75、HashMap 和Hashtable 的区别? 【基础】

76、Arraylist 与Vector 区别?【基础】

77、List、Map、Set 三个接口,存取元素时,各有什么特点?【基础】

78、Set 里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别? 【基础】

79、用程序给出随便大小的10 个数,序号为1-10,按从小到大顺序输出,并输出相应的序号。【基础】

80、用JAVA 实现一种排序,JAVA 类实现序列化的方法? 在COLLECTION 框架中,实现比较要实现什么样的接口?【基础】

81、sleep() 和wait() 有什么区别? 【基础】

82、当一个线程进入一个对象的一个synchronized 方法后,其它线程是否可进入此对象的其它方法? 【基础】

83、请说出你所知道的线程同步的方法。【基础】

84、多线程有几种实现方法,都是什么?同步有几种实现方法,都是什么? 【基础】

85、同步和异步有何异同,在什么情况下分别使用他们?举例说明。【基础】

86、启动一个线程是用run()还是start()?【基础】

87、线程的基本概念、线程的基本状态以及状态之间的关系?【基础】

88、简述synchronized 和java.util.concurrent.locks.Lock 的异同?【中等难度】

89、java 中有几种方法可以实现一个线程?用什么关键字修饰同步方法?stop()和suspend()方法为何不推荐使用?【中等难度】

90、设计4 个线程,其中两个线程每次对j 增加1,另两个线程对j 每次减少1;写出程序。【中等难度】

91、什么是java 序列化,如何实现java 序列化?【基础】

92、java 中有几种类型的?JDK 为每种类型的流提供了一些抽象类以供继承,请说出他们分别是哪些类?【基础】

93、文件和目录(IO)操作:

1)如何列出某个目录下的所有文件?

2)如何列出某个目录下的所有子目录?

3)如何判断一个文件或目录是否存在?

4)如何读写文件?【基础】

95、Java 的通信编程,编程题(或问答),用JAVA SOCKET 编程,读服务器几个字符,再写入本地显示?【基础】

96、UML 是什么?常用的几种图?【基础】

97、编程题: 写一个Singleton 出来。【基础】

98、说说你所熟悉或听说过的j2ee 中的几种常用模式?及对设计模式的一些看法。【中等难度】

99、Java 中常用的设计模式?说明工厂模式?【中等难度】

以上面试题太多就不一一展示了需要获取这份面试题含答案解析的小伙伴可以转发+关注后私信(学习)获取

这几十套面试题小编已经为大家整理好了,由于面试文档很多,内容更多,没有办法一一为大家展示出来,所以只好为大家节选出来了一部分供大家参考,需要全部文档的,转发小编的文章+私信【学习】二字即可。

本文作者及来源:Renderbus瑞云渲染农场https://www.renderbus.com

点赞 0
收藏 0

文章为作者独立观点不代本网立场,未经允许不得转载。