3.2字节大数据面试
一面
Java中的接口与抽象类
-
接口用implements实现,抽象类用extends继承
-
接口中全是抽象方法、抽象类中至少有一个抽象方法(没有方法体的方法)
-
一个类只能继承一个类,但可以实现多个接口
-
接口主要是将接口与实现分离开,便于扩展,比如同一个业务有多个不同的实现
-
抽象类中可以有已经实现了的方法,可以作为抽象方法的依赖,比如说一个抽象方法的多个实现都依赖与某个具体方法,这时候可以用抽象类
HashMap
-
底层原理
-
数组加链表
-
-
hash冲突怎么办
-
如何保证读写时间复杂度O(1),存在冲突如何保证O(1)
-
key的hashcode是数组下标
-
理想状态是O(1),存在冲突,需要遍历链表
-
冲突节点过多,会转化成红黑树,降低查询时间复杂度
-
还可能会扩容,缩短链表长度
-
-
容量为什么是 2^n
-
先拿到key的hashcode,是32位int;
-
将高16位与敌16位异或
-
再和容量取 & 操作
-
当容量为2^n时,取余与与操作等价
-
-
线程安全不
-
CurrentHashMap如何实现线程安全的
-
节点锁起来,CAS操作
-
Synchronize与Lock
-
Synchronize是关键字,Lock是类
-
Synchronize加锁不需要自动释放,lock需要(try finally)
-
Synchronize在线程阻塞时仍然持有锁,Lock不会
-
通过Lock可以知道线程有没有拿到锁(trylock),而synchronized不能
锁升级
-
无锁
-
偏向锁
-
轻量级锁
-
重量级锁
JVM
-
java虚拟机
-
由类加载器、运行时数据区、执行引擎、本地方法接口、垃圾回收机制组成
-
java程序先被编译成.class文件,由类加载器加载到内存中,由执行引擎翻译成底层机器码,交给CPU调用本地方法执行,最后垃圾回收
-
运行时数据区包括java堆,Java栈,本地方法区、程序计数器和直接内存
-
Java堆是最主要的工作区域,几乎所有对象的实例化都放在其中
-
java栈主要存放局部变量表、操作数栈、动态链接、方法出口
-
本地方法区主要存放常量静态变量
-
GC
GC流程
-
java堆分成新生代和老年代
-
新生代分成一块eden区和两个survivor区
-
java对象一般会被分配到java堆中的eden区
-
当eden区满了,执行minorGC,将eden中存活的对象移动到survivor1区中,清空eden区
-
新对象又分配在eden区,满了执行minorGC,eden中和survivor1中存活的对象被移动到survivor2区,清空eden区survivor1区;
-
下次survivor1与survivor2区调换,实现对象年龄的增长,年龄增长到一定阈值,对象移动到老年代。
-
老年代满了执行full GC
对象是否应该被GC
-
可达性分析
-
从java栈、本地方法栈中的变量常量出发,如果能到达某个对象则表明它存活,并标记
-
将未标记的对象全部干掉
大数据学了啥
Kafka
-
概念
-
基本架构
-
生产消费数据流程
-
多个生产者同时写或多个消费者同时读问题
算法题
典型回溯
二面
介绍第一个项目
-
相关技术栈 hadoop、spark、Hbase
-
遇到的哪些问题,怎么解决
-
Hbase rowKey 设置讲究
-
作用
-
读写数据时,通过rowKey找到对应的Region
-
MemStore中的数据按RowKey字典顺序排序
-
HFile中的数据按RowKey字典顺序排序
-
-
设计原则
-
唯一性,某一行数据的唯一标识符
-
长度,长度要占存储空间,越短越好
-
随机性,解决Hbase热点问题,避免只访问一个或几个节点
-
-
hbase热点问题解决方案
-
主要是增加rowkey的随机性,常见做法
-
反转:手机号等前几位相似度高,可以反转后使用
-
加盐:rowKey前面加随机数
-
hash处理,MD5
-
-
-
hadoop设了几个数据备份
-
hadoop块的大小,为什么要设置这么大
-
读写数据时间开销主要是:传输时间和寻址时间
-
块太大了,磁盘传输数据时间太长,程序执行慢
-
块太小了,寻址时间长,程序会一直在找块
-
介绍第二个项目
-
相关技术栈 kafka、sparkStreaming、redis
-
用reduceByKey出现数据倾斜怎么办
-
自定义分区(继承Partitioner)
-
使用累加器
-
reduceByKey本身有分区内聚合操作,出现数据倾斜可能性较小
-
-
怎么用的Kafka,新旧API差别
-
用spark封装的KafkaUtils类的createDreateStream方法获取数据
-
高级 API 的特点 优点
-
高级API写起来简单
-
不需要去自行去管理offset,系统通过zookeeper自行管理
-
不需要管理分区,副本等情况,系统自动管理
-
消费者断线会自动根据上一次记录在 zookeeper中的offset去接着获取数据
-
可以使用group来区分对访问同一个topic的不同程序访问分离开来(不同的group记录不同的offset,这样不同程序读取同一个topic才不会因为offset互相影响)
缺点
-
不能自行控制 offset(对于某些特殊需求来说)
-
不能细化控制如分区、副本、zk 等
-
-
低级 API 的特点 优点
-
能够开发者自己控制offset,想从哪里读取就从哪里读取。
-
自行控制连接分区,对分区自定义进行负载均衡
-
对 zookeeper 的依赖性降低(如:offset 不一定非要靠 zk 存储,自行存储offset 即可,比如存在文件或者内存中)
缺点
-
太过复杂,需要自行控制 offset,连接哪个分区,找到分区 leader 等
-
-
算法题
-
我说将节点放到数组中,然后遍历数组重建
-
面试官让想个别的办法
-
提示解决方案:先找到中点,然后反转后半部分链表,然后重建
-
写完了代码,面试官说结果不对,一起bug,没找到。
总结
-
二面有些东西没答出来比如说HBase和Kafka,算法题也没做出来
-
基本上,应该是挂了,虽然还没收到邮件通知
全部评论
(9) 回帖