陵薮市朝

一、HDFS

1. HDFS的读流程

  1.  客户端向NameNode发起读数据请求
  2.  NameNode响应请求并告诉客户端要读的文件的数据块位置(存在哪个DataNode上);
  3.  客户端到对应DataNode读取数据,当数据读取到达末端,关闭与这个DataNode的连接,并查找下一个数据块,直到文件数据全部读完;
  4.  最后关闭输出流。

2. HDFS的写流程

  1.     客户端向NameNode发起写数据请求;
  2.  NameNode相应请求(NameNode会检查要创建的文件是否已经存在,创建者是否有权限,成功会创建一个记录,失败会报异常); 
  3.  客户端将文件进行切片(分成数据块),然后上传数据块,按照一个一个的形式进行发送,每个数据块都要写到三个DataNode上;
  4.  成功后DataNode会返回一个确认队列给客户端,客户端进行效验,然后客户端上传下一个数据块到DataNode,直到所有数据块写入完成;
  5.  当所有数据块全部写入成功后,客户端会向NameNode发送一个反馈并关闭数据流。

3. Hadoop有哪些配置文件?

core-site.xml hdfs-site.xml mapred-site.xml yarn-site.xml slaves container-executor.cfg(会默认禁止root等用户提交任务)

4. 小文件过多会造成什么影响?

因为文件的存放位置数据(元数据)存在于NameNode的内存,1个文件块,占用namenode内存大概150-200字节,小文件过多,对nn负荷比较大。

解决方案:

  1. 采用har归档方式,将小文件归档
  2. 采用CombineTextInputFormat
  3. 有小文件场景开启JVM重用;如果没有小文件,不要开启JVM重用,因为会一直占用使用到的task卡槽,直到任务完成才释放。

    JVM重用可以使得JVM实例在同一个job中重新使用N次,N的值可以在Hadoop的mapred-site.xml文件中进行配置。通常在10-20之间

5. block为什么设置成128M,为什么不建议设置太大,或者太小?

block大小设置原则:

1. 减少硬盘寻道时间:

2. 减少NameNode内存消耗:NameNode需要在内存FSImage文件中记录DataNode中数据块信息,若block size太小,那么需要维护的数据块信息会更多

3. map崩溃问题:若Map任务崩溃,重新启动执行需要重新加载数据,数据块越大,数据加载时间将越长,恢复时间越长。

4. 网络传输问题: 在数据读写计算的时候,需要进行网络传输.如果block过大会导致网络传输时间增长,程序卡顿/超时/无响应.

如果块设置过大:

    第一点: 从磁盘传输数据的时间会明显大于寻址时间,导致程序在处理这块数据时,变得非常慢;

    第二点: mapreduce中的map任务通常一次只处理一个块中的数据,如果块过大运行速度也会很慢

    第三点: 在数据读写计算的时候,需要进行网络传输.如果block过大会导致网络传输时间增长,程序卡顿/超时/无响应. 任务执行的过程中拉取其他节点的block或者失败重试的成本会过高.

    第四点: namenode监管容易判断数据节点死亡.导致集群频繁产生/移除副本, 占用cpu,网络,内存资源.

如果块设置太小:

    第一点: 存放大量小文件会占用NameNode中大量内存来存储元数据

    第二点: 文件块过小,寻址时间增大,导致程序一直在找block的开始位置

为什么设置为128M:

时间和空间的权衡,磁盘的传输速度大概在100M,寻址时间大概在1s,而且千兆网卡传输速度在100M/s 所以大概为100M

6. namenode对元数据的管理

namenode对数据的管理采用了三种存储形式:

  • 内存元数据(NameSystem)

  • 磁盘元数据镜像文件(fsimage镜像)

  • 数据操作日志文件(可通过日志运算出元数据)(edit日志文件)

7. checkpiont 触发条件?

每隔一段时间,会由secondary namenode将namenode上积累的所有edits和一个最新的fsimage下载到本地,并加载到内存进行merge(这个过程称为checkpoint

  • 两次检查点创建之间的固定时间间隔,默认3600,即1小时。
  • 检查的事务数量。若检查事务数达到这个值,也触发一次

8. DFSZKFailoverController的作用?

它是一个守护进程,它负责和ZK通信,并且时刻检查NameNode的健康状况。它通过不断的ping,如果能ping通,则说明节点是健康的。然后ZKFC会和ZK保持一个持久通话,及Session对话,并且ActiveNode在ZK里面记录了一个"锁",这样就会Prevent其它节点成为ActiveNode,当会话丢失时,ZKFC会发通知给ZK,同时删掉"锁",这个时候其它NameNode会去争抢并建立新的“锁”,这个过程叫ZKFC的选举

9. MapReduce哪里使用了combiner?

combiner的作用是在Map端把同一个key的键值对合并在一起并计算

  • 数据在环形缓存区根据分区排序完成,在溢写文件之前会执行一次combiner
  • 多个溢写文件在进行merge合并时,也会触发一次combiner

10. MapReduce中partition的作用?

partition的主要作用将map阶段产生的所有kv对分配给不同的reducer task处理,可以将reduce阶段的处理负载进行分摊。

HashPartitioner是mapreduce的默认partitioner。

  • 当map输出的时候,写入缓存之前,会调用partition函数,计算出数据所属的分区,并且把这个元数据存储起来。
  • 把属与同一分区的数据合并在一起。

11. MapReduce中map,reduce数量如何决定,怎么配置?

1. map数量

  • 默认map个数

(1)如果不进行任何设置,默认的map个数是和blcok_size相关的。

 default_num = total_size / block_size;

(2)用户指定mapreduce.map.tasks

exp_num = max(exp_num, default_num)

(3)获取分片大小mapreduce.min.split.size 

split_max_size = max(mapreduce.min.split.size , block_size)

(4) 获取分片个数

split_num = total_size / split_max_size

(5) 获取真实的map个数

real_num = min(split_num, exp_num)

  • 如果想增加map个数,则设置mapred.map.tasks 为一个较大的值。减少mapred.min.split.size的值
  • 如果想减小map个数,则设置mapred.min.split.size 为一个较大的值。减小mapred.map.tasks 为一个较小的值。

2. reduce数量

  • 默认为-1,代表系统根据需要自行决定reduce个数(根据一个reduce能够处理的数据量来决定)
  • 手动设置

12. MapReduce优化

数据输入:

  • 在进行map任务前,合并小文件,大量的小文件会产生大量的map任务
  • 采用combineTextInputformat来作为输入

Map阶段:

  • 减少溢写(spill)次数:io.sort.mb 和 .sort.spill.percent 增大内存上限和溢写百分比
  • 减少合并(merge)次数:调整io.sort.factor ,增大merge文件数目,减少merge次数
  • 在map后,再不影响业务逻辑的情况下,先进行combiner处理

Reduce阶段:

  • 设置合理的map和reduce数量:设置太少导致task任务等待,延长处理时间,太多会导致任务间资源竞争
  • 增加每个Reduce去Map中拿数据的并行数
  • 集群性能可以的前提下,增大 Reduce 端存储数据内存的大小。

I/O传输:

  • 采用数据压缩的方式,减少网络 IO 的的时间。安装 Snappy 和 LZOP 压缩编码器。
  • 使用orc,parquet,sequenceFile等文件格式

整体:

  • MapTask 默认内存大小为 1G,可以增加 MapTask 内存大小为 4-5g
  • ReduceTask 默认内存大小为 1G,可以增加 ReduceTask 内存大小为 4-5g
  • 可以增加 MapTask 的 cpu 核数,增加 ReduceTask 的 CPU 核数
  • 增加每个 Container 的 CPU 核数和内存大小
  • 调整每个 Map Task 和 Reduce Task 最大重试次数

 

13. 用mapreduce怎么处理数据倾斜问题?

数据倾斜:map /reduce程序执行时,reduce节点大部分执行完毕,但是有一个或者几个reduce节点运行很慢,导致整个程序的处理时间很长,这是因为某一个key的条数比其他key多很多(有时是百倍或者千倍之多),这条key所在的reduce节点所处理的数据量比其他节点就大很多,从而导致某几个节点迟迟运行不完,此称之为数据倾斜。

1)提前在map进行combine,减少传输的数据量

在Mapper加上combiner相当于提前进行reduce,即把一个Mapper中的相同key进行了聚合,减少shuffle过程中传输的数据量,以及Reducer端的计算量。

如果导致数据倾斜的key大量分布在不同的mapper的时候,这种方法就不是很有效了。

2)导致数据倾斜的key 大量分布在不同的mapper

(1)局部聚合加全局聚合。

第一次在map阶段对那些导致了数据倾斜的key 加上1到n的随机前缀,这样本来相同的key 也会被分到多个Reducer中进行局部聚合,数量就会大大降低。

第二次mapreduce,去掉key的随机前缀,进行全局聚合。

思想:二次mr,第一次将key随机散列到不同reducer进行处理达到负载均衡目的。第二次再根据去掉key的随机前缀,按原key进行reduce处理。

这个方法进行两次mapreduce,性能稍差。

(2)增加Reducer,提升并行度
JobConf.setNumReduceTasks(int)

(3)实现自定义分区

根据数据分布情况,自定义散列函数,将key均匀分配到不同Reducer

14. Hadoop高可用HA模式

HDFS高可用原理:

Hadoop HA(High Available)状态分别是Active和Standby. Standby Namenode作为热备份,从而允许在机器发生故障时能够快速进行故障转移,同时在日常维护的时候使用优雅的方式进行Namenode切换。Namenode只能配置一主一备,不能多于两个Namenode。

主Namenode处理所有的操作请求(读写),维护尽可能同步的状态,为了使Standby Namenode与Active Namenode数据保持同步,两个Namenode都与一组Journal Node进行通信。当主Namenode进行任务的namespace操作时,都会确保持久会修改日志到Journal Node节点中Standby Namenode持续监控这些edit,当监测到变化时,将这些修改同步到自己的namespace。

当进行故障转移时,Standby在成为Active Namenode之前,会确保自己已经读取了Journal Node中的所有edit日志,从而保持数据状态与故障发生前一致。

确保任何时刻只有一个Namenode处于Active状态非常重要,否则可能出现数据丢失或者数据损坏。当两台Namenode都认为自己的Active Namenode时,会同时尝试写入数据(不会再去检测和同步数据)。为了防止这种脑裂现象,Journal Nodes只允许一个Namenode写入数据,内部通过维护epoch数来控制,从而安全地进行故障转移。

二、YARN

 1. 集群资源分配参数(项目中遇到的问题)

集群有30台机器,跑mr任务的时候发现5个map任务全都分配到了同一台机器上,这个可能是由于什么原因导致的吗?

解决方案:yarn.scheduler.fair.assignmultiple 是否允许NodeManager一次分配多个容器 这个参数 默认是开的,需要关掉

 2. yarn的几种调度器

FIFO: 单队列,先进先出,(生产环境一般不用)

CapacityScheduler(容量调度):多队列,队列内部任务先进先出 CDH默认

FairScheduler(公平调度):支持多队列,保证每个任务公平享有队列资源。apache 和 HDP 默认

3. yarn提交任务的流程

  1. 用户向YARN 中提交应用程序, 其中包括ApplicationMaster 程序、启动ApplicationMaster 的命令、用户程序等。

  2. ResourceManager 为该应用程序分配第一个Container, 并与对应的NodeManager 通信,要求它在这个Container 中启动应用程序的ApplicationMaster。

  3. ApplicationMaster 首先向ResourceManager 注册, 这样用户可以直接通过ResourceManage 查看应用程序的运行状态,然后它将为各个任务申请资源,并监控它的运行状态,直到运行结束,即重复步骤4~7。

  4. ApplicationMaster 采用轮询的方式通过RPC 协议向ResourceManager 申请和领取资源。

  5.  一旦ApplicationMaster 申请到资源后,便与对应的NodeManager 通信,要求它启动任务。

  6. NodeManager 为任务设置好运行环境(包括环境变量、JAR 包、二进制程序等)后,将任务启动命令写到一个脚本中,并通过运行该脚本启动任务。

  7. 各个任务通过某个RPC 协议向ApplicationMaster 汇报自己的状态和进度,以让ApplicationMaster 随时掌握各个任务的运行状态,从而可以在任务失败时重新启动任务。在应用程序运行过程中,用户可随时通过RPC 向ApplicationMaster 查询应用程序的当前运行状态。

  8.  应用程序运行完成后,ApplicationMaster 向ResourceManager 注销并关闭自己。

4. yarn中的 vcores 是什么意思?

在yarn中使用的是虚拟CPU,考虑到不同节点的CPU性能可能不同每个CPU具有的计算能力不一,比如某个物理CPU的计算能力可能是另外一个物理CPU的2倍,这时候,你可以通过为第一个物理CPU多配置几个虚拟CPU弥补这种差异。用户提交作业时,可以指定每个任务需要的虚拟CPU个数。

三、HIVE

1. insert into 和 override write区别?

insert into:将数据写到表中

override write:覆盖之前的内容

2. order by 、sort by、disturb by 、cluster by 区别?

order by(全局排序)

order by会对输入做全局排序,因此只有一个Reducer(多个Reducer无法保证全局有序),然而只有一个reducer,会导致当输入规模较大时,消耗较长的计算时间。

sort by (分区内排序)

不是全局排序,其在数据进入reducer前完成排序,也就是说它会在数据进入reduce之前为每个reducer都产生一个排序后的文件。因此,如果用sort by进行排序,并且设置mapreduce.job.reduces>1,则sort by只保证每个reducer的输出有序,不保证全局有序

distribute by(数据分发)

distribute by是控制在map端如何拆分数据给reduce端的。类似于MapReduce中分区partationer对数据进行分区

hive会根据distribute by后面列,将数据分发给对应的reducer,默认是采用hash算法+取余数的方式

sort by为每个reduce产生一个排序文件,在有些情况下,你需要控制某写特定的行应该到哪个reducer,这通常是为了进行后续的聚集操作。distribute by刚好可以做这件事。因此,distribute by经常和sort by配合使用。

cluster by

cluster by除了具有distribute by的功能外还兼具sort by的功能。但是排序只能是升序排序,不能指定排序规则为ASC或者DESC。

  1. order by 是全局排序,可能性能会比较差;

  2. sort by分区内有序,往往配合distribute by来确定该分区都有那些数据;

  3. distribute by 确定了数据分发的规则,满足相同条件的数据被分发到一个reducer;

  4. cluster by 当distribute by和sort by 字段相同时,可以使用cluster by 代替distribute by和sort by,但是cluster by默认是升序,不能指定排序方向;

  5. sort by limit 相当于每个reduce 的数据limit 之后,进行order by 然后再limit ;

3. 用hive创建表有几种方式?

hive建表有三种方式

  • 直接建表法

  • 查询建表法(通过AS 查询语句完成建表:将子查询的结果存在新表里,有数据一般用于中间表)

  • like建表法(会创建结构完全相同的表,但是没有数据)

4. union all和union的区别

union 去重

union all 不去重

5. hive的优化

数据的压缩与存储格式

  数据存储格式采用orc/parquet 列式存储格式

  压缩格式采用snappy 或者lzo lzo支持压缩文件切分

合理利用分区分

  分区是将表的数据在物理上分成不同的文件夹,以便于在查询时可以精准指定所要读取的分区目录,从来降低读取的数据量

  分桶是将表数据按指定列的hash散列后分在了不同的文件中,将来查询时,hive可以根据分桶结构,快速定位到一行数据所在的分桶文件,从来提高读取效率

hive参数优化

  开启任务并行执行 set hive.exec.parallel=true;

  设置jvm重用 特别是很难避免小文件的场景或者task特别多的场景,这类场景大多数执行时间都很短。jvm的启动过程可能会造成相当大的开销,尤其是执行的job包含有成千上万个task任务的情况。

  调整map切片大小

  调整map tasks个数

  调整每个reduce所接受的数据量大小 set hive.exec.reducers.bytes.per.reducer=500000000; (500M)

  直接设置reduce数量 set mapred.reduce.tasks = 20

  map端聚合,降低传给reduce的数据量 set hive.map.aggr=true

  开启hive内置的数倾优化机制 set hive.groupby.skewindata=true

sql优化

1. where条件优化

优化前(关系数据库不用考虑会自动优化)

select m.cid,u.id from order m join customer u on( m.cid =u.id )where m.dt='20180808';

优化后(where条件在map端执行而不是在reduce端执行)

select m.cid,u.id fromselect * from order where dt='20180818') m join customer u on( m.cid =u.id);

2. count distinct优化

不要使用count (distinct  cloumn) ,使用子查询

select count(1) from (select id from tablename group by id) tmp;

join 优化

Common/shuffle/Reduce JOIN 连接发生的阶段,发生在reduce 阶段, 适用于大表 连接 大表(默认的方式)

Map join :连接发生在map阶段 , 适用于小表 连接 大表
                       大表的数据从文件中读取
                       小表的数据存放在内存中(hive中已经自动进行了优化,自动判断小表,然后进行缓存)

SMB join
   Sort -Merge -Bucket Join  对大表连接大表的优化,用桶表的概念来进行优化。在一个桶内发生笛卡尔积连接(需要是两个桶表进行join)

6. hive的数据倾斜问题

1)怎么产生的数据倾斜?

(1)不同数据类型关联产生数据倾斜

情形:比如用户表中user_id字段为int,log表中user_id字段既有string类型也有int类型。当按照user_id进行两个表的Join操作时。

后果:处理此特殊值的reduce耗时;只有一个reduce任务
默认的Hash操作会按int型的id来进行分配,这样会导致所有string类型id的记录都分配到一个Reducer中。

解决方式:把数字类型转换成字符串类型

select * from users a

left outer join logs b

on a.usr_id = cast(b.user_id as string)

(2)控制空值分布

在生产环境经常会用大量空值数据进入到一个reduce中去,导致数据倾斜。

解决办法:

自定义分区,将为空的key转变为字符串加随机数或纯随机数,将因空值而造成倾斜的数据分不到多个Reducer。

注意:对于异常值如果不需要的话,最好是提前在where条件里过滤掉,这样可以使计算量大大减少

(3)group by

如果是在group by中产生了数据倾斜,是否可以讲group by的维度变得更细,如果没法变得更细,就可以在原分组key上添加随机数后分组聚合一次,然后对结果去掉随机数后再分组聚合

在join时,有大量为null的join key,则可以将null转成随机值,避免聚集

(4)count(distinct)

情形:某特殊值过多

后果:处理此特殊值的 reduce 耗时;只有一个 reduce 任务

解决方式:count distinct 时,将值为空的情况单独处理,比如可以直接过滤空值的行,

在最后结果中加 1。如果还有其他计算,需要进行 group by,可以先将值为空的记录单独处理,再和其他计算结果进行 union。

注意:有时count(distinct) 会比 group by 效率会高,因为group by 会启动2个job,而时间主要浪费在了数据传输,数据磁盘落地和中间任务的创建上,浪费I/O和网络资源,反而count(distinct)效率要高,那么什么时候 group by 比 count(distinct) 效率高呢,一个是发生数据倾斜,另一个是在数据量特别大的时候,因为count(distinct) 只会启动一个reduce任务,有种千军万马过独木桥的感觉,反而group by 会启动两个job任务,会先缩小数据量。

再者,hive3.0 将hive.optimize.countdistinct 设置为true,也能解决数据倾斜问题。

(5)key本身分布不均

可以在key上加随机数,或者增加reduceTask数量

开启数据倾斜时负载均衡

set hive.groupby.skewindata=true;

思想:就是先随机分发并处理,再按照 key group by 来分发处理。

操作:当选项设定为 true,生成的查询计划会有两个 MRJob。

第一个 MRJob 中,Map 的输出结果集合会随机分布到 Reduce 中,每个 Reduce 做部分聚合操作,并输出结果,这样处理的结果是相同的 GroupBy Key 有可能被分发到不同的Reduce 中,从而达到负载均衡的目的;

第二个 MRJob 再根据预处理的数据结果按照 GroupBy Key 分布到 Reduce 中(这个过程可以保证相同的原始 GroupBy Key 被分布到同一个 Reduce 中),最后完成最终的聚合操作。

7. hive小文件问题

小文件的产生有三个地方,map输入,map输出,reduce输出,小文件过多也会影响hive的分析效率:

设置map输入的小文件合并

set mapred.max.split.size=256000000;  
//一个节点上split的至少的大小(这个值决定了多个DataNode上的文件是否需要合并)
set mapred.min.split.size.per.node=100000000;
//一个交换机下split的至少的大小(这个值决定了多个交换机上的文件是否需要合并)  
set mapred.min.split.size.per.rack=100000000;
//执行Map前进行小文件合并
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;

设置map输出和reduce输出进行合并的相关参数:

//设置map端输出进行合并,默认为true
set hive.merge.mapfiles = true
//设置reduce端输出进行合并,默认为false
set hive.merge.mapredfiles = true
//设置合并文件的大小
set hive.merge.size.per.task = 256*1000*1000
//当输出文件的平均大小小于该值时,启动一个独立的MapReduce任务进行文件merge。
set hive.merge.smallfiles.avgsize=16000000

8. hive常用的函数

类型转换

  cast(expr as <type>)

日期函数

  to_date(string timestamp)

  from_unixtime(bigint unixtime, string format)

  date_format(date/timestamp/string ts, string fmt)

  nvl(T value, T default_value)

字符函数:

  concat(string|binary A, string|binary B...)

  concat_ws(string SEP, string A, string B...)

  regexp_replace(string INITIAL_STRING, string PATTERN, string REPLACEMENT)

  split(string str, string pat)

  substr(string|binary A, int start) substring(string|binary A, int start)

9. hive中null是如何存储的

hive在底层数据存储Null默认是‘N’中,是由 alter table name SET SERDEPROPERTIES('serialization.null.format' = 'N'); 参数控制的

 

10. left semi join和left join区别

  • LEFT SEMI JOIN 是 IN/EXISTS 子查询的一种更高效的实现

  • LEFT SEMI JOIN 的限制是, JOIN 子句中右边的表只能在 ON 子句中设置过滤条件,在 WHERE 子句、SELECT 子句或其他地方都不行。

  • 因为 left semi join 是 in(keySet) 的关系,遇到右表重复记录,左表会跳过,而 join 则会一直遍历。这就导致右表有重复值得情况下 left semi join 只产生一条,join 会产生多条,也会导致 left semi join 的性能更高。

  • left semi join 是只传递表的 join key 给 map 阶段,因此left semi join 中最后 select 的结果只许出现左表。因为右表只有 join key 参与关联计算了,而left  join on 默认是整个关系模型都参与计算了

11. 聊聊hive的执行引擎,spark和mr的区别?

 内存 vs 磁盘 ?

spark 和 mapreduce 计算都是发生在内存中,区别在于:Mapreduce 需要将中间计算的结果写入磁盘,然后再读取磁盘,从而导致了频繁的磁盘io

spark则不需要将中间计算结果保存在磁盘,得益于RDD(弹性分布式数据集)和DAG(有向无环图)

DAG记录了job的stage以及在job执行过程中父RDD和子RDD之间的依赖关系。

中间结果能够以RDD的形式存放在内存中,且能够从DAG中恢复,大大减少了磁盘IO。

Shuffle

MapReduce在Shuffle时需要花费大量时间进行排序,排序在MapReduce的Shuffle中似乎是不可避免的

Spark在Shuffle时则只有部分场景才需要排序,支持基于Hash的分布式聚合,更加省时;

多进程模型 vs 多线程模型的区别

MapReduce采用了多进程模型,而Spark采用了多线程模型。

多进程模型的好处是便于细粒度控制每个任务占用的资源,但每次任务的启动都会消耗一定的启动时间。就是说MapReduce的Map Task和Reduce Task是进程级别的,而Spark Task则是基于线程模型的。

mapreduce 中的 map 和 reduce 都是 jvm 进程,每次启动都需要重新申请资源,消耗了不必要的时间(假设容器启动时间大概1s,如果有1200个block,那么单独启动map进程事件就需要20分钟)

Spark则是通过复用线程池中的线程来减少启动、关闭task所需要的开销。

12. Hive的执行流程?

  1. 用户提交查询等任务给Driver。

  2. 编译器获得该用户的任务Plan。

  3. 编译器Compiler根据用户任务去MetaStore中获取需要的Hive的元数据信息。

  4. 编译器Compiler得到元数据信息,对任务进行编译,先将HiveQL转换为抽象语法树,然后将抽象语法树转换成查询块,将查询块转化为逻辑的查询计划,重写逻辑查询计划,将逻辑计划转化为物理的计划(MapReduce), 最后选择最佳的策略。

  5. 将最终的计划提交给Driver。

  6. Driver将计划Plan转交给ExecutionEngine去执行,获取元数据信息,提交给JobTracker或者SourceManager执行该任务,任务会直接读取HDFS中文件进行相应的操作。

  7. 获取执行的结果。

  8. 取得并返回执行结果。

四、HBase

1. RegionServer上部署多少个region合适?

主要的压力来源于:

  1. memStore,因为每个region的每个列簇都有一个memStore,所以region过多,可能导致会频繁触发regionServer级别的阻塞flush,这个时候,基本数据写入服务会被阻塞,而且会带来小文件过多的问题。
  2. RS故障恢复,region的迁移 需要切分的hlog也过多。线程压力大
  3. BlockCache, 在一个jvm下,lru会频繁的进行block置换。
  4. hbase:meta 表维护的region过多,压力有点大。

五、Kafka

 1. 如何优雅的关闭kafka,并且这样的好处是什么?

使用 kill -s term $KAFKA_PID 或者 kill -15 $KAFKA_PID 来进行关闭kafka,kafka程序入口有个钩子函数,待 Kafka 进程捕获终止信号的时候会执行这个关闭钩子中的内容。

好处:

  • 日志同步到磁盘里当重启时,以避免需要做任何的日志恢复。日志恢复需要时间,所以这样可以加快启动。
  • 将所有leader分区服务器移动到其他的副本,并且把每个分区不可用的几毫秒的时间降至更低。

其他更多kafka面试题:

https://www.cnblogs.com/erlou96/p/14401394.html

六、Zookeeper

七、spark

1. spark on Yarn,Yarn cluster 和 Yarn client模式区别:

Yarn cluster模式中,一般用于线上生产。应用程序都作为Yarn框架所需要的主应用程序(Application Master),并通过Yarn资源管理器(Yarn ResourceManager)为其分配的一个随机节点上运行。

Yarnclient模式中,一般用于本地代码调试,因为该模型下Spark上下文(Spark-Context)会运行在本地,如Spark Shell和Shark等。

2. spark常见的算子:

spark算子分为transform 和 action :

Transform :

  1. map
  2. flatmap
  3. mapPartitions
  4. sample(抽样)
  5. groupByKey
  6. reduceByKey
  7. union
  8. distinct
  9. join
  10. sortByKey
  11. repartition
  12.  coalesce

Action:

  1. count(统计个数)
  2. collect(将结果收集到driver,容易oom)
  3. saveAsText
  4. take (提取前n个元素)
  5. first   =  take(1)
  6. reduce -> 将RDD内部的数据集按照顺序两两合并,直到产生最后一个值为止,并将其返回。即首先合并前两个元素,将结果与第三个元素合并,以此类推。
  7. foreach 函数func应用在数据集的每一个元素上,通常用于更新一个累加器,或者和外部存储系统进行交互,例如Redis.

 

3. repartition 和 coalesce 的区别?

1)关系:

两者都是用来改变 RDD 的 partition 数量的repartition 底层调用的就是 coalesce 方法:coalesce(numPartitions, shuffle = true)

2)区别:

repartition 一定会发生 shuffle,coalesce 根据传入的参数来判断是否发生 shuffle

一般情况下增大 rdd 的 partition 数量使用 repartition,减少 partition 数量时使用coalesce

4. map 、flatMap 和 mapPartitions 的区别?

map是对rdd中的每一个元素进行操作;
flatMap函数则是两个操作的集合——正是“先映射后扁平化”:
mapPartitions则是对rdd中的每个分区的迭代器进行操作
 

5. reduceByKey和groupBykey的区别

reduceByKey会传一个聚合函数, 相当于  groupByKey + mapValues

reduceByKey 会有一个分区内聚合,而groupByKey没有  最核心的区别  

结论:reduceByKey有分区内聚合,更高效,优先选择使用reduceByKey。

6. spark读取hdfs文件的分区数

 spark读hdfs文件的分区数由hdfs文件占用的文件块数决定。

例如:如果读取的一个hdfs文件大小为1280MB,可能是存储为10块,那么spark读取这个文件的分区数就是10。

 spark的并行度是同一时刻进行任务计算的task的最大数量。如果分区数超过了并行度,那么就会排队计算。

 比如读取的文件分区数是10,spark任务的并行度是5,同一时刻只会计算5个分区的内容,当某个分区计算完成空出资源之后才会计算其他分区。

7. SparkSession 和 SparkContext 关系

SparkSession是Spark 2.0引如的新概念。
我们通过sparkcontext来创建和操作RDD。对于每个其他的API,我们需要使用不同的context。
例如,对于Streming,我们需要使用StreamingContext;对于sql,使用sqlContext;对于Hive,使用hiveContext。
SparkSession内部封装了sparkContext,所以计算实际上是由sparkContext完成的。

8. 使用 saveAsHadoopFile 时生产 _SUCCESS 文件问题

使用 saveAsHadoopFile 保存文件时,有时候会产生 _SUCCESS 文件。使用下面的设置就可以不产生这个文件:

sparkConf.set(“spark.hadoop.mapreduce.fileoutputcommitter.marksuccessfuljobs”, “false”);

9. 关于 Spark Streaming 中 LocationStrategies 的设置

  • LocationStrategies.PreferBrokers():仅仅在你 spark 的 executor 在相同的节点上,优先分配到存在 kafka broker 的机器上;
  • LocationStrategies.PreferConsistent():大多数情况下使用,一致性的方式分配分区所有 executor 上。(主要是为了分布均匀)
  • LocationStrategies.PreferFixed():如果你的负载不均衡,可以通过这两种方式来手动指定分配方式,其他没有在 map 中指定的,均采用 preferConsistent() 的方式分配;

10. cache和checkPoint的比较

都是做 RDD 持久化的

1.缓存,是在触发action之后,把数据写入到内存或者磁盘中。不会截断血缘关系

(设置缓存级别为memory_only:内存不足,只会部分缓存或者没有缓存,缓存会丢失,memory_and_disk :内存不足,会使用磁盘)

2.checkpoint 也是在触发action之后,执行任务。单独再启动一个job,负责写入数据到hdfs中。(把rdd中的数据,以二进制文本的方式写入到hdfs中,有几个分区,就有几个二进制文件)

3.某一个RDD被checkpoint之后,他的父依赖关系会被删除,血缘关系被截断,该RDD转换成了CheckPointRDD,以后再对该rdd的所有操作,都是从hdfs中的checkpoint的具体目录来读取数据。缓存之后,rdd的依赖关系还是存在的。

 

 

八、Java

1. intern()

String str1=new StringBuilder("58").append("58").toString();

System.out.println(str1.intern() == str1);  // true

String str2=new StringBuilder("ja").append("va").toString();

System.out.println(str2.intern() == str2);  // false

九、linux

1. 找出/data/目录下大于10k的文件,并将其移动到/databak下

find /data -size +10k -exec mv {} /databak ;

2. 设置linux 默认的文件权限

umask 0022  // 文件默认755,文件夹默认644(少一个可执行)

十、杂谈

1. http 错误状态码:

  1. 500 服务器内部错误,代码级别的
  2. 502 错误网关 
  3. 403 - 禁止访问
  4. 404 - 无法找到文件

2. kerberos 主备切换,数据同步问题

1. 使用kdb5_util dump 备份kdc数据库

2. 在使用kprop -f /var/kerberos/krb5kdc/kdc.dumpkerberos2.example.com 

  以上命令,可以封装成一个bash,定时运行,即定时更新slave上的database。

3. parquet格式 和 orc格式区别

相同点:都是列式存储,都支持文件索引,都支持压缩

不同点:orc支持acid事务,和update,delete操作,而parquet不支持

原文地址:https://www.cnblogs.com/erlou96/p/14343814.html