作者:牛客899427222号
    链接:https://www.nowcoder.com/discuss/604268?source_id=discuss_experience_nctrack&channel=-1
    来源:牛客网

    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
    概念

    基本架构

    生产消费数据流程

    多个生产者同时写或多个消费者同时读问题

    算法题
    leetcode113 路径总和

    典型回溯

    二面
    介绍第一个项目
    相关技术栈 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 等

    算法题
    leetcode143 重排链表

    我说将节点放到数组中,然后遍历数组重建

    面试官让想个别的办法

    提示解决方案:先找到中点,然后反转后半部分链表,然后重建

    写完了代码,面试官说结果不对,一起bug,没找到。

    总结
    二面有些东西没答出来比如说HBase和Kafka,算法题也没做出来

    基本上,应该是挂了,虽然还没收到邮件通知