1.hdfs的原理,各个进程的作用
hdfs是一个主从架构的分布式文件管理系统。
设计思想:分而治之——将大文件、大批量文件,分布式存放在大量独立的服务器上,以便于采取分而治之的方式对海量数据进行运算分析。
hdfs提供了一个统一的目录树来定位hdfs中的文件,文件是被切块存储在若干台datanode服务器上,每一个文件的每一个切块,在hdfs集群中都可以保存多个备份(默认3份)。
namenode:它维护了一个hdfs的目录树及hdfs目录结构与文件真实存储位置的映射关系,负责管理集群任务调度,资源分配等。
datanode服务进程专门负责接收和管理"文件块,接收按成nameNode分配的任务。
secondnamenode可以做冷备份,即对namenode做快照。
jobtracker:管理任务,将任务分配给子节点上的tasktracker执行
2.hdfs的容错机制
HDFS数据块副本机制,文件分块后存储在不同datanode上,默认备份三份。
secondnamenode是namenode的冷备份,保存namenode中对HDFS metadata的信息的备份,并减少namenode重启的时间。
3.mapreduce在yarn上的执行过程
1. job.waitForCompletion()向Resource Manager发出一个请求,请求运行一个mr程序,分配一个jobid和一个job资源提交的路径;
2. 向HDFS提交所需要的资源,需要的jar包以及计算切片后得到的切片信息;
3. 向Resource Manager申请一个容器来运行MRAPPMaster进程,Resource Manager分配nodemanager,nodemanager去hdfs上下载所需的程序文件;
4. hdfs发送一个启动MRAPPMaster的命令,开始执行map和reduce任务;
5. 最后一个reducetask运行完毕之后,MRAPPMaster会向Resource Manager汇报job运行完毕并且退出。资源会被nodemanager回收。
4.hive的优化
整体架构优化点:
1.根据不同业务需求进行日期分区,并执行类型动态分区。
相关参数设置 默认hive.exec.dynamic.partition=ture
2.文件压缩
hive中间表以SequenceFile保存,可以节约序列化和反序列化的时间hive.query.result.fileformat=SequenceFile
3.mr优化:
调整reduce个数
4.解决数据倾斜问题set hive.groupby.skewindata=true
5.job优化:
小数据使用本地模式
对小文件进行合并
map端join
6.sql优化:
Map端join,以大表作驱动,小表载入所有mapper内存中
调整Join顺序,确保以大表作为驱动表
函数过滤 null
尽量减少子查询内的 group by,join操作
5.hive的分区分桶的区别以及工作中如何选择
partitioned by分区是以字段的形式在表结构中存在,该字段不存放实际的数据内容,是虚拟字段,每个分区以文件夹的形式单独存在表文件夹的目录下。
clustered by 桶是更为细粒度的数据范围划分,是对某一列(真实存在的列)进行桶的划分,分桶之前要执行命令下hive.enforce.bucketiong=true;hive.enforce.bucketiong=true; Hive采用对列值哈希,然后除以桶的个数求余的方式决定该条记录存放在哪个桶当中。
场景选择:
每天会生成大量的日志,导致数据表的内容巨大,在查询时进行全表扫描耗费的资源非常多,这个情况下,我们可以按照日期对数据表进行分区,不同日期的数据存放在不同的分区,在查询时只要指定分区字段的值就可以直接从该分区查找。
相同分区下有大量小文件的时候采用分桶,更高效
6.hive内部表和外部表的区别,应用中如何选择?
创建内部表时,会将数据移动到数据仓库指向的路径;若创建外部表,仅记录数据所在的路径,不对数据的位置做任何改变。
内部表删除表时:在删除表的时候,内部表的元数据和数据会被一起删除, 而外部表只删除元数据,不删除数据。这样外部表相对来说更加安全些,数据组织也更加灵活,方便共享源数据。
外来采集的数据一般使用外部表,避免源数据被错误删除,内部计算创建的表建成内表。
7.hive常用函数
round函数取整。
UNIX时间戳转日期函数: from_unixtime
获取当前UNIX时间戳函数: unix_timestamp
日期时间转日期函数: to_date
CASE when 条件判断
字符串连接函数:concat
字符串截取函数:substr,substring
窗口函数 row_number、rank
8.hive的udf(自定义函数)的实现过程
第一步:引入依赖hive-exec
第二步:自定义类继承UDF类,实现一个或多个evaluate,然后将项目打成jar包,然后把jar包上传到hdfs上
第三步:在hive的sessiono上add jar,然后使用ddl创建自定义函数名,用as指向我们定义的类型:create function function_name as 'name.of.my.udfsclass'
9.hive如何实现topN
sort by limit N ,order by limit N
分组内排序 row_number() OVER (partition by COL1 order by COL2 desc )
10.hql脚本是如何接受参数的
${xxx}}
11.对zookeeper的理解
分布式服务框架,解决分布式集群中数据一致性问题,保证集群的高可用
用来监控和维护所存储的数据的状态变化
统一命名
统一配置
集群管理, leader Election选举功能
12.hbase的hmaster和hregionserver的作用各是什么
hmaster管理hregionserver实现负载均衡,给每一个server分配HRegion,负责失效的region的重新分配,管理namespace和table的元数据。
hregionserver存放和管理本地HRegion,文件的切片,读写HDFS,管理Table中的数据,Client直接通过HRegionServer读写数据。
13.hbase的行健设计
1.长度原则(rowkey的长度尽量限定在100字节以内,定长,8字节的整数倍)
在定长上,如果是字符串类型,空余的字节可以在右边补:0x1F,如果是数值类型,空余的字节可以在左边补:0x00。
2.散列原则(不散列容易造成热点访问)
1.散列的数据内容需要添加在hbase rowkey的高位上
2.散列的实现方式:对顺序的数据求hash值或者求md5值,然后生成uuid
3.对原顺序的数据进行定长逆向后作为散列值
3.唯一性原则
4.业务中经常用作查询条件的列放在rowkey上
14.hbase的协处理器
创建二级索引 便于进行简单的排序、求和、计数等操作,轻易建立二次索引、复杂过滤器(谓词下推)以及访问控制等。
协处理器有两种: observer 和 endpoint
Observer 类似于传统数据库中的触发器,当发生某些事件的时候这类协处理器会被 Server 端调用。
Endpoint 协处理器类似传统数据库中的存储过程,客户端可以调用这些 Endpoint 协处理器。
observer协处理器写法:
1.定义一个类,继承 BaseRegionObserver,重写其prePut方法,在prePut方法里面获取当前正在被put的数据,然后取出name值当做rowkey,取出rowkey当做列名称插入到w_user_name_index表中。
2.把代码打成jar包,放入hbase的classpath中,或者放到hdfs上
3.通过表的属性把这个协处理器配置到hbase表上
15.HBase容错性
1、Master容错机制
当master节点挂掉时,Zookeeper重新选择一个新的Master,无Master过程中,数据读取仍照常进行;无Master过程中,region切分、负载均衡等无法进行;
2、RegionServer容错
RegionServer会定时向Zookeeper汇报心跳,如果一旦时间内未出现心跳,Master将该RegionServer上的Region重新分配到其他RegionServers上,失效服务器上“预写”日志由主服务器进行分割并派送给新的RegionServer。
3、Zookeeper容错
Zookeeper是一个可靠地服务,一般配置3或5个Zookeeper实例。
16.flume的拦截器和选择器的作用
拦截器:Source读取events发送到Sink的时候,在events header中加入一些有用的信息,或者对events的内容进行过滤,完成初步的数据清洗
选择器:决定Source接收的一个特定事件写入哪些Channel
17.flume常用的flume的sink和source类型
常用Source如下:
Avro Source:监听在agent的某个网络端口上等待接受数据并且采集,网络协议是avro的协议,当配置agent链式集成的时候一般用avro类型的source。
Spooling Directory Source:监听一个文件夹,当这个文件夹下有新的文件放入进来的时候,采集这个文件的内容作为数据内容
限制1,文件进入到被监听文件夹后就不允许再被编辑了
限制2,文件夹放入的文件不能重名
Taildir Source:监听多个文件,当这些文件中有新的内容出现时,会近实时的被flume采集,新增的内容就是被采集的内容
Kafka Source:从kafka里获取数据,作为采集内容
NetCat source:测试时常用,和avro source的采集过程类似,只不过是采用tcp或udp协议来传输被采集的数据
常用sink如下:
HDFS Sink:把采集到的数据存放到hdfs上
Hive Sink:把采集到的数据存放到hive中
HBaseSinks:把数据采集到hbase中
Kafka Sink:把采集到的数据存放到kafka中
Avro Sink:把数据以avro的协议发送出去,一般用于链式集成多个agent的场景下
Logger Sink:用来测试和调试
18.sqoop的架构原理
把用户的操作转换成map任务然后发布到yarn上进行分布式的执行,从而完成对大数据的迁移。
sqoop2引入了sqoop server(具体服务器为tomcat),对connector实现了集中的管理
sqoop2:create link...
sqoop1的命令:sqoop-import,sqoop-export
19.hbase常用过滤器
1.比较过滤器
底层的过滤器,可以通过对hbase表扫数据时添加扫描限定条件从而获取想要的数据内容
比较过滤器是一种专门的用于比较的过滤器,通过实现比较运算符与比较器,来实现用户的需求
RowFilter,对rowkey进行过滤的过滤器,满足条件的整行数据都会被提取
ValueFilter,对列值进行比较查询的过滤器,只有满足该条件的单元格数据才会被提取
QualifierFilter,对满足列成员名称的数据提取出来,只有该列成员的列名称满足条件的数据会被提取
2.专有过滤器
是对比较过滤器的封装,是比较过器的简写
PrefixFilter,相当于,过滤器:RowFilter
比较器:BinaryPrefixComparator
操作符:EQUAL
ColumnPrefixFilter,相当于,过滤器:QualifierFilter
比较器:BinaryPrefixComparator
操作符:EQUAL
5.hbase的二级索引
1.索引是一种数据
2.它是排序的
3.他要存储索引值和对应的数据快速定位的地址,在原表有数据进入的时候,同时把相应的索引数据存储到索引表(实时更新)
如果原表已经有部分数据,则使用mapreduce对原数据进行批量提取,并以索引的形式导入到索引表(批量更新),在所有操作原表的代码里面,添加操作索引表的代码
华为的二级索引:1) 保证主表和索引表在同一个regionserver上(通过自定义的balancer实现) 2) 使用coprocessor实现索引表的创建和插入
21.spark的常用api方法
map :一个输入元素对应一个输出元素。每一个元素都会经过map的算子被计算
mapPartitions:每一个partition作为一个整体经过mappartition算子被计算(效率更高)
flatMap:一个输入对应多个输出元素
filter:过滤rdd的元素,留下符合条件的数据。每个元素,经过算子输出是true就会被留下,如果是false的话就会被排掉
数据聚合
action:
reduce:不需要初值,算子的输入和输出类型要保持一致
fold:需要初值,算子的输入和输出类型要保持一致
aggregate:需要初值,算子的输入和输出类型可以不一致
分组聚合函数:
transformation:
下面三个聚合函数的聚合都有两个过程,1:partition内部聚合,2:partition之间的聚合
reduceByKey:根据key值对pairrdd的value进行分组聚合,不需要聚合的初始值,但是要求聚合的结果值必须要和kvrdd的value的类型保持一致。reducebykey只接受一个算子,这个算子要同时被用于partition内部聚合和partition之间的聚合,所以,这个要求这个算子必须满足两个输入参数的地位要是对等关系。reducebykey值适合进行累加之类的计算。
foldByKey:foldbykey除了比reducebykey多了一个初值之外,reducebykey的限制,它一样具有。
aggregateByKey:对分组聚合没有太多的限制几乎可以满足所有的聚合,该方法接受三个参数,一个初始值和两个算子,第一个算子是用于分区内的聚合过程(会用到初始值),第二个算子是用于分区间的聚合(不会用到初始值)。
combineByKey:对分组聚合没有太多的限制几乎可以满足所有的聚合,该方法接受三个参数,三个参数都是算子,第一个算子用于初始值的计算过程.这个算子是会作用于每一个分区的第一个元素,第二个算子用于分区内的聚合过程(要使用到第一个算子执行结果),第三个算子是用于分区间的聚合。
groupByKey:对数据按照key值进行合并,把一个rdd下某个key值相同的所有的value合并成一个集合对象,并和原key形成一个新的kv
action:
foreach
foreachPartition
22.reducebykey,combinebykey,aggregatebykey的区别
reduceByKey:根据key值对pairrdd的value进行分组聚合,不需要聚合的初始值,但是要求聚合的结果值必须要和kvrdd的value的类型保持一致。reducebykey只接受一个算子,这个算子要同时被用于partition内部聚合和partition之间的聚合,所以,这个要求这个算子必须满足两个输入参数的地位要是对等关系。reducebykey值适合进行累加之类的计算。
aggregateByKey:对分组聚合没有太多的限制几乎可以满足所有的聚合,该方法接受三个参数,一个初始值和两个算子,第一个算子是用于分区内的聚合过程(会用到初始值),第二个算子是用于分区间的聚合(不会用到初始值)。
combineByKey:对分组聚合没有太多的限制几乎可以满足所有的聚合,该方法接受三个参数,三个参数都是算子,第一个算子用于初始值的计算过程.这个算子是会作用于每一个分区的第一个元素,第二个算子用于分区内的聚合过程(要使用到第一个算子执行结果),第三个算子是用于分区间的聚合。
23.map,mappartition的区别,谁的效率更高
map:一个输入元素对应一个输出元素。每一个元素都会经过map的算子被计算
mapPartitions:每一个partition作为一个整体经过mappartition算子被计算(效率更高)
24.宽依赖和窄依赖的区别
窄依赖:父rdd的一个分区的数据进行计算只流向子rdd的一个分区,不会产生shuffler
宽依赖:父rdd的一个分区的数据计算时会流向子rdd的多个分区,会产生shuffler
25.cache和persist的区别,和应用场景
当一个rdd会被后续的很多计算进行使用的时候,把这个rdd放在缓存中会提高程序的运行效率
cache:把数据缓存在内存中,是persist的一种, cache只能把数据缓存到内存中。
persist:persist是可以根据缓存的级别自定义配置,接受StorageLevel级别来决定把数据缓存在内存中或者缓存在磁盘上,如果不传参数就是默认缓存在内存中。
26.kafka的架构原理,如何实现分布式的,如何实现高吞吐的
zookeeper:集群协调管理配置工具。kafka的集群的形成和集群的基本配置信息,以及kafka的元数据信息,都保存在zookeeper中。kafka的broker连接信息也保存在zookeeper中。
Broker:kafka的每一个服务节点都被称作broker,kafka集群就是由若干个broker构成的一个服务整体,broker节点是一个逻辑上的概念(一个broker就是指一台机器上的一个进程),不是物理上的节点。
Topic:数据的划分类别,如果把kafka认为是一个数据的话,topic就是表的概念,它可以做数据隔离,类似redis上称作的channel频道。
Partition:kafka的分布式方式,一个topic可以划分成多个partition,不同的partition负责不同的数据读写请求。
Replication:kafak的容错手段,每一个partition有若干个replication,多个replication分别由不同的broker来进行负责。一个parttion的多个replicition中在某个时间点只有一个是对外提供读写服务的,这个replication被称作leader,其余的replication被称作follower,follower主动同步leader的数据。
Producer:生产者(客户端),主要负责把数据发送至kafka,producer可以随意的和任意的broker来对接。
Consumer:消费者(客户端),主要是负责取出kafka中的数据进行消费处理。consumer也可以连接任意的broker。
Consumer Group:消费组,保证kafka消费不会重复,它是被存储在kafka服务端的一个名称,每个comsumer必须属于某个消费组,不同组的消费者之间消费的数据是可以重复的,同一个消费组下的多个消费者之间,他们消费的数据是完全不会重复的,这点是kafka要保证的。
Offset:kafka的offset值上都有每一个topic的被消费信息,被哪个组消费,被哪个组的consumer消费,记录消费的位置。
kafka如何实现高吞吐的:
顺序读写,零拷贝,文件分区再分段,批量发送,数据压缩
kafka如何实现分布式的:
kafka集群在每一个节点都部署一个broker,通过zookeeper来协调管理
producer、consumer、broker三者通过zookeeper管理协调请求和转发,这其间的连接都是需要zookeeper来进行分发的。这样有了zookeeper之后,producer产生了数据,会先通过zookeeper找到broker,然后把数据存放进broker中;consumer如果要消费数据,会先通过zookeeper找到对应的broker,然后进行消费。
27.SPARK广播变量和累加器的应用场景
广播变量:广播变量是在driver上声明,在executor上使用的一些变量数据,广播变量对executor来说是只读的。
使用步骤:1.在driver上声明广播变量。2.在executor执行的算子中使用这个广播变量。工作过程中,经常在两张表关联的时候使用广播变量。
场景:spark上在对两个rdd进行关联的时候,如果一个rdd的数据量很小,一个rdd的数据量很大,可以使用广播变量来把关联过程变成map端关联,把小表的数据变成广播变量,广播给每一个加载大表rdd的executor。
累加器:在driver上声明,在executor进行累加记数,累加器对executor来说是只写。
使用步骤:1.driver上声明累加器。2.在executor上对累加器进行累加数据处理。3.在driver上读取并得到累加结果。
场景:当在工作过程中需要一些全局计数类型的聚合的时候,可以考虑使用累加器来替代rddapi方法完成聚合。这种方式可以减少job的数量提高spark的执行效率。
28.DataFrame和dataset的区别
DataFrame多了数据的结构信息,即schema。RDD是分布式的 Java对象的集合。DataFrame是分布式的Row对象的集合。
Dataset中的每一个元素可以是任意的类型,而dataframe是一种更加具体的dataset,dataframe中每一个元素必须是Row的对象,Row在声明的时候初始化方法跟Tuple一样,一个row里面可以放多个数据,位置是有序的,多个数据之间可以是不同的数据类型,在取值的时候row和array 、list类似,使用小括号以位置标识作为参数来取值
val row = Row(1,"a",true,3.14)
row(0)
row(1)
dataset可以通过调用toDF的方法转换成dataframe,dataset数据以编码的二进制形式被存储,不需要反序列化就可以执行sorting、shuffle等操作。
29.spark和hadoop的区别
解决问题的层面不一样
首先,Hadoop和Apache Spark两者都是大数据框架,但是各自存在的目的不尽相同。Hadoop实质上更多是一个分布式数据基础设施: 它将巨大的数据集分派到一个由普通计算机组成的集群中的多个节点进行存储,意味着您不需要购买和维护昂贵的服务器硬件。同时,Hadoop还会索引和跟踪这些数据,让大数据处理和分析效率达到前所未有的高度。Spark,则是那么一个专门用来对那些分布式存储的大数据进行处理的工具,它并不会进行分布式数据的存储。
Hadoop除了提供为大家所共识的HDFS分布式数据存储功能之外,还提供了叫做MapReduce的数据处理功能。所以这里我们完全可以抛开Spark,使用Hadoop自身的MapReduce来完成数据的处理。相反,Spark也不是非要依附在Hadoop身上才能生存。但如上所述,毕竟它没有提供文件管理系统,所以,它必须和其他的分布式文件系统进行集成才能运作。这里我们可以选择Hadoop的HDFS,也可以选择其他的基于云的数据系统平台。但Spark默认来说还是被用在Hadoop上面的,毕竟,大家都认为它们的结合是最好的。
30.spark窗口计算的三个时间间隔
Reducebykeyandwindow
Groupbykeyandwindow
窗口长度 它决定一次计算过程数据的范围,必须是微批次的整数倍
滑动间隔 它决定两次窗口计算之间的时间间隔,默认等于微批次的时间,必须是微批次时间的整数倍
累计计算:state
streamingcontext要开启checkpoint
在进行累计计算时,最好先聚合再更新累计值
31.spark的容错如何实现的
记录数据的更新,数据检查点
Lineage:
RDD的Lineage记录的是粗颗粒度的特定数据Transformation操作(如filter、map、join等)行为。当这个RDD的部分分区数据丢失时,它可以通过Lineage获取足够的信息来重新运算和恢复丢失的数据分区
checkpoint:
设置检查点:sc.setCheckpointDir("/path") 。做lineage机制的辅助手段,在lineage链过长时可以在中间需要的地方设置检查点,把内存中的变化刷新到持久存储,斩断依赖链。在Lineage足够长,存在宽依赖的情况下,对Shuffle Dependency加Checkpoint是最物有所值的,可以节约大量的系统资源。
在以下两种情况下,RDD需要加检查点。
1.DAG中的Lineage过长,如果重算,则开销太大(如在PageRank中)。
2.在宽依赖上做Checkpoint获得的收益更大。
32.spark的优化
缓存,累加器和广播变量可以优化spark程序。
当一个rdd会被后续的很多计算进行使用的时候,把这个rdd放在缓存中会提高程序的运行效率。
cache:把数据缓存在内存中。
persist:接受StorageLevel级别来决定把数据缓存在内存中或者缓存在磁盘上。如果不传参数就是缓存在内存中
原则一:避免创建重复的RDD
原则二:尽可能复用同一个RDD
原则三:对多次使用的RDD进行持久化
原则四:尽量避免使用shuffle类算子
原则五:使用map-side预聚合的shuffle操作
原则六:使用高性能的算子
原则七:广播大变量
原则八:使用Kryo优化序列化性能
原则九:优化数据结构