1、百度大数据面试题学习目标l 掌握Spark缓存l 掌握zookeeper选举l 掌握什么是脑裂l 理解Hbase为什么用日志合并树l 理解hdfs的数据一致性l 掌握平衡二叉树的插入删除等操作l 掌握JDK1.8 新特性l 理解Paxos协议l 了解Java的NIO1 Spark做缓存时缓存在哪里问题分析主要考查缓存的时候数据存储在哪里,可以从缓存方式入手核心讲解缓存解决什么问题?-解决的是热点数据频繁访问的效率问题在Spark开发中某些RDD的计算或转换可能会比较耗费时间,如果这些RDD后续还会频繁的被使用到,那么可以将这些RDD进行持久化/缓存,这样下次再使用到的时候就不用再重新计算了,提
2、高了程序运行的效率。APIrdd.cacherdd.persist/cache底层persistrdd.persist(StorageLevel.MEMORY_ONLY)/persist底层默认是内存rdd.persist(StorageLevel.MEMORY_AND_DISK)/开发中使用内存+磁盘(内存不够时才用!)rdd.unpersist()/清空缓存可以将RDD数据直接缓存到内存中,函数声明如下:但是实际项目中,不会直接使用上述的缓存函数,RDD数据量往往很多,内存放不下的。在实际的项目中缓存RDD数据时,往往使用如下函数,依据具体的业务和数据量,指定缓存的级别。在Spark框架中
3、对数据缓存可以指定不同的级别,对于开发来说至关重要,如下所示:问题扩展释放缓存/持久化当缓存的RDD数据,不再被使用时,考虑释资源,使用如下函数:此函数属于eager,立即执行。结合项目使用在反爬虫项目里面就会将爬虫的ip数据持久化,因为需要频繁的使用这部分数据。2 Linux系统(常用命令啥的)问题分析考查Linux命令,大家在学习的过程当中接触了很多命令,特别是高级的Linux命令,尽量的说出来。核心讲解find、df、tar、ps、top、netstat、grep、awk、sed等等问题扩展Linux查看内存、磁盘存储、io 读写、端口占用、进程等命令 1、查看内存:top 2、查看磁盘
4、存储情况:df -h 3、查看磁盘IO读写情况:iotop(需要安装一下:yum install iotop)、iotop -o (直接查看输出比较高的磁盘读写程序) 4、查看端口占用情况:netstat -tunlp | grep 端口号 5、查看进程:ps aux结合项目使用Linux命令与大数据开发工程师的岗位结合的非常紧密,不可能不用这些命令,例如在工作中用的经常根据内容查询某个文件,要用到grep、每天早上来了之后发现查询很慢需要用到系统命令、如果要恢复数据需要用到awk命令等等。3 除了这些平时还接触或者学习哪些技术问题分析看似是个送分题,其实隐隐已经透露出面试官对你目前掌握的技术
5、熟练度或者宽度不满。所以一定要拿点硬货出来。核心讲解除了Hadoop、spark之外,还会NOSQL相关的一些数据库,例如Redis、HBASE、ELK,还会NewSql(HBASE+Phoenix)。使用过FLink计算引擎做过车联网项目,用到的技术架构有Flink + kafka + HBASE + Phoenix还会做一些可视化分析的工具,例如FineBI、superset、zeppeline等等。问题扩展对HBASE+Phoenix二级索引做进一步讲解。用API读取HBASE数据当数据量大了之后会很慢,HBASE+Phoenix二级索引之后,可以加快查询速度,之前在项目中测试过是HBA
6、SE查询的100倍。Phoenix索引有全局索引、本地索引、函数索引、覆盖索引。结合项目使用在车联网项目里,为了可视化查询的更快也跟家方便,用到了HBASE + PHoenix二级索引。4 自定义UDF、UDTF问题分析考查是否会自定义UDF、UDTF函数核心讲解Hive自定义UDF函数的流程1)写一个类继承(org.apache.hadoop.hive.ql.)UDF类; 2)覆盖方法evaluate(); 3)打JAR包; 4)通过hive命令将JAR添加到Hive的类路径: hive add jar /home/ubuntu/ToDate.jar; 5)注册函数: hive create
7、 temporary function xxx as XXX; 6)使用函数;自定义UDTF过程以及例子编程套路:继承org.apache.hadoop.hive.ql.udf.generic.GenericUDTF,实现initialize, process, close三个方法。UDTF首先会调用initialize方法,此方法返回UDTF的返回行的信息加粗样式(返回个数,类型)。初始化完成后,会调用process方法,真正的处理过程在process函数中,在process中,每一次forward()调用产生一行;如果产生多列可以将多个列的值放在一个数组中,然后将该数组传入到forward
8、()函数。最后close()方法调用,对需要清理的方法进行清理。问题扩展需求:切分”key:value;key:value;”这种字符串,返回结果为key, value两个字段。public class ExplodeMap extends GenericUDTF Override public void close() throws HiveException Override public StructObjectInspector initialize(ObjectInspector args) throws UDFArgumentException if (args.length !=
9、 1) throw new UDFArgumentLengthException(ExplodeMap takes only one argument); if (args0.getCategory() != ObjectInspector.Category.PRIMITIVE) throw new UDFArgumentException(ExplodeMap takes string as a parameter); ArrayList fieldNames = new ArrayList(); ArrayList fieldOIs = new ArrayList(); fieldName
10、s.add(col1); fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector); fieldNames.add(col2); fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector); return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames,fieldOIs); Override public void process(Objec
11、t args) throws HiveException String input = args0.toString(); String test = input.split(;); for(int i=0; i 1)3.右边的是平衡二叉树节点6的子节点:节点3的高度为:1,节点7的高度为:0,| 1 0 | = 1 = 1 )平衡二叉树的特点AVL树是高度平衡的(严格平衡),频繁的插入和删除,会引起频繁的rebalance,导致效率下降,它比较试用与插入/删除较少,查找较多的场景。因为子节点只有2个,所以深度会很大,不利于查询。需要重新设计二叉树16 JDK1.8 新特性问题分析考查JDK8
12、的认识程度核心讲解default关键字在java里面,我们通常都是认为接口里面是只能有抽象方法,不能有任何方法的实现的,那么在jdk1.8里面打破了这个规定,引入了新的关键字default,通过使用default修饰方法,可以让我们在接口里面定义具体的方法实现,Lambda表达式是jdk1.8里面的一个重要的更新,这意味着java也开始承认了函数式编程,并且尝试引入其中。首先,什么是函数式编程,引用廖雪峰先生的教程里面的解释就是说:函数式编程就是一种抽象程度很高的编程范式,纯粹的函数式编程语言编写的函数没有变量,因此,任意一个函数,只要输入是确定的,输出就是确定的,这种纯函数我们称之为没有副作
13、用。而允许使用变量的程序设计语言,由于函数内部的变量状态不确定,同样的输入,可能得到不同的输出,因此,这种函数是有副作用的。函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数!函数式接口定义:“函数式接口”是指仅仅只包含一个抽象方法的接口,每一个该类型的lambda表达式都会被匹配到这个抽象方法。jdk1.8提供了一个FunctionalInterface注解来定义函数式接口,如果我们定义的接口不符合函数式的规范便会报错。方法与构造函数引用jdk1.8提供了另外一种调用方式:,当你需要使用方法引用时,目标引用 放 在 分隔符:前 ,方法的名称放在 后 面 ,即C
14、lassName : methodName 。例如 ,Apple:getWeight就是引用了Apple类中定义的方法getWeight。请记住,不需要括号,因为你没有实际调用这个方法。方法引用就是Lambda表达式(Apple a) - a.getWeight()的快捷写法。函数式接口定义:“函数式接口”是指仅仅只包含一个抽象方法的接口,每一个该类型的lambda表达式都会被匹配到这个抽象方法。jdk1.8提供了一个FunctionalInterface注解来定义函数式接口,如果我们定义的接口不符合函数式的规范便会报错。方法与构造函数引用jdk1.8提供了另外一种调用方式:,当你需要使用方法
15、引用时,目标引用 放 在 分隔符:前 ,方法的名称放在 后 面 ,即ClassName : methodName 。例如 ,Apple:getWeight就是引用了Apple类中定义的方法getWeight。请记住,不需要括号,因为你没有实际调用这个方法。方法引用就是Lambda表达式(Apple a) - a.getWeight()的快捷写法。局部变量限制Lambda表达式也允许使用自由变量(不是参数,而是在外层作用域中定义的变量),就像匿名类一样。 它们被称作捕获Lambda。 Lambda可以没有限制地捕获(也就是在其主体中引用)实例变量和静态变量。但局部变量必须显式声明为final,或
16、事实上是final。为什么局部变量有这些限制?(1)实例变量和局部变量背后的实现有一个关键不同。实例变量都存储在堆中,而局部变量则保存在栈上。如果Lambda可以直接访问局部变量,而且Lambda是在一个线程中使用的,则使用Lambda的线程,可能会在分配该变量的线程将这个变量收回之后,去访问该变量。因此, Java在访问自由局部变量时,实际上是在访问它的副本,而不是访问原始变量。如果局部变量仅仅赋值一次那就没有什么区别了因此就有了这个限制。(2)这一限制不鼓励你使用改变外部变量的典型命令式编程模式。Date Api更新1.8之前JDK自带的日期处理类非常不方便,我们处理的时候经常是使用的第三方工具包,比如commons-lang包等。不过1.8出现之后这个改观了很多,比如日期时间的创建、比较、调整、格式化、时间间隔等。这些类都在java.time包下。流定义:流是Java API的新成员,它允许我们以声明性方式处理数据集合(通过查询语句来表达,而不是临时编写一个实现)。就现在来说,我们可以把它们看成遍历数据集的高级迭代器。此外,流还可以透明地并行处理,也就是说我们不用写多线程代码了。17 请说一下spark的RDD?问题分析考查RDD的特性核心讲解RDD的5大特性RDD 是一个数据集的抽象表示,不仅表示了数据集,还表示了这个数据集