大数据开发遗漏知识点完善(持续更新)

1. Hive整合HBase的环境配置以及测试

1、环境配置
Hive与HBase整合的实现是利用两者本身对外的API接口互相通信来完成的,其具体工作交由Hive的lib目录中的hive-hbase-handler-.jar工具类来实现。所以只需要将hive的 hive-hbase-handler-.jar 复制到hbase/lib中就可以了。
注:如果在hive整合hbase中,出现版本之类的问题,那么以hbase的版本为主,将hbase中的jar包覆盖hive的jar包。

2、在hive中创建映射hbase的表
在hive中创建一个映射hbase的表,为了方便,设置两边的表名都为t_student,存储的表也是这个。
在hive中输入:
create table t_student(id int,name string) stored by ‘org.apache.hadoop.hive.hbase.HBaseStorageHandler’ with serdeproperties(“hbase.columns.mapping”=":key,st1:name") tblproperties(“hbase.table.name”=“t_student”,“hbase.mapred.output.outputtable” = “t_student”);
说明:org.apache.hadoop.hive.hbase.HBaseStorageHandler 这个是指定的存储器。
hbase.columns.mapping 是定义在hbase的列族,key对应hbase的rowkey,st1表示列簇,name表示列。

HBase中表数据是以列簇存储在HDFS中的,其中每个列簇对应HDFS中的一个单独文件。

2. 栈内存和堆内存溢出

1、 栈内存溢出情况(StackOverflowError):
栈是内存私有的,它的生命周期和线程相同,每个方法在执行时会创建一个栈帧,用于存储局部变量、操作数、动态链接、方法出口等信息。
栈内存溢出可以理解为方法执行时创建的栈帧超过了栈的最大深度,即递归容易出现栈内存溢出。
2、 堆内存溢出情况(OutOfMemoryError):
堆内存中主要存储对象实例,当这些对象实例的大小达到一定的阈值,比如无限循环向一个集合插数据,就会导致堆内存溢出。

3. Spark开发性能调优

1、 分配更多的资源进行调优;
2、 设置合理的并行度
理想情况下,task数量设置成spark Application的总CPU核数,但是现实中总有一些task运行慢一些task运行快,快的先执行完,导致空余的CPU核就浪费了,官方建议task数量设置成spark Application的总CPU核数的2~3倍。
SparkConf conf = new SparkConf().set(“spark.default.parallelism”,”500”)
3、 RDD的重用、RDD持久化到内存/磁盘、数据序列化(大大减少数据存储的内存空间)、双副本机制(提高容错)。
4、 广播变量(Broadcast)
若不使用broadcast,默认情况下,每个task执行的算子中,使用到了非本地的变量,每个task都会获取一份变量的副本,若副本较大,则会消耗大量的内存;
若使用broadcast,在driver上会有一份初始的副本,在启动后,当需要使用到广播变量中的数据时,Executor会获取driver中的副本,或者去距离更近的节点上获取副本,以后该节点上的所有task即可直接使用该节点上的副本。
总而言之,广播变量的好处就是:将每个task一份副本,变成每个Executor一份副本,大大减少了变量副本的数量。
5、 Kryo序列化
Spark默认使用java的序列化机制objectInputstream/objectOutputStream,而Kryo序列化机制速度要快很多,且序列化后的数据大小比默认要小很多。
SparkConf conf = new SparkConf().set(“spark.serializer”,” org.apache.spark.serializer.KryoSerializer”).registerKryoClasses(new Class[]{CategorySortKey.class})
注:如果要达到Kryo的最佳性能的话,那么就一定要注册自定义的类。
6、 Fastutil(JDK7以上)
扩展了 java标准集合框架的类库,提供了Map、Set、List和queue这几种类型,更小的内存占用,更快的存取速度
7、 本地化等待时长做合理的调整,默认3秒
8、 Shuffle调优
① 合并map端输出文件,默认是不开启的
new SparkConf().set(“spark.shuffle.consolidateFiles”,”true”)
② Map端内存缓冲和reduce内存占比调整,默认每个task的内存缓冲为32kb,reduce端内存占比为0.2.
spark.shuffle.file.buffer = 32kb -> 128kb
spark.shuffle.memoryFraction = 0.2 -> 0.3
9、 使用mapPartitions(Iterator[U] -> Iterator[V])方法代替普通的Map(func)
优点:假如一个partition中有一万条数据,那么map中的function就要执行和计算一万次,但是使用mapPartitions,一个task对应一个partition就只会执行一次function,function一次接收一个partition中所有的数据;
缺点:如果一个partition数据有上亿条,一次性传入function之后,可能导致内存直接溢出,所以要估算每个partition的数据能不能一下子缓存到分配给Executor的内存中,确保可以,才能使用。
10、 当使用filter过后,出现以下情况时,①每个partition内的数据量偏差较大(数据倾斜);②partition数据量急剧减少,就需要使用coalesce算子来处理,用来压缩partition的数量。
11、 使用foreachPartition()方法批量写入数据到数据库。
12、 reduceByKey()的本地聚合
在map端,给下一个stage的每个task创建的输出文件中,写数据之前,会进行本地的combiner操作,减少了数据量,也减少了磁盘IO,同时减少了网络传输。

4. HashMap与Hashtable的区别

1、 HashMap允许key或者value为null,而Hashtable不允许;
2、 Hashtable继承自Dictionary类,而HashMap是JDK2引进的Map接口的一个实现;
3、 Hashtable的方法被synchronized关键字修饰,而HashMap没有。即Hashtable线程安全,写入效率偏低;而HashMap线程不安全。

5. HashMap、LinkedHashMap和TreeMap的区别

遍历时,HashMap取出数据的顺序是完全随机的;
LinkedHashMap保存了记录的插入顺序,即先插入的数据就先被取出来;
TreMap实现SortMap接口,默认按键值的升序排序,也可以自定义比较器,比如在treeMap初始化实例时,创建一个内部类,实现Comparator接口,自定义排序。

6. Spark作业执行流程

1、 Spark集群启动,通过ActorSystem创建MasterActor,启动定时器,定时检查与接受Worker节点的发送消息;
2、 Worker节点主动向Master发送注册消息;
3、 Master接受Worker的注册请求(TCP协议请求),然后把Worker的注册信息保存起来,并向Worker返回一个注册成功的消息;
4、 Worker接受到Master注册成功的消息后,启动定时器,定时向Master发送心跳报活,Master接受到Worker发送来的心跳消息,更新Worker上一次的心跳时间,若超出最大等待时间,Master会将超时Worker的注册信息删掉,所以Spark各个节点时间同步极其重要;
5、 DAGScheduler根据FilnalRDD递归向上解析Lineager的依赖关系,并以宽依赖为切分一个新stage的依据,并将多个task任务封装到TaskSet,其中Task的数量由其父RDD的切片数量决定,最后使用递归提交最浅的参数,即优先提交父stage的TaskSet;
6、 先创建TaskScheduler,接着又创建SparkDeploySchedulerBackend,创建AppClient向Master注册Application,用于管理资源,并替每个TaskSet创建TaskManager负责监控此TaskSet中任务的执行情况;
7、 Master接收到ClientActor的任务描述后,将任务描述信息保存起来,然后返回消息给ClientActor,告知ClientActor任务注册成功,接下来Master(打散|负载均衡|尽量集中)进行资源调度;
8、 Master跟Worker通信,然后让Worker启动Executor;
9、 Executor向Driver发送注册信息,Driver接收到Executor注册消息后,响应注册成功的消息;
10、 Executor接收到Driver注册成功的消息后,本进程中创建Executor的引用对象;
11、 Driver中TaskScheduler向Executor发送LaunchTask消息,Executor将创建一个线程池作为所提交的Task任务的容器;
12、 Task接收到LaunchTask消息后,准备运行文件初始化与反序列化,就绪后,调用Task的run方法,其中每个Task所执行的函数是应用在RDD中的一个独立分区上;
13、 Task运行完成,向TaskManager汇报情况,并且释放线程资源;
14、 所有Task运行结束之后,Executor向Worker注销自身,释放资源。

7. JavaWeb框架的原理

1、 Spring的工作原理
① IOC:控制反转,从字面意思就可以看出是控制权颠倒的意思。没错,也正是这样。将相互依赖的对象通过封装到IOC容器中,容器内部对外部是透明的,当一个对象需要创建他的依赖对象时,由于IOC容器加入,两个对象之间会失去直接联系,IOC容器此时会把握各个对象的控制权,会通过反射主动创建一个依赖对象注入到需要对象中,使创建对象的过程变得轻量及对象间的耦合度大幅度降低。
② DI:依赖注入,不需要去类内部去和依赖的类进行绑定,而是将依赖关系以参数的形式注入到类的内部,使对象间的耦合度降低,通常与IOC配合使用。
③ AOP:面向切面编程,也被称为横切关注点,实现将通用实现模块和核心业务模块相分离,是高内聚低耦合的又一体现。

2、 SpringMVC的工作原理
MVC模型图
在这里插入图片描述分析:
M-Model 模型(完成业务逻辑:有javaBean构成,service+dao+entity)
V-View 视图(做界面的展示 jsp,html……)
C-Controller 控制器(接收请求—>调用模型—>根据结果派发页面)

3、 Mybatis的工作原理
创建对象与关系数据库的映射,做数据库的增删查改操作。
4、 Hibernate的工作原理
创建对象与关系数据库的映射,做数据库的增删查改操作。

8. Mybatis常见题

1、 #{}和$${}的区别是什么?
#{} 解析传递进来的参数数据,进行预编译处理;
${} 对传递进来的参数原样拼接在SQL中,即直接进行字符串替换。
2、 当实体类中属性名和表中的字段名不一样,如数据库字段是order_id,对象属性名为orderId,怎么办?
① 查询的sql语句中定义字段名为属性名作为别名即可。
select order_id orderId from orders where order_id=#{orderId}
② 通过resultMap映射字段名和属性名一一对应(推荐)。
3、 如何获取自动生成的(主)键值
在插入之前,通过select LAST_INSERT_ID() 即可获取到要插入的该条数据的自动生成的主键值。
4、 resultType和resultMap的区别
在mybatis进行查询映射时,查询出来的每一个属性都是放在一个对应的map里面的,其中键是属性名,值是对应的查询结果。
① 当提供的返回类型属性是resultType时,mybatis会将map里面的键值对取出赋给resultType所制定的对象对应的属性,前提是查询字段名与指定对象的属性名一致。所以mybatis的每一个查询映射的返回类型都是resultMap;
② 当提供的返回类型属性是resultMap时,如果查询出的列名和pojo属性名不一致,则需要定义一个resultMap在列名和pojo属性名之间做一个映射关系。

9. 集群中大量小文件的处理方法

1、 在将大量小文件上传到HDFS之前,通过flume采集文件夹下的文件时,将小文件进行滚动,再上传到HDFS上。
具体实现:
第一种方法:将sink中的round时间系列参数去掉,并将rollSize和rollCount置为0,表示部根据临时文件大小和event数量来滚动文件;
第二种方法:设置a1.sinks.k1.hdfs.minBlockReplicas=1,文件会因为块的复制而滚动文件。
2、 若HDFS上已经存在大量的小文件,则可以在mapreduce程序的起始map端,重写InputFormat类,继承CombinerFileInputFormat,可以将众多小文件逻辑上当作一个文件交于一个maptask来拆分处理。

10. SparkStreaming读取kafka的数据

1、 createStream
使用receiver从Kafka中拉取数据存储在Spark Executor的内存中,利用的是kafka高层次的消费者api,然后SparkStreaming启动的job会去处理这些拉取过来的数据。然而,在默认配置下,这种方式可能会因为底层的失败而丢失数据。如果要启用高可靠机制,让数据零丢失,就必须启用sparkStreaming的预写日志机制(该机制会同步地将接收到的kafka数据写入分布式文件系统上的预写日志中),即使底层节点出现了失败,也可以使用预写日志中的数据进行数据恢复。
2、 createDirectStream
引入Direct方式,kafka与sparkStreaming直连,用来代替掉使用Receiver接收数据,这种方式需要获取kafka中topic+partition的最新的offset,并更新到zk上,sparkStreaming通过调用kafka的简单消费者api读取一定范围偏移量的数据。与基于Receiver方式相比:
① 简化并行。不需要创建多个kafka输入流,sparkStreaming将会创建和kafka分区一样的RDD分区个数,而且会从kafka并行地读取数据,也就是说spark分区将会和kafka分区一一对应的关系,当然kafka的分区数量可以稍微建立多一些,从而提高并行度;
② Receiver方式,启用高可靠机制,即KafkaUtils.createStream(…, StorageLevel.MEMORY_AND_DISK_SER),这种方式实际上会导致数据被拷贝两次,很不高效。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值