Java ZooKeeper-RocketMQ 面试题

Java ZooKeeper-RocketMQ 面试题

  • 前言
  • 1、谈谈你对ZooKeeper的理解 ?
  • 2、Zookeeper的工作原理(Zab协议)
  • 3、谈谈你对分布式锁的理解,以及分布式锁的实现?
  • 4、 zookeeper 是如何保证事务的顺序一致性的?
  • 5、 zookeeper主从同步机制:
  • 6、分布式集群中为什么会有 Master?
  • 7、 zk 节点宕机如何处理?
  • 8、说几个 zookeeper 常用的命令?
  • 9、ZK 如何投票实现Leader选举?
  • MQ中间件
  • 10、什么是 RocketMq?
  • 11、什么是消息队列?
  • 12、RocketMq的路由类型和发送消息的方式?
  • 13、死信消息的生命周期?
  • 14、如何保证消息的顺序性?
  • 15、如何防止消息丢失?
  • 16、如何保证消息不被重复消费?
  • 17、MQ处理消息失败了怎么办?
  • 18、消息基于什么传输?
  • 19、RocketMQ 底层原理?
  • 20、RocketMQ为什么速度快, 吞吐量?
  • 21、什么是零拷贝?
  • 22、死信队列?
  • 总结


前言

最新的 Java 面试题,技术栈涉及 Java 基础、集合、多线程、Mysql、分布式、Spring全家桶、MyBatis、Dubbo、缓存、消息队列、Linux…等等,会持续更新。

如果对老铁有帮助,帮忙免费点个赞,谢谢你的发财手!

1、谈谈你对ZooKeeper的理解 ?

ZooKeeper 是一个开源的分布式协调服务,为分布式系统提高了一系列的服务,提供的服务包括了:服务注册与订阅、统一命名服务、集群管理、分布式锁和分布式通知等。
Zookeeper提供了三个核心功能,分别是:文件系统、监听机制和集群管理

  • 1、文件系统
    Zookeeper存储数据的结构,类似于一个文件系统,每个节点(znode)都是类似于K-V的结构,每个节点的名字相当于key,每个节点保存的数据,相当于value。
  • 2、监听机制
    客户端先向ZooKeeper服务端的某个节点注册一个 Watcher 监听,当监听的数据状态发生变化时,服务端会向指定客户端发送一个事件通知,客户端收到事件以后,调用对应的回调方法,完成事件变更的通知。
  • 3、集群管理
    Zookeeper提供了CP的模型,来保证集群中的每个节点的数据一致性。
    zookeeper本身是一个集群结构,它有3种角色:
    leader领导者:处理所有的事务请求(写请求),也可以处理读请求,集群中只有一个leader;
    follower追随者:只能处理读请求,参与leader选举
    observer观察者:只能处理读请求,不参与leader选举,作用是为了提升集群的读性能

2、Zookeeper的工作原理(Zab协议)

  • Zookeeper的工作原理核心是原子广播机制,这个机制保证了各个节点之间的数据一致性,实现这个机制的协议叫做Zab协议。
    Zab协议有两种模式,分别是恢复模式(选主)和广播模式(同步),当服务启动或者 Leader 服务器宕机,Zab就进入了恢复模式,此时不对外提供服务。
  • 首先选举出新的 Leader 服务器,然后与其他的Follower 服务器进行数据同步,当集群中超过半数机器完成数据同步之后,退出恢复模式进入广播模式,然后就可以接收客户端的事务请求了。

3、谈谈你对分布式锁的理解,以及分布式锁的实现?

  • 分布式锁,是一种跨进程的跨机器节点的互斥锁,它可以保证同一时刻只能有一个线程去访问共享资源。
    目前实现分布式锁最常用的中间件是 Redis 和 Zookeeper:
  • Redis:利用它提供的 SETNX 命令,如果设置key返回1,说明获取锁成功,返回0获取锁失败。然后还可以通过 EX参数来设置key的过期时间,从而避免死锁问题。
    但也可能存在一些极端情况,比如锁过期了,但是业务逻辑还没处理完。这种极端情况可以使用Redisson 客户端来实现,Redisson 中有一个 watchdog 的机制,翻译过来就是看门狗,它是基于Netty下面的一个时间轮的实现类来实现。(getLock、lock、unlock)
  • Zookeeper:利用它提供的有序节点,当线程创建节点后,如果该节点是当前目录下所有节点序号最小的节点,则认为获取锁成功。如果不是最小的节点,则对该节点序号的前一个节点添加一个监听事件,当监听的节点释放锁之后,触发回调通知,从而再次去尝试抢占锁。
    总的来说,这两种方案都有各自的优缺点:
    Redis它获取锁的方式简单粗暴,如果获取不到锁,会不断尝试获取锁,消耗性能比较大,但是实现难度比较低。
    Zookeeper如果获取不到锁,只需要添加一个监听器就可以了,消耗性能比较小,但是实现难度比较高。

4、 zookeeper 是如何保证事务的顺序一致性的?

  • zookeeper采用了全局递增的事务Id 来标识,所有的 proposal(提议)在被提出的时候都会加上 zxid,zxid实际上是一个64位的数字,高32位是epoch(时期; 纪元; 世; 新时代)用来标识leader是否发生改变,如果有新的leader产生出来,epoch会自增,然后低32位用来递增计数。
    当产生新的提议时,zookeeper会采用数据库的二阶段提交,首先会向其他的节点发出事务执行请求,如果超过半数的机器都能执行,那么就会提交事务。

5、 zookeeper主从同步机制:

  • 1、当leader 接受到消息请求后,会给消息加上一个全局的事务Id (zxid);
  • 2、leader将带有zxid的消息作为一个提案(proposal)分发给所有的follower;
  • 3、当follower接受到提案后,先把提案写到磁盘,写入成功以后再向leader回复一个ack;
  • 4、当leader 接受到半数以上ack,就会向follower发送提交commit命令,同时自己也执行;
  • 5、当follower接受到commit命令以后,就会提交该消息,从而实现数据同步。

6、分布式集群中为什么会有 Master?

在分布式环境中,有些业务逻辑只需要集群中的某一台机器进行执行,其他的机器可以共享这个结果,这样可以大大减少重复计算,提高性能。

7、 zk 节点宕机如何处理?

  • 1、如果是一个 Follower 宕机,只要超过半数的节点正常,集群就能正常提供服务,否则集群就会失效;
  • 2、如果是一个 Leader 宕机,Zookeeper会进入恢复模式,重新选举出新的 Leader。
    Zookeeper本身也是集群,推荐不少于 3 个服务器,而且最好奇数个。

8、说几个 zookeeper 常用的命令?

常用命令:ls get set create delete 等。

9、ZK 如何投票实现Leader选举?

如果 Leader 节点宕机了,为了保证集群继续提供服务,Zookeeper 需要从剩下的 Follower 节点里面去选举一个新的节点作为 Leader,也就是所谓的 Leader 选举。具体的实现是:

  • 1、每一个节点都会向集群里面的其他节点发送一个票据 Vote,这个票据包括三个属性:epoch逻辑时钟,zxid事务id,myid服务器id;然后第一轮投票都会投给自己。
  • 2、每个节点把收到的票据和自己节点的票据做比较,根据 epoch、zxid、myid 的顺序逐一比较,以值最大的一方获胜,比较结束以后就把票投给获胜的节点;
  • 3、通过多轮投票以后,以少数服从多数的方式,最终获得票数最多的节点成为Leader。
    到这里,leader选举就结束啦。
    其中epoch,逻辑时钟,用来标识当前票据是否过期;zxid,事务id,用来表示当前节点最新存储的数据的事务编号; myid,服务器id,在 myid 文件里面填写的;

MQ中间件

10、什么是 RocketMq?

  • RocketMq是一个基于 AMQP 高级消息队列协议的中间件,接受并转发消息。它有4个核心组件,分别是:
  • producer生产者:负责生产和发送消息到 Broker;
  • Exchange交换机:按照一定的规则将消息路由转发到某个队列,对消息进行过虑;
  • Queue队列:用来存储消息,并把消息转发给指定的消费者;
  • consumer消费者:负责从 Broker 中获取消息,并进行相应处理;
    它的工作原理是生产者把消息发送到Exchange交换机上。Exchange交换机把收到的消息根据路由规则,转发给绑定的queue队列,队列再把消息投递给订阅了这个队列的消费者,从而完成消息的异步通讯。

11、什么是消息队列?

消息队列 Message Queue,简称 MQ。
消息队列有很多使用场景,比较常见的有3个:解耦、异步、削峰。

  • 1、应用解耦:把相关联的系统进行职责解耦,比如:生成订单会调用仓库管理系统或积分系统。
  • 2、异步处理:不需要立即处理消息,提高系统的性能,比如:用户注册发送验证码、下单短信通知、发送优惠券等。
  • 3、流量削峰:能够有效的顶住瞬间高并发,防止服务器承受不住导致崩溃,比如秒杀、限时抢购优惠券等。
    比如吞吐量低的中小型公司,一般用 ActiveMQ、RabbitMQ 较为合适,
    大数据、吞吐量高的大型公司一般选用 Kafka 和 RocketMQ。

12、RocketMq的路由类型和发送消息的方式?

它的工作原理是生产者把消息发送到Exchange交换机上,Exchange交换机把收到的消息根据路由规则,转发给绑定的queue队列,最后再把消息投递给订阅了这个队列的消费者,从而完成消息的异步通讯。
在RabbitMQ中,交换机常见的有3种类型,分别是Fanout、Direct 、Topic:

  • Fanout(扇出交换机):类似于广播机制,将消息转发给到所有绑定的队列上,与routingKey(路由键)无关;
  • Direct(直连交换机):完整匹配方式,也就是Routing key和Binding Key完全一致,才把消息发给该队列;
  • Topic(主题交换机):就是Routing Key加了通配符,符合匹配规则的Queue队列都会收到这个消息,#:代表0个或多个单词,*:代表一个单词。

13、死信消息的生命周期?

  • 1、消费者消费业务消息时发生异常,就会返回nck或者reject操作;
  • 2、那么这些消息就会被投递到死信交换机中;
  • 3、死信交换机将消息发送到相应的死信队列;
  • 4、死信队列可以定时重新投递到Broker中,也可以由死信消费者消费。

14、如何保证消息的顺序性?

这个问题是由于不同的消息都发送到了同一个 queue队列中,而这个queue队列又被多个消费者消费。
解决这个问题,我们可以给 RabbitMQ 创建多个 queue队列,每个队列对应一个消费者。比如生产者发送消息的时候,同一个订单号的消息发送到同一个 queue队列中,由于同一个 queue队列的消息是有序的,那么同一个订单号的消息就只会被一个消费者顺序消费,从而保证了消息的顺序性。

15、如何防止消息丢失?

  • 1)、使用事务消息
  • 2)、使用消息确认机制
    消息丢失的场景有下面几种:
  • 1)、生产者发送消息到MQ的过程中丢失
    解决方法: 在生产者端开启comfirm 确认模式,每个消息会分配一个唯一的 id,如果MQ写入了内存中, 就会返回一个ack,告诉你说这个消息ok了,如果MQ没有写入这个消息,会回调一个nack接口,告诉你这个消息失败了,你可以进行重试或抛弃此条消息。
  • 2)、MQ收到消息,写入到内存中,还没消费,服务挂掉了,数据都会丢失
    解决方法:将消息持久化到磁盘,有两个步骤:
    第1步:把该消息设置为持久化,即deliveryMode设置为2,第3个参数设置如下:
    channel.basicPublish(“exchange”, “routingKey”, MessageProperties.PERSISTENT_TEXT_PLAIN, " message".getBytes());
    第2步:把该queue队列设置为持久化,即durable=true,第2个参数设置为true,
    channel.queueDeclare(QUEUE_NAME, true, false, false, null);
  • 3)、消费者刚拿到消息,还没处理,服务挂掉了,MQ又以为消费者处理完了
    解决方式:首先关闭 RabbitMQ 的自动 ack,然后消费者在处理完消息之后,再手动返回ack。这样可以保证,如果你还没处理完,就不会返回ack,那队列就不会删除该消息。
    (关闭 RabbitMQ 的自动 ack,即autoAck=false,第2个参数设置为false
    channel.basicConsume(QUEUE_NAME, true, new DefaultConsumer(channel){});)

16、如何保证消息不被重复消费?

我们为了消息的可靠性,采用了手动ack机制;如果消费者在处理完一个消息之后,还没有手动调用ack,服务就挂了,MQ以为你还还没处理,就把这个消息投递给其他的消费者,就导致了消息被重复消费。
我觉得这个问题可以分为2种场景来对待:

  • 第1种幂等性场景:就是说消息重复消费和消费一次产生的影响是一样的,可以不用处理,比如Redis的set操作,它是天然幂等性的;
  • 第2种非幂等性场景:把消息唯一id保存到 mysql 或者 redis 里面,在处理消息之前先去 mysql 或者 redis 里面,判断一下是否已经消费过了。

17、MQ处理消息失败了怎么办?

一般生产环境中,都会在使用MQ的时候设计两个队列:一个是核心业务队列,一个是死信队列。核心业务队列,就是比如专门用来给订单系统发送订单消息的,然后另外一个死信队列就是用来处理异常情况的。

18、消息基于什么传输?

RabbitMQ 使用channel通道的方式来传输数据,通道是建立在真实的 TCP 连接内的虚拟连接,且通道数量没有限制,大大提升了MQ的处理性能。

19、RocketMQ 底层原理?

RocketMQ 架构主要包含以下四个部分:

  • 1、NameServer:是一个简单的Topic路由注册中心,支持Broker的注册与发现,主要有两个功能:Broker管理(提供心跳检测机制)和路由信息管理(保存Broker的路由信息和用于客户端查询的队列信息);
  • 2、BrokerServer:RocketMQ 的核心组件,主要负责消息的
    1、存储:CommitLog(存储消息的文件);
    2、投递:ConsumeQueue(消息消费队列);
  • 3.查询:IndexFile(索引文件);
  • 4.以及维护消费者的Topic订阅信息和保证服务高可用;
    1、Producer:消息生产者,往Broker发送指定Topic的消息。
    2、Consumer:消息消费者,主动拉取消息来消费,支持集群方式(同一Topic下的一条消息只会发送到同一消费组中的一个消费者)和广播方式(所有的消息会广播发送到所有的消费者)。

20、RocketMQ为什么速度快, 吞吐量?

因为使⽤了顺序存储、页缓存(Page Cache)和异步刷盘;我们在写⼊commitlog的时候是顺序写⼊的,这样⽐随机写⼊的性能就会⾼很多,而且它不是直接写⼊磁盘,⽽是先写⼊页缓存,开启一个异步线程通过零拷贝机制,定时的将缓存中的数据刷到磁盘中,从而保证消息的快速读写。

21、什么是零拷贝?

  • 传统⽂件复制方式:需要对⽂件在内存中进⾏四次复制(内核态到用户态的来回复制)。
  • 零拷⻉:就是减少内核态到用户态的来回复制,它是通过内存映射的机制,直接把内核态里的数据映射到用户态,对文件的操作转化为对内存地址的操作;
    通常有两种⽅式,mmap(RocketMq)和sendfile(kafka)。
    在这里插入图片描述

22、死信队列?

当一条消息消费失败时,经过多次重试依然失败,为了保证消息数据不丢失,需要将消息投入到死信队列中。
死信的来源:

  • 1、消息 TTL(存活时间)过期
  • 2、队列满了,无法再添加数据到队列中
  • 3、消息被拒绝(消费方拒绝应答:basic.reject 或 basic.nack)并且不放回队列中( requeue=false)

总结

都已经看到这里啦,赶紧收藏起来,祝您工作顺心,生活愉快!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用lnmp环境部署laravel框架需要注意的点

1,上传项目文件后,需要chmod -R 777 storage授予文件权限,不然会报错file_put_contents(/): failed to open stream: Permission denied。 如果后面还是报错没有权限的话,就执行ps -ef |grep php查询php运行用户。然后执行chown …

STM32-ADC一步到位学习手册

1.按部就班陈述概念 ADC 是 Analog-to-Digital Converter 的缩写,指的是模拟/数字转换器。它将连续变量的模拟信号转换为离散的数字信号。在 STM32 中,ADC 具有高达 12 位的转换精度,有多达 18 个测量通道,其中 16 个为外部通道&…

小朋友来自多少小区 - 华为OD统一考试(C卷)

OD统一考试(C卷) 分值: 100分 题解: Java / Python / C 题目描述 幼儿园组织活动,老师布置了一个任务: 每个小朋友去了解与自己同一个小区的小朋友还有几个。 我们将这些数量汇总到数组 garden 中。 请…

gofly框架接口入参验证使用介绍

接口传入的参数做相关性质验证是开发中较为常用,gofly框架内置校验工具,提供开发效率,开发接口简单调用即可实现验证,下面介绍gofly框架数据验证设计思路及使用方法。 gofly框架提供了功能强大、使用便捷、灵活易扩展的数据/表单…

jupyter调用envs环境——jupyter内核配置虚拟环境

1.jupyter无法使用envs环境 pycharm的终端打开jupyter notebook: 在kernel下找不到上面的Pytorch_GPU环境: 2.解决方法 在对应的envs环境中安装ipykernel: 将该环境写入jupyter: python -m ipykernel install --user --name Py…

蓝桥杯前端Web赛道-自适应页面

蓝桥杯前端Web赛道-自适应页面 题目链接:1.自适应页面 - 蓝桥云课 (lanqiao.cn) 先看题目要求: 简单的来说就是需要完成上面规定的布局和要求当800px及以下的时候要显示移动端布局来完成下面gif的效果,那么我们先一步一步来 首先想到的就…

逻辑漏洞(pikachu)

#水平,垂直越权,未授权访问 通过个更换某个id之类的身份标识,从而使A账号获取(修改、删除)B账号数据 使用低权限身份的账号,发送高权限账号才能有的请求,获得其高权限操作 通过删除请求中的认…

SpringCloud微服务技术栈-什么是Docker?怎么安装Docker?

初识Docker以及常见技术及其概念概述 1、项目部署存在的问题 大型项目组件较多,运行环境也较为复杂,部署时会碰到一些问题: 依赖关系复杂,容易出现兼容性问题 开发、测试、生产环境有差异 Docker如何解决大型项目依赖关系复杂&#xff0…

面试高频率问答题目

索引: 主键索引:表的id (唯一 且 不能为空) 唯一索引:表User 假设有account 字段 ,用户名不重复 (唯一 可以为空) 复合索引:where() 的条件 用户名,密码 …

判断点是否在多边形内

std::vector<cv::Point2d> vanCorner_;bool inArea(const Pose &pos) {cv::Point2d point cv::Point2d(pos.position.x(), pos.position.y());double distance cv::pointPolygonTest(vanCorner_, point, false);return distance > 0; } 似乎效果不太好,会误报 …

springboot236基于springboot在线课程管理系统的设计与实现

基于SpringBoot在线课程管理系统的设计与实现 摘要 本文首先介绍了在线课程管理系统的现状及开发背景&#xff0c;然后论述了系统的设计目标、系统需求、总体设计方案以及系统的详细设计和实现&#xff0c;最后对在线课程管理系统进行了系统检测并提出了还需要改进的问题。本系…

STM32 | 零基础 STM32 第一天

零基础 STM32 第一天 一、认知STM32 1、STM32概念 STM32:意法半导体基于ARM公司的Cortex-M内核开发的32位的高性能、低功耗单片机。 ST:意法半导体 M:基于ARM公司的Cortex-M内核的高性能、低功耗单片机 32&#xff1a;32位单片机 2、STM32开发的产品 STM32开发的产品&a…

李宏毅机器学习入门笔记——第八节

Auto-Encoder 输入图片经过两个网络后&#xff0c;计算他们两个越接近越好。 类似于Cycle GAN。 encoder将高纬度数据降维&#xff0c;作为低纬度向量 假如噪声进行训练&#xff0c;encoder将图片中的噪声去除。 其实BERT而言&#xff0c;就是以后个auto-encoder。 Feature d…

linux之进程理解(1)

目录 1. 冯诺依曼体系结构 2. 操作系统(OS) 2.1 概念 2.2 设计OS的目的 2.3 定位 2.4 理解管理 3. 系统调用和库函数概念 4. 补充 1. 冯诺依曼体系结构 我们常见的计算机&#xff0c;如笔记本。我们不常见的计算机&#xff0c;如服务器&#xff0c;大部分都遵守冯诺依曼体…

电子电气架构——AUTOSAR架构下EcuM唤醒源事件详解

电子电气架构——AUTOSAR架构下EcuM唤醒源事件详解 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 没有人关注你。也无需有人关注你。你必须承认自己的价值,你不能站在他人的角度来反对自己。人…

CDC作业历史记录无法删除问题

背景 数据库开启CDC功能后&#xff0c;每天会生成大量的历史记录&#xff0c;即使达到参数“每个作业的最大历史记录“的阈值后也不会被删除&#xff0c;导致其它作业的历史记录被删除&#xff0c;无法查看以前的执行情况&#xff0c;非常不方便。 现象 数据库开启CDC后会创建…

JavaScript入门学(Web APIs)

1.变量声明 2 DOM介绍 2.1 什么是DOM 2.2 DOM树 2.3 DOM对象&#xff08;重要&#xff09; 3.DOM&#xff08;文档对象模型&#xff09;-获取元素 3.1 获取匹配的第一个元素 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8&…

swoole

php是单线程。php是靠多进程来处理任务&#xff0c;任何后端语言都可以采用多进程处理方式。如我们常用的php-fpm进程管理器。线程与协程,大小的关系是进程>线程>协程,而我们所说的swoole让php实现了多线程,其实在这里来说,就是好比让php创建了多个进程,每个进程执行一条…

Python爬虫——Urllib库-3

目录 ajax的get请求 获取豆瓣电影第一页的数据并保存到本地 获取豆瓣电影前十页的数据 ajax的post请求 总结 ajax的get请求 获取豆瓣电影第一页的数据并保存到本地 首先可以在浏览器找到发送数据的接口 那么我们的url就可以在header中找到了 再加上UA这个header 进行请…

ssm个人学习01

Spring配置文件: spring环境的搭建: 1:导入对应的spring坐标 也就是依赖 2:编写controller, service, dao相关的代码 3:创建配置文件(在resource下面配置文件) 例如:applicationContext.xml <bean id "" class ""> <property name "&…