项目问题
- 挑一个做得好的项目介绍下全流程。难点在哪,讲一下。
Java 相关问题
- JVM 内存结构?大体架构有几层(不是细分到年轻代、老年代)?手动画一下?
- JVM 方法区持久代会溢出吗?
- 为啥 Java 语言里面要有反射?反射是什么?(==》反射用多了最终会导致持久化溢出)
- 动态代理怎么解释?(==》动态代理用多了最终会导致持久代溢出)
- 持久化里面除了存储类信息还存储了啥?1. 类信息 2. 常量池 3. 静态常量
- 一个类的静态字段和实例字段分别存储在什么位置?
- 栈溢出?什么时候会发生栈溢出?
- 你有遇到过内存溢出的情况吗?如果内存溢出了怎么定位问题?一般怎么分析内存溢出后生成的堆转储文件?
- JDK 自带的工具:jstack、jmap 等,你有用过吗?
- JAVA 里面都有什么锁?
- Synchronize 是可重入锁吗?分别都是锁在什么上面?
- HashMap 实现原理?HashTable-》HashMap、ConcurrentHashMap相关?HashMap put方法执行过程?得到 key 的hash值后怎么确定它在哈希数组中的索引位置?
- 如果我们自定义的对象作为HashMap 的key的话,要重写什么方法?equals 和hashcode?
单例模式(Singleton)
Java中的实例指的是基于某个类的对象实现,这一过程被称为实例化。因此有时候我们也将对象叫做一个类的实例
单例模式就是:单一的实例,即在某个系统中只存在一个实例。即一个类只有一个实例。
为什么使用单例模式
通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。
使用单例模式的例子
数据库的连接池 / 线程池、缓存、日志对象等,它们都只需要创建一个对象。
单例模式的好处
使用单例模式好处在于可以节省内存,节约资源,因为它限制了实例的个数,有利于java垃圾回收。好的单例模式也能提高性能。对于一般频繁创建和销毁对象的可以使用单例模式。
单例模式的缺点
一、开销
虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题。
二、可能的开发混淆
使用单例对象时,开发人员必须记住自己不能使用new关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类。
三、对象生存期
不能解决删除单个对象的问题。在提供内存管理的语言中,只有单例类能够导致实例被取消分配,因为它包含对该实例的私有引用。在某些语言中(如 C++),其他类可以删除对象实例,但这样会导致单例类中出现悬浮引用
单例模式失灵
但使用静态final的实例对象或者使用静态代码块依旧不能解决在反序列化、反射、克隆时重新生成实例对象的问题。
当单例对象有必要实现 Serializable 接口时,即使将其构造函数设为私有,在它反序列化时依然会通过特殊的途径再创建类的一个新的实例,相当于调用了该类的构造函数有效地获得了一个新实例。
单例模式 —— 饿汉模式
//“饿汉模式”(eager initialization),即在初始阶段就主动进行实例化,并时刻保持一种渴求的状态,无论此单例是否有人使用。
public class Sun{
//static确保将太阳放入内存里的静态区,GC不会对其回收。在类加载的时候就初始化了,比堆中的对象实例化要早。
private static final Sun sun = new Sun();
private Sun(){
//禁止外部调用无参构造器
}
//需要一个静态方法getInstance()来获取太阳的单例对象,同时将其设置为“public”以暴露给外部使用
public static Sun getInstance(){
return sun;
}
}
单例模式 —— 懒汉模式
饿汉模式的缺点:如果始终没人获取日光,那岂不是白造了太阳,一块内存区域被白白地浪费了。
public class Singleton{
//volatile对静态变量的修饰则能保证变量值在各线程访问时的同步性、唯一性
private volatile static Singleton single;
private Singleton(){
}
//这种线程还没进入方法内部便不管三七二十一直接加锁排队,会造成线程阻塞,资源与时间被白白浪费。
//public static synchronized Singleton getInstance(){
//if(single == null)
//single = new Singleton();
//return single;
//}
//我们一共用了2个嵌套的判空逻辑,这就是懒加载模式的“双检锁”:外层放宽入口,保证线程并发的高效性;内层加锁同步,保证实例化的单次运行
public static Singleton getInstance(){
if(single == null){
synchronized(Singleton.class){
if(single == null)
single = new Singleton();
}
}
return single;
}
}
这样的好处是如无请求就不实例化,节省了内存空间;而坏处是第一次请求的时候速度较之前的饿汉初始化模式慢,因为要消耗CPU资源去临时创建这个对象。
但是上面的程序在并发条件下是有问题的。可以加上synchronized同步锁让其同步。这样某线程调用前必须获取同步锁,调用完后会释放同步锁给其他线程用。
相比“懒汉模式”,在大多数情况下我们通常会更多地使用“饿汉模式”,原因在于这个单例迟早是要被实例化占用内存的,延迟懒加载的意义并不大,加锁解锁反而是一种资源浪费,同步更是会降低CPU的利用率.
大数据组件复习
HDFS
MapReduce
1. MR实现wordcount过程
spark
1. spark和MR的核心区别
spark比mapreduce的好处在哪:
1.spark把中间计算结果存放在内存中,减少迭代过程中的数据落地,能够实现数据高效共享,迭代运算效率高。mapreduce中的计算中间结果是保存在磁盘上的,这样必然影响整体运行速度。
2.spark容错性高。spark支持DAG图的分布式并行计算(简单介绍一下spark DAG:即有向无环图,描述了任务间的先后依赖关系,spark中rdd经过若干次transform操作,由于transform操作是lazy的,因此,当rdd进行action操作时,rdd间的转换关系也会被提交上去,得到rdd内部的依赖关系,进而根据依赖,划分出不同的stage。
3.spark更加通用。hadoop只提供了map和reduce两种操作,spark提供的操作类型有很多,大致分为转换和行动操作两大类。转换操作包括:map,filter,flatmap,sample,groupbykey,reducebykey,union,join,cogroup,mapvalues,sort,partitionby等多种操作,行动操作包括:collect,reduce,lookup和save等操作
2. 说一下checkpoint机制,项目中有用到吗?
1)为什么需要checkpoint?
分布式计算中难免因为网络,存储等原因出现计算失败的情况,RDD中的lineage信息常用来在task失败后重计算使用,为了防止计算失败后从头开始计算造成的大量开销,RDD会checkpoint计算过程的信息,这样作业失败后从checkpoint点重新计算即可,提高效率。
2)什么时候写checkpoint数据?
- 当RDD的action算子触发计算结束后会执行checkpoint。
- 在spark streaming中每generate一个batch的RDD也会触发checkpoint操作。
3)什么时候读checkpoint数据?
task计算失败的时候会从checkpoint读取数据进行计算。
3. 说一下Spark 和 Hadoop区别?
Spark,是分布式计算平台,是一个用scala语言编写的计算框架,基于内存的快速、通用、可扩展的大数据分析引擎
Hadoop,是分布式管理、存储、计算的生态系统;包括HDFS(存储)、MapReduce(计算)、Yarn(资源调度)
4. 说一下Spark streaming 和 Flink 还有 Storm 的区别?
storm支持at-least-once语义。 Spark streaming 和 Flink支持exactly once语义。
5. stage,job,task 的联系。如何划分stage?
spark如何知道是宽依赖还是窄依赖 宽依赖(一个父RDD对应多个子RDD)对应的对象是shuffleDependency。ShuffleDependency被CoGroupedRDD和ShuffledRDD所创建
划分stage的思路:从后往前推,遇到宽依赖就断开,划分为一个Stage。遇到窄依赖就将这个RDD加入到该stage中,DAG最后一个阶段会为每个结果的partition生成一个ResultTask。每个Stage里面的Task数量由最后一个RDD的Partition数量决定,其余的阶段会生成ShuffleMapTask。
6. RDD、DataFrame、DataSet的区别?
DataFrame: 是一种以RDD为基础的分布式数据集, 被称为SchemaRDD RDD(Resilient Distributed Dataset):弹性分布式数据集,是一个容错的、并行的数据结构
7. 如何确定task 数量
每个Stage里面的Task数量由最后一个RDD的Partition数量决定,其余的阶段会生成ShuffleMapTask。
8. 50台机器,如何保证每台机器上运行一个Task?怎么设置参数?
9. Spark 如何处理数据倾斜?一个task 特别慢,其他的很慢都等待?如何应对这个task?
- 提高并行度。只能缓解最大的那个Task倾斜,不能根治。
- Spark AQE Skew Join。AQE根据shuffle文件统计数据自动检测倾斜数据,将那些倾斜数据的分区打散成小的子分区,然后各自进行join
10. 有没有其他的方式,比如说数据预处理,在传入Spark 之前的预处理?
手动过滤倾斜的key并向这些数据添加随机"加盐"处理
11. Spark 如何通过调参处理数据倾斜?
- spark.sql.adaptive.shuffle.targetPostShuffleInputSize: 64M -> 512M 设置reduce任务处理文件的上限
通过优化InputSize,单个Task处理的数据量变多了,然后Aggrerator产生了作用,有效的降低了整体的shuffle数据量。
- spark.sql.files.maxPartitionBytes: 1G -> 40G 把每个分区写大小提高,这样每个分区能写的数量就比较多
通过参数调整,让M*R有了几个数量级的下降。增大了读取时候的 Chunk size,减缓了随机读的问题。减少了shuffle过程中IOPS,避免了长时间的 Blocked Time
- spark.default.parallelism && spark.sql.shuffle.partitions: 并发度过高的话会导致随机读。并发度过低的话,一个Task处理的数量就会太大,如果这个作业并发跑不起来,作业端到端的时间就会延长。
- spark.hadoopRDD.ignoreEmptySplits:在最开始减少一些不必要的partition数量,如果文件是空的就不产生partition
- spark.reducer.maxSizeInFlight
spark.reducer.maxReqsInFlight spark.reducer.maxBlocksInFlightPerAddress
当数据实在过大的时候,可以调节reducer的OOM数据,让reducer读取的速度变慢,从而防止把磁盘打爆
12. Spark的shuffle优化
避免shuffle,使用broadcast替代join
传统的join操作会导致shuffle,因为两个RDD中相同的key都需要通过网络拉取到一个节点上,由一个task进行join操作。用Broadcast+map替换join操作
如果一个RDD对应的数据比较小,比如一个RDD数据有1TB,而另外一个只有500MB。这个时候就可以将第二个RDD broadcast出去,作为广播变量发给所有Executor。然后在rdd1的map算子中,可以从rdd2DataBroadcast中,获取rdd2的所有数据。然后进行遍历,如果发现rdd2中某条数据的key与rdd1的当前数据的key是相同的,那么就做一些map操作。以上操作仅在rdd2的数据量比较少如几百M或者1,2G的情况下,因为每个Executor的内存中,都会驻留一份rdd2的全量数据,否则会触发OOM。
13. spark架构和工作原理
Cluster Manager是集群管理器,控制整个集群,监控Worker,负责资源管理和调度。
Worker节点是从节点,在yarn中可以称为Node manager负责控制计算节点,启动Executor进程
Driver Program相当于一个APP master,负责作业的任务调度,是一个JVM进程。其运行程序的main函数,创建一个spark context上下文
用户会创建一个SparkContext,然后SparkContext会连接到Cluster Manager,Cluster Manager根据用户提交时设置的参数为本次提交去分配计算资源来启动executor。
Driver会将用户程序划分不同的stage,每一个stage会有一组完全相同的task去构成。这些Task会处理一些待处理数据的不同分区。这些创建完成后,Driver会向Executor发送task
Executor接收到task之后,会下载task的运行时依赖,准备好task的执行环境,然后开始执行task。task会不停的将状态告知给driver,driver根据这些状态不断的发送task到executor。
flink
1. flink的checkpoint和exactly-once语义的实现
exactly-once由两阶段提交协议和checkpoint来实现的
2PC: 是一种分布式算法,用于协调参与分布式原子事务的所有进程,以确定是提交还是终止(回滚)事务。其包括两阶段:1. 提交请求阶段 2. 提交阶段
flink的检查点是一个snapshot,其包括: 1.The current state of an application 2.The position in an input stream
yarn
hadoop
网络:
- TCP 和 UDP 的区别?
答了可靠和不可靠,答了应用场景。 - TCP 是怎么实现可靠性的?
答了:ACK机制,三次握手四次挥手,流量控制,拥塞控制。没有继续追问。 - 为啥需要三次握手和四次挥手?
为了保证全双工。发送方和接收方都有发送和接受的能力。没有继续追问。 - IP 地址和 MAC 地址的区别说一下?
IP 是网络层,MAC是数据链路层。IP可以来做路由转发,MAC主要是ARP点对点发送。 - 只用MAC地址不用IP地址行不行?\
不行。MAC地址太多了,种类也多,直接找MAC地址不现实,都是先找到同一片局域网内在进行ARP寻址