哔哩哔哩推荐搜索大数据研发面经
大家好,今天为大家奉献上新鲜出炉的大数据开发面经,不会的背起来!!!
面试时间:54 分钟
面试方向:推荐搜索大数据研发工程师
面试工具:赛码网
面试难度 : ⭐⭐⭐⭐
岗位要求:如下图。
面试环节
1 面试官: 做个自我介绍吧
面试官,您好! 我叫 xxx , xxxx 年 x 月毕业于 xxx 学校,xx 学历,目前就职于 xxx 公司 xxx 部门,职位为:大数据开发工程师,主要从事于 Flink 流计算组件、平台的开发工作。
工作以来,我先后参加了 xxx 项目、xxx 项目以及 xxx 项目,积累了丰富的项目经验,同时,这 x 个项目都得到了领导的一致好评。
我对流计算组件有着浓厚的兴趣,工作之余经常钻研技术、例如:xxx 等。
2 面试官:kafka 组件熟悉吗,kafka 如何实现消息的有序的?
生产者:通过分区的 leader 副本负责数据以先进先出的顺序写入,来保证消息顺序性。
消费者:同一个分区内的消息只能被一个 group 里的一个消费者消费,保证分区内消费有序。
kafka 每个 partition
中的消息在写入时都是有序的,消费时, 每个 partition
只能被每一个消费者组中的一个消费者消费,保证了消费时也是有序的。
整个 kafka 不保证有序。如果为了保证 kafka
全局有序,那么设置一个生产者,一个分区,一个消费者。
3 面试官:Kafka 消息确认(ack 应答)机制了解吗?
为保证 producer
发送的数据,能可靠的达到指定的 topic ,Producer 提供了消息确认机制。生产者往 Broker
的 topic 中发送消息时,可以通过配置来决定有几个副本收到这条消息才算消息发送成功。可以在定义 Producer
时通过 acks
参数指定,这个参数支持以下三种值:
(1)acks = 0:producer 不会等待任何来自 broker 的响应。
特点:低延迟,高吞吐,数据可能会丢失。
如果当中出现问题,导致 broker
没有收到消息,那么 producer
无从得知,会造成消息丢失。
(2)acks = 1(默认值):只要集群中 partition 的 Leader 节点收到消息,生产者就会收到一个来自服务器的成功响应。
如果在 follower
同步之前,leader
出现故障,将会丢失数据。
此时的吞吐量主要取决于使用的是 同步发送 还是 异步发送 ,吞吐量还受到发送中消息数量的限制,例如 producer
在收到 broker
响应之前可以发送多少个消息。
(3)acks = -1:只有当所有参与复制的节点全部都收到消息时,生产者才会收到一个来自服务器的成功响应。
这种模式是最安全的,可以保证不止一个服务器收到消息,就算有服务器发生崩溃,整个集群依然可以运行。
根据实际的应用场景,选择设置不同的 acks
,以此保证数据的可靠性。
另外,Producer
发送消息还可以选择同步或异步模式,如果设置成异步,虽然会极大的提高消息发送的性能,但是这样会增加丢失数据的风险。如果需要确保消息的可靠性,必须将 producer.type 设置为 sync。
#同步模式 producer.type=sync #异步模式 producer.type=async
4 面试官:LEO、HW、LSO、LW 分别代表什么?
LEO :是 LogEndOffset
的简称,代表当前日志文件中下一条。
HW:水位或水印一词,也可称为高水位(high watermark)
,通常被用在流式处理领域(flink、spark)
,以表征元素或事件在基于时间层面上的进展。在 kafka
中,水位的概念与时间无关,而是与位置信息相关。严格来说,它表示的就是位置信息,即位移(offset)
。取 partition
对应的 ISR
中最小的 LEO
作为 HW,consumer 最多只能消费到 HW 所在的上一条信息。
LSO: 是 LastStableOffset
的简称,对未完成的事务而言,LSO 的值等于事务中第一条消息的位置(firstUnstableOffset),对已完成的事务而言,它的值同HW 相同。
LW: Low Watermark
低水位,代表 AR
集合中最小的 logStartOffset
值。
5 面试官:java 中 object 类有哪些方法?
Object 是所有类的父类,任何类都默认继承 Object,主要包含 9 个方法:
1. clone 方法
保护方法,实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法,否则抛出CloneNotSupportedException异常。
2. getClass 方法
final 方法,获得运行时类型。
3. toString 方法
该方法用得比较多,一般子类都有覆盖。
4. finalize 方法
该方法用于释放资源。因为无法确定该方法什么时候被调用,很少使用。
5. equals 方法
该方法是非常重要的一个方法。一般 equals 和 == 是不一样的,但是在Object中两者是一样的。子类一般都要重写这个方法。
6. hashCode 方法
该方法用于哈希查找,重写了 equals 方法一般都要重写 hashCode 方法。这个方法在一些具有哈希功能的 Collection 中用到。
7. wait 方法
用于让当前线程失去操作权限,当前线程进入等待序列
8. notify 方法
唤醒在此对象监视器上等待的单个线程。
6 面试官:说一下==和equals的区别?
== 对于基本类型来说是 值比较
,对于引用类型来说是比较的是引用
;
equals 默认情况下是引用比较,只是很多类重写了 equals 方法,比如 String、Integer 等把它变成了值比较,所以一般情况下 equals 比较的是值是否相等
7 面试官: 为什么要重写 equals 和 hashcode()方法
首先:两个对象相同(即用 equals 比较返回 true),那么它们的 hashCode 值一定相同;
String str1 = "通话"; String str2 = "通话"; System.out.println(String.format("str1:%d | str2:%d", str1.hashCode(),str2.hashCode())); System.out.println(str1.equals(str2)); ............ 结果如下:........ str1:1179395 | str2:1179395 true
但是:两个对象的 hashCode 相同,这两个对象并不一定相同(即用 equals 比较返回 false)
String str1 = "通话"; String str2 = "重地"; System.out.println(String.format("str1:%d | str2:%d", str1.hashCode(),str2.hashCode())); System.out.println(str1.equals(str2)); ............ 结果如下:........ str1:1179395 | str2:1179395 false
所以,为了避免代码出错,需要重写 equals 和 hashcode 方法。
8 面试官: 机器学习了解吗? 能简单介绍一下这个概念吗?
额 (⊙o⊙)…
目前官方的定义,由来自卡内基梅隆大学机器学习领域的著名教授 Tom Mitchell提出。
一个程序被认为能从经验E
中学习,解决任务 T
,达到性能度量值 P
,当且仅当,有了经验 E
后,经过 P
评判,程序在处理 T
时的性能有所提升。
具体可以看看土哥之前写的这篇文章 当机器学习拥有思维后......
9 面试官: 监督学习 和 无监督学习的区别是啥??
机器学习主要分为:监督学习(Supervised Learn)和无监督学习(Unspervised Learn)。
(1)监督学习简单理解就是:我们将教计算机如何去完成任务。
监督学习对未知事物的预测,一般分为两类问题:
回归问题: 预测连续值输出,如房屋预测。
分类问题:预测离散值输出,如乳腺癌预测。
监督学习都带有标签
。即数据集给出正确答案(有标签,有y值)。
(2)无监督学习简单理解就是,我们打算让计算机自己进行学习。
无监督学习的特点是:没有任何的标签
。
训练样本不含有标记(label)信息,既没有类别信息,也不会给定目标值。(没有属性或标签,不知道正确的答案)。
算法题
10 面试官:写一个简单的算法吧,归并排序
先简单介绍一下它的思想:
归并排序 是 1945 年由约翰·冯·诺伊曼首次提出。该算法采用分治法实现,且各层分治递归可以同时进行。
1、基本思想
归并排序算法 是将两个(或两个以上)有序表合并成一个新的有序表
,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列
。
2、算法描述
归并排序通过递归方式实现:
自上而下的递归
递归法(假设序列共有n个元素):
将序列每相邻两个数字进行归并操作,形成 floor(n/2)个序列,排序后每个序列包含两个元素;
将上述序列再次归并,形成 floor(n/4)个序列,每个序列包含四个元素;
重复步骤②,直到所有元素排序完毕。
代码实现:
/** * 归并排序(递归) * * ①. 将序列每相邻两个数字进行归并操作,形成 floor(n/2)个序列,排序后每个序列包含两个元素; * ②. 将上述序列再次归并,形成 floor(n/4)个序列,每个序列包含四个元素; * ③. 重复步骤②,直到所有元素排序完毕。 * @param arr 待排序数组 */ /** * 归并排序 * * @param arrays * @param L 指向数组第一个元素 * @param R 指向数组最后一个元素 */ public static void mergeSort(int[] arrays, int L, int R) { //如果只有一个元素,那就不用排序了 if (L == R) { return; } else { //取中间的数,进行拆分 int M = (L + R) / 2; //左边的数不断进行拆分 mergeSort(arrays, L, M); //右边的数不断进行拆分 mergeSort(arrays, M + 1, R); //合并 merge(arrays, L, M + 1, R); } } /** * 合并数组 * * @param arrays * @param L 指向数组第一个元素 * @param M 指向数组分隔的元素 * @param R 指向数组最后的元素 */ public static void merge(int[] arrays, int L, int M, int R) { //左边的数组的大小 int[] leftArray = new int[M - L]; //右边的数组大小 int[] rightArray = new int[R - M + 1]; //往这两个数组填充数据 for (int i = L; i < M; i++) { leftArray[i - L] = arrays[i]; } for (int i = M; i <= R; i++) { rightArray[i - M] = arrays[i]; } int i = 0, j = 0; // arrays数组的第一个元素 int k = L; //比较这两个数组的值,哪个小,就往数组上放 while (i < leftArray.length && j < rightArray.length) { //谁比较小,谁将元素放入大数组中,移动指针,继续比较下一个 if (leftArray[i] < rightArray[j]) { arrays[k] = leftArray[i]; i++; k++; } else { arrays[k] = rightArray[j]; j++; k++; } } //如果左边的数组还没比较完,右边的数都已经完了,那么将左边的数抄到大数组中(剩下的都是大数字) while (i < leftArray.length) { arrays[k] = leftArray[i]; i++; k++; } //如果右边的数组还没比较完,左边的数都已经完了,那么将右边的数抄到大数组中(剩下的都是大数字) while (j < rightArray.length) { arrays[k] = rightArray[j]; k++; j++; } }
时间复杂度为:O()
11 面试官:使用递归算法有哪些缺点?
递归 由于是函数调用自身。
而函数调用是有时间和空间的消耗的:每一次函数调用,都需要在内存栈中分配空间以保存参数、返回地址以及临时变量,而往栈中压入数据和弹出数据都需要时间。这样效率会比较低。
#哔哩哔哩##面经#