哔哩哔哩推荐搜索大数据研发面经

大家好,今天为大家奉献上新鲜出炉的大数据开发面经,不会的背起来!!!

面试时间: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个元素):

  1. 将序列每相邻两个数字进行归并操作,形成 floor(n/2)个序列,排序后每个序列包含两个元素;

  2. 将上述序列再次归并,形成 floor(n/4)个序列,每个序列包含四个元素;

  3. 重复步骤②,直到所有元素排序完毕。

代码实现:

/**
 * 归并排序(递归)
 *
 * ①. 将序列每相邻两个数字进行归并操作,形成 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 面试官:使用递归算法有哪些缺点?

递归 由于是函数调用自身。

而函数调用是有时间和空间的消耗的:每一次函数调用,都需要在内存栈中分配空间以保存参数、返回地址以及临时变量,而往栈中压入数据和弹出数据都需要时间。这样效率会比较低。

#哔哩哔哩##面经#
全部评论
土哥!!!yyds
1 回复
分享
发布于 2022-03-02 23:49
满满干货,很实用的,感谢分享
点赞 回复
分享
发布于 2022-02-14 15:41
联易融
校招火热招聘中
官网直投
感觉大数据和算法都没咋问,这个岗位是不是做平台的啊,要精通java😂
点赞 回复
分享
发布于 2022-03-12 09:11

相关推荐

1、new一个子类会创建几个对象?super指的是什么?this指的是什么?2、重写和重载有什么区别?什么是多态呢?3、怎么实现直接退出两层for循环?4、抽象类和接口有什么区别呢?接口可以写方法实现吗?5、序列化是什么意思呢?为什么要加一个版本号呢?不加的话,会有什么后果吗?会自动帮我加吗?6、信号量的原理是什么?与线程池的区别?线程变量分别用那个信号量和线程池的区别?线程池的状态?7、linkedHashMap和treeMap有什么区别呢?8、Runnable和Callable的区别是什么呢?获取到这个返回值?join方法的作用?多线程之间通信的机制有哪几种呢?线程池有哪些拒绝策略?说说怎么实现用请求线程执行?9、不可响应中断的阻塞有哪些呢?10、mysql事务隔离级别有哪些呢?怎么解决幻读?11、如果有一张很大的表的话,有五百万数据里面,怎么查表性能是最好的?12、ES里面的keyword和text这两个字段有什么区别吗?match和term这两个关键字有什么区别吗?模糊匹配怎么设置?13、springbean是线程安全的吗?如果让你实现一个IOC容器,你会怎么设置呢?spring的自动装配原理?14、redis做一个排行榜,怎么做可以节省内存和减少内存碎片呢?15、zookeeper脑裂问题?16、让你做一个安全接口设计会怎么做呢?17、sentinel限流策略了解过吗?那漏桶会有什么缺点吗?18、怎么查看GC次数?如果发现内存占用过高,我要看一下是哪些对象占用了,我怎么看呢?19、你平时是如何学习的东西?20、代码实现一个生产者和消费者模型
点赞 评论 收藏
转发
8 65 评论
分享
牛客网
牛客企业服务