9.1 滴滴一面 70 分钟
项目
- sparkstreaming 怎么实现的
Spark Streaming在内部处理的机制原理是:先接受实时流的数据,并根据一定的时间间隔拆分成一批批的数据,这些批数据在Spark内核对应一个RDD实例,因此,流数据的DStream可以看成一组RDDs,然后通过调用Spark核心的作业处理这些批数据,最终得到处理后的一批批结果数据。
- 怎么处理 可能就是问如何从 kafka 获取数据
- receiver
使用 kafka 高层次 Comsumer API 来实现的。receiver 从 kafka 获取的数据都是存储在 executor 内存的,然后 spark streaming 启动的 job 会去处理这些数据。用这种方式来与 Kafka 集成,配置中设置了 enable.auto.commit 为 true,表明自己不需要维护 offset,而是由 Kafka 自己来维护(在 Kafka 0.10 后,默认的 offset 存储位置改为了 Kafka,实际上就是 Kafka 的一个 topic),Kafka 消费者会周期性地(默认为 5s)去修改偏移量。这种方式接收的数据都保存在 Receiver 中,一旦出现意外,数据就有可能丢失,要想避免丢失的情况,就必须采用 WAL(Write Ahead Log,预写日志)机制,在数据写入内存前先进行持久化。
现在我们来试想一种情况,数据从 Kafka 取出后,进行了 WAL,在这个时候,Driver 与 Executor 因为某种原因宕机,这时最新偏移量还没来得及提交,那么在 Driver 恢复后,会从记录的偏移量继续消费数据并处理 WAL 的数据,这样一来,被 WAL 持久化的数据就会被重复计算一次。因此,开启了 WAL 后,这样的容错机制最多只能实现“至少一次”的消息送达语义。而且开启 WAL 后,增加了 I/O 开销,降低了 Spark Streaming 的吞吐量,还会产生冗余存储。
2.direct
spark 1.3 引入的,从而能够确保更加健壮的机制。这种接收数据的方式会周期性地查询 kafka,来获取每个 topic+partition 最新的 offset,从而定义每个 batch 的 offset 的范围。当处理数据的 job 启动时,就会使用 kafka 简单 Comsumer API 来获取 kafka 指定 offset 范围的数据。利用 Spark 本身的 DAG 容错机制,使所有计算失败的数据均可溯源,从而实现了“恰好一次”的消息送达语义。
- spark 内存管理
- 哪些 gcroots 可以回收
- 虚拟机栈 本地方法栈引用的对象
2. 方法区中静态属性、常量引用的对象
- 算法题:判断是否有环 证明
9.2 华为一面 1h
项目
- kafka 特点
- 高吞吐 kafka高吞吐量的原因
- 容错性
- 高性能
- kafka broker 挂了怎么办
ISR 选举过程讲一遍。
- map 数据结构
Hashmap
concurrenthashmap
- hashmap 底层数据结构 数组长度多少 怎么扩容的 为什么是 2 的幂次方
- 锁 自旋锁
- 红黑树特点 为什么设计红黑树
查找树,为了解决二叉查找树在某些情况下退化为线性结构,为节点添加了颜色
- 根节点是黑色的;
- 叶子节点是黑色的空节点
- 非红即黑
- 节点是红色的,子节点一定是黑的,反之不一定
- 黑色高度相同
- 贪心算法 动态规划区别
- 算法题:最长不重复子串
9.7 顺丰一面
- hbase 场景
- 结构化和半结构化的数据
数据结构不确定,很难按一个概念去进行抽取的数据。比如需要存储用户的 email、phone、address 信息时需要 RDBMS 停机维护,Hbase 支持动态增加
- 记录稀疏
RDBMS 列是固定的,为 null 的空列浪费很多存储空间。Hbase 的空列不占空间,既节省了空间又提高了读性能
- 多版本数据
存储有变动的历史记录,用Hbase比较方便
- 二级索引
由于HBase的查询比较弱,如果需要实现类似于 select name,salary,count(1),max(salary) from user group by name,salary order by salary 等这样的复杂性的统计需求,基本上不可能,或者说比较困难,所以我们在使用HBase的时候,一般都会借助二级索引的方案来进行实现;
HBase的一级索引就是rowkey,我们只能通过rowkey进行检索。如果我们相对hbase里面列族的列列进行一些组合查询,就需要采用HBase的二级索引方案来进行多条件的查询。
常见的二级索引我们一般可以借助各种其他的方式来实现,例如solr或者ES等。
- hbase 热点问题怎么解决
- 项目模型参数都有哪些
9.18 蘑菇街一面 39min
- Flink、Spark Streaming 区别
- Kakfa 概念
- offset 理解
- Zookeeper 选举机制
- HashMap HashTable ConcurrentHashMap
- BIO NIO
- 为什么要分 S0 S1 区
可以知道,新生代使用复制回收算法,我们设想一下只有一个Survivor区会发生什么情况。
当Eden区填满后,Minor GC进行垃圾回收,幸存的对象会移动到Survivor区,这样循环往复。此时,Survivor区被装满了,也会进行Minor GC,将一些对象kill掉,幸存的对象只能保存在原来的位置,这样就会出现大量的内存碎片(被占用内存不连续)。
应该建立两块Survivor区,刚刚新建的对象在Eden中,经历一次Minor GC,Eden中的存活对象就会被移动到第一块survivor space S0,Eden被清空;等Eden区再满了,就再触发一次Minor GC,Eden和S0中的存活对象又会被复制送入第二块survivor space S1(这个过程非常重要,因为这种复制算法保证了S1中来自S0和Eden两部分的存活对象占用连续的内存空间,避免了碎片化的发生)。S0和Eden被清空,然后下一轮S0与S1交换角色,如此循环往复。
内存碎片化是严重影响性能的,可以设想当有一个稍大一点的对象从Eden区存活转入Survivor区,发现空闲内存断断续续,没有他能落脚的地方,就只能直接存到老年代了,如此反复,老年代会出现我们第一部分的问题。打个比方:我们出去郊游,一些吃的罐头,玩的玩具随便放在包里,最后发现最主要的折叠帐篷放不进去了,只好手拿着到处溜达,非常不方便且影响心情。
最后,如果有两个Survivor区,便可以保证一个为空,另一个是非空且无碎片保存的。
- Kafka 每个分区只能被一个消费者消费
- 重写 重载
9.***华一面 18min
- 重写 重载
- 抽象类 接口区别
- 接口里可以有静态方法和方法体
- 接口中的所有方法必须是抽象方法(JDK8 之后就不是了)
- 接口要被类实现
- 接口支持多继承,类不支持多个类继承
- 一个类只能继承一个类,但是能实现多个接口。接口只能继承另一个接口,用 extends 关键字。
- 接口:在 Java 语言中是一个抽象类型,是抽象方法的集合。接口通常以 interface 来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。
- 类描述对象的属性和方法,接口则包含类要实现的方法。
- 接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。
-
- 抽象类:在面向对象的概念中,所有的对象都是通过类来描述的,并不是所有的类都用来描述对象。如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。抽象类除了不能实例化对象之外,类的其它功能还在,成员变量、成员方法和构造方法的访问方式和普通类一样。由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。父类包含了子类集合的常见方法,由于父类本身是抽象的,所以不能使用这些方法。在 Java 中抽象类表示的一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现多个接口
- 声明抽象类会造成两个后果:
- 如果一个类含有抽象方法,那么该类必须为抽象类
- 任何子类必须重写父类的抽象方法,或者声明自身为抽象类
-
-
- 接口和抽象类的区别:
- 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口不行
- 抽象类的成员变量可以是各种类型(除了 private,因为子类要继承),而接口中的成员变量只能是 public static final 类型的
- 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法的(JDK 1.8 以后,接口可以有静态方法和方法体了
- 一个类只能继承一个抽象类,而一个类可以实现多个接口
-
- 抽象类和普通类的区别:
- 抽象方法必须为 public 或者 protected(如果是 private,子类没办法继承,也就无法实现该方法),缺省情况下默认为 public
- 抽象类不能用来创建对象
- 如果一个类继承于一个抽象类,那么必须实现父类的抽象方法。如果子类没有实现父类的抽象方法,必须声明子类为抽象类
-
- static
- 阻塞有哪些方法
synchronized lock
- lock 接口提供的 synchronized 关键字不具备的主要特性:
- 尝试非阻塞地获取锁。当前线程尝试获取锁,如果这一时刻没有被其它线程获取到,则成功获取并持有锁;
- 能被中断地获取锁。与 synchronized 不同,获取到锁的线程能够被中断,当获取到锁的线程被中断时,中断异常将会被抛出,同时锁被释放;
- 超时获取锁。在指定的截止时间之前获取锁,如果截止时间到了仍旧无法获取锁,则返回。
- rdd 介绍
- 推荐算法了解哪些
- 怎么划分 stage
宽依赖
- MapReduce 流程
- rdd 转换 行动算子
全部评论
(9) 回帖