大数据面试题(相关知识点罗列)

自述:这篇可能也不完全是 面试题,就是一些知识点的整理。【持续更新中…】

【愿君一路披荆斩棘,觅得心仪大offer】

1、linux的常用的命令:

(1)磁盘管理:
pwd:显示工作目录的绝对路径名称
ls:显示指定工作目录下的内容(列出目前工作目录所含之文件及子目录)
mkdir:用于创建目录
rmdir:删除空的目录
cd:用于切换当前工作目录
(2)文件管理:
touch:用于修改文件或者目录的时间属性,包括存取时间和更改时间。若文件不存在,系统会建立一个新的文件
cp:用于复制文件或目录
rm:删除一个文件或者目录
mv:为文件或目录改名、或将文件或目录移入其它位置
cat:连接文件并打印到标准输出设备上
more:类似 cat ,不过会以一页一页的形式显示
less:与 more 类似,但使用 less 可以随意浏览文件,而 more 仅能向前移动,却不能向后移动,而且 less 在查看之前不会加载整个文件
chmod:控制用户对文件的权限的命令
chown:用于设置文件所有者和文件关联组的命令
chgrp:用于变更文件或目录的所属群组。(与 chown 命令不同,chgrp 允许普通用户改变文件所属的组,只要该用户是该组的一员)
(3)系统管理:
useradd:用来建立用户账号。账号建好之后,再用 passwd 设定账号的密码。而可用 userdel 删除账号。使用 useradd 指令所建立的账号,实际上是保存在 /etc/passwd 文本文件中
passwd:用来更改使用者的密码
su:用于变更为其他使用者的身份,除 root 外,需要键入该使用者的密码。(使用权限:所有使用者。)
sudo:以系统管理者的身份执行指令,也就是说,经由 sudo 所执行的指令就好像是 root 亲自执行。(使用权限:在 /etc/sudoers 中有出现的使用者。)
userdel:用于删除用户账号
who:用于显示系统中有哪些使用者正在上面,显示的资料包含了使用者 ID、使用的终端机、从哪边连上来的、上线时间、呆滞时间、CPU 使用量、动作等等。(使用权限:所有使用者都可使用。)
(4)其他命令:
head:用于查看文件的开头部分的内容,有一个常用的参数 -n 用于显示行数,默认为 10,即显示 10 行的内容
tail:用于查看文件的内容,有一个常用的参数 -f 常用于查阅正在改变的日志文件

【详细内容可参考 菜鸟教程的 linux命令大全:https://www.runoob.com/linux/linux-command-manual.html

2、MR、Hive、Spark的词频统计

(1)MR的词频统计:
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import java.io.IOException;

public class WordCount {

    public static void main(String[] args) throws Exception {
        //获取job对象
        //1.新创建配置文件
        Configuration conf = new Configuration();
        conf.set("mapreduce.framework.name","local");
        conf.set("fs.defaultFS","file:///");    //本地模式
      // conf.set("fs.defaultFS", "hdfs://192.168.137.71:8020");    //集群模式

        Job job = Job.getInstance(conf);
        //2.指定驱动类进行打包
        job.setJarByClass(WordCount.class);

        //3.指定Mapper,reducer类
        job.setMapperClass(wcMapper.class);
        job.setReducerClass(wcReducer.class);

        //4.指定mapper输出的数据类型
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(LongWritable.class);

        //5.指定reduce输出的数据类型
        job.setOutputKeyClass(NullWritable.class);
        job.setOutputValueClass(Text.class);

        //6.指定输入的数据路径
        FileInputFormat.setInputPaths(job,new Path("D:\\Test\\spark\\words.txt"));
        FileOutputFormat.setOutputPath(job,new Path("D:\\Test\\1"));

        //8.提交任务并退出
        boolean b = job.waitForCompletion(true);
        System.exit(b?0:1);

    }
}

class wcMapper extends Mapper<LongWritable,Text,Text, LongWritable>{

    @Override
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
        String[] splits = value.toString().split(" ");
        for (String s : splits) {
            context.write(new Text(s),new LongWritable(1L));
        }

    }
}

class wcReducer extends Reducer<Text, LongWritable, NullWritable, Text>{
    @Override
    protected void reduce(Text key, Iterable<LongWritable> values, Context context) throws IOException, InterruptedException {
        long l=0L;
        for (LongWritable value : values) {
            l  ;
        }
        context.write(NullWritable.get(),new Text(key " " l));

    }
}
(2)Hive的词频统计:

① 在服务器,编辑文本 words.txt:

vi words.txt

zhangsan is beijing
zhangsan is running
country
nihao hi love hi

② 进到hive进行建表:

hive> create table wc(txt String) row format delimited fields terminated by '\t';

③ 导数据:

hive> load data local inpath '/root/words.txt' overwrite into table wc;

④ 先查询数据是否导入成功,验证一下:

hive> select * from wc;

⑤ 编写wordCount:

hive>select t1.word,count(t1.word) from (select explode(split(txt,' '))word from wc)t1 group by t1.word;

相关语法:
split----------------> 列变数组
explode--------------> 数组拆分成多行
group by和count------> 对行分组后,求各行出现的次数

⑥ 结果如下,则运行成功:

beijing1
country1
hi2
is2
love1
nihao1
running1
zhangsan2
(3)Spark的词频统计 [scala编写]:
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}

object wordCount {

  def main(args: Array[String]): Unit = {
    val conf: SparkConf = new SparkConf()
    conf.setAppName(s"${this.getClass.getSimpleName}")
    conf.setMaster("local[*]")
    val sc: SparkContext = new SparkContext(conf)

    val sourceRDD: RDD[String] = sc.textFile("D:\\Test\\spark\\words.txt")
    val wordRDD: RDD[String] = sourceRDD.flatMap(_.split(" "))
    val wcRDD: RDD[(String, Int)] = wordRDD.map((_,1)).reduceByKey(_ _)
    wcRDD.collect().foreach(println)

  }
}

3、Hadoop是什么?

Apache Hadoop 为可靠的,可扩展的分布式计算开源框架,用于集群上存储数据和运行应用程序。它为任何类型的数据提供海量存储,巨大的处理能力以及处理几乎无限的并发任务或作业的能力。
包括这些模块:
Hadoop Common:支持其他Hadoop模块的常用工具。
Hadoop分布式文件系统(HDFS™):一种分布式文件系统,可提供对应用程序数据的高吞吐量访问。
Hadoop YARN:作业调度和集群资源管理的框架。
Hadoop MapReduce:一种用于并行处理大型数据集的基于YARN的系统。

上述每个模块有自己独立的功能,而模块之间又有相互的关联。

广义上来说,HADOOP通常是指一个更广泛的概念——HADOOP生态圈

HDFS:分布式文件系统
MAPREDUCE:分布式运算程序开发框架
HIVE:基于大数据技术(文件系统 运算框架)的SQL数据仓库工具
HBASE:基于HADOOP的分布式海量数据库
ZOOKEEPER:分布式协调服务基础组件
Mahout:基于mapreduce/spark/flink等分布式运算框架的机器学习算法库
Oozie:工作流调度框架
Sqoop:数据导入导出工具
Flume:日志数据采集框架

4、Hadoop常用端口号:

dfs.namenode.http-address:50070
dfs.datanode.http-address:50075
SecondaryNameNode辅助名称节点端口号:50090
dfs.datanode.address:50010
fs.defaultFS:8020 或者 9000
yarn.resourcemanager.webapp.address:8088
历史服务器web访问端口:19888

5、ETL是什么?

ETL:是英文Extract-Transform-Load的缩写,用来描述将数据从来源端经过抽取(extract)、转换(transform)、加载(load)至目的端的过程。
    ETL是将业务系统的数据经过抽取、清洗转换之后加载到数据仓库的过程,目的是将企业中的分散、零乱、标准不统一的数据整合到一起,为企业的决策提供分析依据, ETL是BI(商业智能)项目重要的一个环节。

6、Hadoop配置文件以及简单的Hadoop集群搭建:

(1)配置文件:
core-site.xml、hdfs-site.xml、mapred-site.xml、yarn-site.xml
hadoop-env.sh、mapred-env.sh、yarn-env.sh、slaves

(2)简单的集群搭建过程:
JDK安装
配置SSH免密登录
配置hadoop核心文件:
格式化namenode

7、hadoop1.0 和 hadoop2.0的区别:

NameNodes可以通过集群的方式布署,增强了NameNodes的水平扩展能力和可用性;

从mapreduce角度来看:2.0相比于1.0 新增了YARN框架,Mapreduce的运行环境发生了变化。

8、Yarn的Job提交流程:

用户使用客户端向 RM 提交一个任务job,同时指定提交到哪个队列和需要多少资源。用户可以通过每个计算引擎的对应参数设置,如果没有特别指定,则使用默认设置。
    RM 在收到任务提交的请求后,先根据资源和队列是否满足要求选择一个 NM,通知它启动一个特殊的 container,称为 ApplicationMaster(AM),后续流程由它发起。
    AM 向 RM 注册后根据自己任务的需要,向 RM 申请 container,包括数量、所需资源量、所在位置等因素。
    如果队列有足够资源,RM 会将 container 分配给有足够剩余资源的 NM,由 AM 通知 NM 启动 container。
    container 启动后执行具体的任务,处理分给自己的数据。NM 除了负责启动 container,还负责监控它的资源使用状况以及是否失败退出等工作,如果 container 实际使用的内存超过申请时指定的内存,会将其杀死,保证其他 container 能正常运行。
    各个 container 向 AM 汇报自己的进度,都完成后,AM 向 RM 注销任务并退出,RM 通知 NM 杀死对应的 container,任务结束。

9、Yarn的默认调度器、调度器分类、以及他们之间的区别

Hadoop2.7.2默认的资源调度器是 容量调度器
FIFO 、Capacity Scheduler(容量调度器)和Fair Sceduler(公平调度器)。

区别:
FIFO调度器:先进先出,同一时间队列中只有一个任务在执行。
容量调度器:多队列;每个队列内部先进先出,同一时间队列中只有一个任务在执行。队列的并行度为队列的个数。
公平调度器:多队列;每个队列内部按照缺额大小分配资源启动任务,同一时间队列中有多个任务执行。队列的并行度大于等于队列的个数。

10、Hadoop宕机

1)如果MR造成系统宕机。此时要控制Yarn同时运行的任务数,和每个任务申请的最大内存。调整参数:yarn.scheduler.maximum-allocation-mb(单个任务可申请的最多物理内存量,默认是8192MB)
2)如果写入文件过量造成NameNode宕机。那么调高Kafka的存储大小,控制从Kafka到HDFS的写入速度。高峰期的时候用Kafka进行缓存,高峰期过去数据同步会自动跟上。

11、HDFS读流程

1)客户端通过NameNode请求下载文件,NameNode通过查询元数据,找到文件块所在的DataNode地址。返回给客户端
2)客户端根据返回的信息挑选一台datanode(就近原则,然后随机)服务器,请求建立socket流
3)datanode开始发送数据(从磁盘里面读取数据放入流,以packet(包)为单位来做校验)
4)客户端以packet为单位接收,现在本地缓存,然后写入目标文件

12、HDFS写流程

1)概述
客户端要向HDFS写数据,首先要跟namenode通信以确认可以写文件并获得接收文件block的datanode,然后,客户端按顺序将文件逐个block传递给相应datanode,并由接收到block的datanode负责向其他datanode复制block的副本
2)详细步骤解析
①、向namenode请求上传文件,namenode检查目标文件是否已存在,父目录是否存在
②、namenode返回是否可以上传
③、client请求第一个 block该传输到哪些datanode服务器上
④、namenode返回3个datanode服务器ABC
⑤、client请求3台dn中的一台A上传数据(本质上是一个RPC调用,建立pipeline),A收到请求会继续调用B,然后B调用C,将整个pipeline建立完成,逐级返回客户端
⑥、client开始往A上传第一个block(先从磁盘读取数据放到一个本地内存缓存),以packet为单位,A收到一个packet就会传给B,B传给C;A每传一个packet会放入一个应答队列等待应答
⑦、当一个block传输完成之后,client再次请求namenode上传第二个block的服务器。

13、FileInputFormat切片机制

1)简单地按照文件的内容长度进行切片
2)切片大小,默认等于Block大小
3)切片时不考虑数据集整体,而是逐个针对每一个文件单独切片
提示:切片大小公式:max(0,min(Long_max,blockSize))

14、什么是InputSplit?FileInputFormat源码解析(input.getSplits(job))

(1)找到你数据存储的目录。
(2)开始遍历处理(规划切片)目录下的每一个文件
(3)遍历第一个文件ss.txt
a)获取文件大小fs.sizeOf(ss.txt);
b)计算切片大小computeSliteSize(Math.max(minSize,Math.min(maxSize,blocksize)))=blocksize=128M
c)默认情况下,切片大小=blocksize
d)开始切,形成第1个切片:ss.txt—0:128M 第2个切片ss.txt—128:256M 第3个切片ss.txt—256M:300M(每次切片时,都要判断切完剩下的部分是否大于块的1.1倍,不大于1.1倍就划分一块切片)
e)将切片信息写到一个切片规划文件中
f)整个切片的核心过程在getSplit()方法中完成。
g)数据切片只是在逻辑上对输入数据进行分片,并不会再磁盘上将其切分成分片进行存储。InputSplit只记录了分片的元数据信息,比如起始位置、长度以及所在的节点列表等。
h)注意:block是HDFS上物理上存储的存储的数据,切片是对数据逻辑上的划分。
(4)提交切片规划文件到yarn上,yarn上的MrAppMaster就可以根据切片规划文件计算开启maptask个数。

15、MapReduce的Shuffle过程

首先shuffle的过程指的是map方法之后以及reduce方法之前。
    数据从map方法出来以后,首先进入getPartition方法,然后会对数据进行分区,之后进入环形缓冲区(默认大小为100Mb,数据量到达80%时会进行磁盘溢写),在溢写数据时会进行一次快排,这里的快排是对key的索引进行字典顺序排序,溢写之后会产生大量的小文件,(由于在hdfs中,每个文件不论大小,都会固定占用150字节的系统空间,因为文件或者文件夹是以对象形式存储在hdfs上的),所以我们要在快排之后在进行一次归并排序,来减少小文件个数,之后把数据按照指定的分区放入对应的分区下,来等待reduce的拉取。
    reduce会拉取指定的分区内的文件,先进入内存,如果内存不足,之后会对数据进行落盘,从而防止数据丢失,而且不管是内存中的数据还是说落盘的数据,都要再进行一次归并排序,(也可以再进行一次分组排序)之后就进入到reduce方法。

16、MapTask工作机制

(1)Read阶段:Map Task通过用户编写的RecordReader,从输入InputSplit中解析出一个个key/value。
(2)Map阶段:该节点主要是将解析出的key/value交给用户编写map()函数处理,并产生一系列新的key/value。
(3)Collect收集阶段:在用户编写map()函数中,当数据处理完成后,一般会调用OutputCollector.collect()输出结果。在该函数内部,它会将生成的key/value分区(调用Partitioner),并写入一个环形内存缓冲区中。
(4)Spill阶段:即“溢写”,当环形缓冲区满后,MapReduce会将数据写到本地磁盘上,生成一个临时文件。需要注意的是,将数据写入本地磁盘之前,先要对数据进行一次本地排序,并在必要时对数据进行合并、压缩等操作。

17、ReduceTask工作机制

(1)Copy阶段:ReduceTask从各个MapTask上远程拷贝一片数据,并针对某一片数据,如果其大小超过一定阈值,则写到磁盘上,否则直接放到内存中。
(2)Merge阶段:在远程拷贝数据的同时,ReduceTask启动了两个后台线程对内存和磁盘上的文件进行合并,以防止内存使用过多或磁盘上文件过多。
(3)Sort阶段:按照MapReduce语义,用户编写reduce()函数输入数据是按key进行聚集的一组数据。为了将key相同的数据聚在一起,Hadoop采用了基于排序的策略。由于各个MapTask已经实现对自己的处理结果进行了局部排序,因此,ReduceTask只需对所有数据进行一次归并排序即可。
(4)Reduce阶段:reduce()函数将计算结果写到HDFS上。

18、mapreduce shuffle过程的优化

1)因为环形缓冲区的大小是可以进行调整的,而100mb的大小在通常情况下是不够用的,所以我们可以调整到200mb左右,而且它的阈值80%也是可以调整的,我们可以调整到90%-95%左右,这样可以减少刷写次数,从而提升效率。
2)溢写之后的文件归并,默认是一次十个文件,如果说实际情况中机器性能允许的话,我们可以适当增大一次归并处理的文件个数。
3)在溢写之后,mr还有一个组件combine,它是对于数据提前做一次聚合,即把多个<key,value>合并成<key3,value3>有几个就是key几的形式,这样就减少了之后的磁盘IO从而减少时间。但是combine有一个前提,就是不能对后续的业务逻辑产生影响,比如求和,就不会有影响,而要是一些复杂的逻辑,就容易产生影响,导致数据不准确。
4)压缩,这个是比较有效的可以减少IO的方式,mr过程可以有三处压缩,但是在shuffle过程中有一处,就是在map方法刚出来时,对数据进行压缩,一般选用的压缩方式是snappy和lzo两种压缩方式,因为这两种压缩的速度相对较快。
5)reduce的拉取,默认一次只拉取5个maptask上的数据,如果机器性能允许的话,我们可以适当调大一次拉取的个数,从而提高效率。
6)默认的maptask和reducetask大小都是1G,通常情况下我们会调成四五个G左右,而集群单个节点和每个任务默认内存都是8G,这个我们要根据实际情况进行调整,如果说我们的机器是8G的,那要调整到五六个G左右,如果我们是256G的,那么我们就要调整到200G左右

19、Hadoop优化

1)HDFS小文件影响
①. 影响NameNode的寿命,因为文件元数据存储在NameNode的内存中
②. 影响计算引擎的任务数量,比如每个小的文件都会生成一个Map任务
2)数据输入小文件处理:
①. 合并小文件:对小文件进行归档(Har)、自定义Inputformat将小文件存储成SequenceFile文件。
②. 采用ConbinFileInputFormat来作为输入,解决输入端大量小文件场景。
(3)对于大量小文件Job,可以开启JVM重用。
3)Map阶段
①. 增大环形缓冲区大小。由100m扩大到200m
②. 不影响实际业务的前提下,采用Combiner提前合并,减少 I/O。
4)Reduce阶段
①. 合理设置Map和Reduce数:两个都不能设置太少,也不能设置太多。太少,会导致Task等待,延长处理时间;太多,会导致 Map、Reduce任务间竞争资源,造成处理超时等错误。
②. 设置Map、Reduce共存:调整slowstart.completedmaps参数,使Map运行到一定程度后,Reduce也开始运行,减少Reduce的等待时间。
③. 规避使用Reduce,因为Reduce在用于连接数据集的时候将会产生大量的网络消耗。
④. 增加每个Reduce去Map中拿数据的并行数
⑤. 集群性能可以的前提下,增大Reduce端存储数据内存的大小。
5)IO传输
①. 采用数据压缩的方式,减少网络IO的的时间。安装Snappy和LZOP压缩编码器。
②. 使用SequenceFile二进制文件
6)整体
①. MapTask默认内存大小为1G,可以增加MapTask内存大小为4-5g
②. ReduceTask默认内存大小为1G,可以增加ReduceTask内存大小为4-5g
③. 可以增加MapTask的cpu核数,增加ReduceTask的CPU核数
④. 增加每个Container的CPU核数和内存大小
⑤. 调整每个Map Task和Reduce Task最大重试次数

20、Zookeeper是什么

Zookeeper是一个开源的分布式的,为分布式应用提供协调服务的Apache项目。
    Zookeeper是Hadoop,kafka和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。ZooKeeper的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。

21、Zookeeper选举机制

1)半数机制(Paxos 协议):集群中半数以上机器存活,集群可用。所以zookeeper适合装在奇数台机器上。
2)Zookeeper虽然在配置文件中并没有指定master和slave。但是,zookeeper工作时,是有一个节点为leader,其他则为follower,Leader是通过内部的选举机制临时产生的
3)以一个简单的例子来说明整个选举的过程。
①. 服务器1启动,此时只有它一台服务器启动了,它发出去的报没有任何响应,所以它的选举状态一直是LOOKING状态。
②. 服务器2启动,它与最开始启动的服务器1进行通信,互相交换自己的选举结果,由于两者都没有历史数据,所以id值较大的服务器2胜出,但是由于没有达到超过半数以上的服务器都同意选举它(这个例子中的半数以上是3),所以服务器1、2还是继续保持LOOKING状态。
③. 服务器3启动,根据前面的理论分析,服务器3成为服务器1、2、3中的老大,而与上面不同的是,此时有三台服务器选举了它,所以它成为了这次选举的leader。
④. 服务器4启动,根据前面的分析,理论上服务器4应该是服务器1、2、3、4中最大的,但是由于前面已经有半数以上的服务器选举了服务器3,所以它只能接收当小弟的命了。
⑤. 服务器5启动,同4一样当小弟。

22、Flume是什么

flume是一个高可用的,高可靠的,分布式的海量日志采集、聚合和传输的系统,Flume支持在日志系统中定制各类数据发送方,用于收集数据。数据源可定制、可扩展,数据存储系统可定制、可扩展。

flume运行的核心是agent。它是一个完整的数据收集工具,含有三个核心组件,分别是source、channel、sink。通过这些组件,event可以从一个地方流向另一个地方。为了保证输送一定成功,在送到目的地之前,会先缓存数据,待数据真正到达目的地后,删除自己缓存的数据。

23、flume有哪些组件,flume的source、channel、sink具体是做什么的

(1) Agent
Agent是一个JVM进程,它以事件的形式将数据从源头送至目的,是Flume数据传输的基本单元。
Agent主要有3个部分组成,Source、Channel、Sink。

(2) Source
Source是负责接收数据到Flume Agent的组件。Source组件可以处理各种类型、各种格式的日志数据,包括avro、thrift、exec、jms、spooling directory、netcat、sequence generator、syslog、http、legacy。

(3) Channel
Channel是位于Source和Sink之间的缓冲区。因此,Channel允许Source和Sink运作在不同的速率上。Channel是线程安全的,可以同时处理几个Source的写入操作和几个Sink的读取操作。
Flume自带两种Channel:Memory Channel和File Channel, Kafka Channel
Memory Channel是内存中的队列。Memory Channel在不需要关心数据丢失的情景下适用。如果需要关心数据丢失,那么Memory Channel就不应该使用,因为程序死亡、机器宕机或者重启都会导致数据丢失。
File Channel将所有事件写到磁盘。因此在程序关闭或机器宕机的情况下不会丢失数据。
Kafka Channel:减少了Flume的Sink阶段,提高了传输效率。

(4)Sink
Sink不断地轮询Channel中的事件且批量地移除它们,并将这些事件批量写入到存储或索引系统、或者被发送到另一个Flume Agent。
Sink是完全事务性的。在从Channel批量删除数据之前,每个Sink用Channel启动一个事务。批量事件一旦成功写出到存储系统或下一个Flume Agent,Sink就利用Channel提交事务。事务一旦被提交,该Channel从自己的内部缓冲区删除事件。
Sink组件目的地包括hdfs、logger、avro、thrift、ipc、file、null、HBase、solr、自定义。

(5)Event
传输单元,Flume数据传输的基本单元,以事件的形式将数据从源头送至目的地。

24、Flume的source

(1)Exec Source
  Exec Source可通过tail -f命令去tail住一个文件,然后实时同步日志到sink。但存在的问题是,当agent进程挂掉重启后,会有重复消费的问题。可以通过增加UUID来解决,或通过改进ExecSource来解决。

(2)Spooling Directory Source
  Spooling Directory Source可监听一个目录,同步目录中的新文件到sink,被同步完的文件可被立即删除或被打上标记。适合用于同步新文件,但不适合对实时追加日志的文件进行监听并同步。如果需要实时监听追加内容的文件,可对SpoolDirectorySource进行改进。

(3)Taildir Source
  Taildir Source可实时监控一批文件,并记录每个文件最新消费位置,agent进程重启后不会有重复消费的问题。
    使用时建议用1.8.0版本的flume,1.8.0版本中解决了Taildir Source一个可能会丢数据的bug。

25、Flume的take和put事务

Source到Channel是Put事务
Channel到Sink是Take事务

26、flume性能调优

(1)Source
    增加Source个(使用Tair Dir Source时可增加filegroups个数)可以增大Soure的读取数据的能力。例如:当某一个目录产生的文件过多时需要将这个文件目录拆分成多个文件目录,同时配置好多个Source 以保证Soure有足够的能力获取到新产生的数据。

batchSize参数决定Source一次批量运输到Channel的event条数,适当调大这个参数可以提高Soure搬运Event到Channel时的性能。

(2)Channel
    type 选择memory 时Channel的性能最好,但是如果flume进程意外挂掉可能会丢失数据。type选择file时Channel的容错性更好,但是性能上会比memory channel差。

使用file Channel时dataDirs配置多个不同盘下的目录可以提高性能。

capacity 参数决定Channel可容纳最大的event条数。
    transactionCapacity 参数决定每次Source往channel里面写的最大event条数和每次Sink从channel里面读的最大event条数。transactionCapacity需要大于Source和Sink的batchSize参数。

(3)Sink
    增加Sink的个数可以增加Sink消费event的能力。Sink也不是越多越好够用就行,过多的Sink会占用系统资源,造成系统资源不必要的浪费。

batchSize参数决定Sink一次批量从Channel读取的event条数,适当调大这个参数可以提高Sink从Channel搬出event的性能。

27、Kakfa分区数

分区数并不是越多越好,一般分区数不要超过集群机器数量。分区数越多占用内存越大(ISR等),一个节点集中的分区也就越多,当它宕机的时候,对系统的影响也就越大。
    分区数一般设置为:3-10个

28、kafka写入数据流程

(1)producer先从broker-list的节点中找到该partition的leader;

(2)然后producer将消息发送给作为leader的partition;

(3)leader收到消息后,将消息写入本地log;

(4)followers从leader中pull消息,实现replication的副本备份机制,同样写入本地log;

(5)replication写入本地log后向leader发送ack(确认);

(6)leader收到所有的replication的ack之后,向producer发送ack;

(7)producer收到leader的ack,证明生产的数据已被kafka成功写入。

29、kafka读流程

(1)连接ZK集群,从ZK中拿到对应topic的partition信息和partition的Leader的相关信息
(2)连接到对应Leader对应的broker
(3)consumer将自己保存的offset发送给Leader
(4)Leader根据offset等信息定位到segment(索引文件和日志文件)
(5)根据索引文件中的内容,定位到日志文件中该偏移量对应的开始位置读取相应长度的数据并返回给consumer

30、Kafka消息数据积压,Kafka消费能力不足怎么处理?

1)如果是Kafka消费能力不足,则可以考虑增加Topic的分区数,并且同时提升消费组的消费者数量,消费者数=分区数。(两者缺一不可)
2)如果是下游的数据处理不及时:提高每批次拉取的数量。批次拉取数据过少(拉取数据/处理时间<生产速度),使处理的数据小于生产的数据,也会造成数据积压。

31、什么情况下会重复消费kafka数据

原因1:强行kill线程,导致消费后的数据,offset没有提交(消费系统宕机、重启等)。
原因2:设置offset为自动提交,关闭kafka时,如果在close之前,调用 consumer.unsubscribe() 则有可能部分offset没提交,下次重启会重复消费
原因3:(重复消费最常见的原因):消费后的数据,当offset还没有提交时,partition就断开连接。比如,通常会遇到消费的数据,处理很耗时,导致超过了Kafka的session timeout时间(0.10.x版本默认是30秒),那么就会re-blance重平衡,此时有一定几率offset没提交,会导致重平衡后重复消费。
原因4:当消费者重新分配partition的时候,可能出现从头开始消费的情况,导致重发问题。
原因5:当消费者消费的速度很慢的时候,可能在一个session周期内还未完成,导致心跳机制检测报告出问题

32、如何保证不重复读kafka数据

(1)幂等操作,重复消费不会产生问题

(2)

dstream.foreachRDD {(rdd, time) =

  rdd.foreachPartition { partitionIterator =>

    val partitionId = TaskContext.get.partitionId()

    val uniqueId = generateUniqueId(time.milliseconds,partitionId)将uniqueID存入数据库中

    //use this uniqueId to transationally commit the data in partitionIterator

 }
}

对每个partitionID,产生一个uniqueID,.只有这个partition的数据被完全消费,才算成功,否则失败回滚。下次若重复执行,就skip

33、如何做到复读kafka数据

消费者要从头开始消费某个topic的全量数据,需要满足2个条件(spring-kafka):

(1)使用一个全新的"group.id"(就是之前没有被任何消费者使用过);

(2)指定"auto.offset.reset"参数的值为earliest;

34、Kafka丢不丢数据

Ack=0,相当于异步发送,消息发送完毕即offset增加,继续生产。
Ack=1,leader收到leader replica 对一个消息的接受ack才增加offset,然后继续生产。
Ack=-1,leader收到所有replica 对一个消息的接受ack才增加offset,然后继续生产。

35、kafka保证数据不丢失

producer 生产端:
ack的配置
acks = 0    生产者发送消息之后 不需要等待服务端的任何响应,它不管消息有没有发送成功,如果发送过程中遇到了异常,导致broker端没有收到消息,消息也就丢失了。
acks = 1(默认值)
  生产者发送消息之后,只要分区的leader副本成功写入消息,那么它就会收到来自服务端的成功响应。
acks = all (或-1)
  生产者在发送消息之后,需要等待ISR中所有的副本都成功写入消息之后才能够收到来自服务端的成功响应,在配置环境相同的情况下此种配置可以达到最强的可靠性。
    
retries的配置策略
    如遇到在leader的选举、网络的抖动等这些异常时,如果配置的retries大于0的,就可以进行重试操作,等到leader选举完成后、网络稳定后,这些异常就会消息,错误也就可以恢复,数据再次重发时就会正常发送到broker端。同时可以增大retries(重试)之间的时间间隔,以确保在重试时可恢复性错误都已恢复。

consumer消费端:
我们在处理消息的时候要添加一个unique key
  假如pull 一个batch 100条的消息,在处理到第80条的时候,由于网络延迟、或者crash的原因没有来得及提交offset,被处理的80条数据都添加了unique key, 可以存到到DB中或者redis中(推荐,因为这样更快),当consumer端会再次poll消费数据时,因为没有提交offset,所以会从0开始消费数据,如果对之前已经消息过的数据没有做unique key的处理,那么会造成重复消息之前的80条数据,但是如果把每条对应的消息都添加了unique key,那就只需要对被处理的消息进行判断,有没有unique key 就可以做到不重复消费数据的问题,这样也同时保证了幂等性。

36、Kafka和其他mq的区别?

作为消息队列来说,企业中选择mq的还是多数,因为像Rabbit,Rocket等mq中间件都属于很成熟的产品,性能一般但可靠性较强,而kafka原本设计的初衷是日志统计分析,现在基于大数据的背景下也可以做运营数据的分析统计,redis的主要场景是内存数据库,作为消息队列来说可靠性太差,而且速度太依赖网络IO,在服务器本机上的速度较快,且容易出现数据堆积的问题,在比较轻量的场合下能够适用。

消息队列有什么优缺点
优点:解耦、异步、削峰。
缺点:系统可用性降低,系统复杂度提高,一致性问题

其他MQ相比较,Kafka有一些优缺点,主要如下,

优点:
可扩展。Kafka集群可以透明的扩展,增加新的服务器进集群。
高性能。Kafka性能远超过传统的ActiveMQ、RabbitMQ等,Kafka支持Batch操作。
容错性。Kafka每个Partition数据会复制到几台服务器,当某个Broker失效时,Zookeeper将通知生产者和消费者从而使用其他的Broker。

缺点:
重复消息。Kafka保证每条消息至少送达一次,虽然几率很小,但一条消息可能被送达多次。
消息乱序。Kafka某一个固定的Partition内部的消息是保证有序的,如果一个Topic有多个Partition,partition之间的消息送达不保证有序。
复杂性。Kafka需要Zookeeper的支持,Topic一般需要人工创建,部署和维护比一般MQ成本更高。

Kafka、ActiveMQ、RabbitMQ、RocketMQ 有什么优缺点?

37、kafka的偏移量offset保存在哪里?

kafka消费者在会保存其消费的进度,也就是offset,存储的位置根据选用的kafka api不同而不同。

首先来说说消费者如果是根据javaapi来消费,也就是【kafka.javaapi.consumer.ConsumerConnector】,我们会配置参数【zookeeper.connect】来消费。这种情况下,消费者的offset会更新到zookeeper的【consumers/{group}/offsets/{topic}/{partition}】目录下。

kafka默认的api来消费,即【org.apache.kafka.clients.consumer.KafkaConsumer】,我们会配置参数【bootstrap.servers】来消费。而其消费者的offset会更新到一个kafka自带的topic【__consumer_offsets】下面,查看当前group的消费进度,则要依靠kafka自带的工具【kafka-consumer-offset-checker】

offset更新的方式,不区分是用的哪种api,大致分为两类:
自动提交:设置enable.auto.commit=true,更新的频率根据参数【auto.commit.interval.ms】来定。这种方式也被称为【at most once】,fetch到消息后就可以更新offset,无论是否消费成功。
手动提交:设置enable.auto.commit=false,这种方式称为【at least once】。fetch到消息后,等消费完成再调用方法【consumer.commitSync()】,手动更新offset;如果消费失败,则offset也不会更新,此条消息会被重复消费一次。

38、如何提高kafka消费性能?

1)如果是Kafka消费能力不足,则可以考虑增加Topic的分区数,并且同时提升消费组的消费者数量,消费者数=分区数。(两者缺一不可)
2)如果是下游的数据处理不及时:提高每批次拉取的数量。批次拉取数据过少(拉取数据/处理时间<生产速度),使处理的数据小于生产的数据,也会造成数据积压。

39、kafka为什么那么快

(1)生产者生产数据
①. 顺序写入
②. Memory Mapped Files
它的工作原理是直接利用操作系统的Page来实现文件到物理内存的直接映射。完成映射之后你对物理内存的操作会被同步到硬盘上(操作系统在适当的时候)。写到mmap中的数据并没有被真正的写到硬盘,操作系统会在程序主动调用flush的时候才把数据真正的写到硬盘。Kafka提供了一个参数——producer.type来控制是不是主动flush,如果Kafka写入到mmap之后就立即flush然后再返回Producer叫同步(sync);写入mmap之后立即返回Producer不调用flush叫异步(async)。
(2)消费者消费数据
①. zero copy
②. 消息传送以文件的形式
③. 批量压缩

总结:
Kafka速度的秘诀在于,它把所有的消息都变成一个批量的文件,并且进行合理的批量压缩,减少网络IO损耗,通过mmap提高I/O速度,写入数据的时候由于单个Partion是末尾添加所以速度最优;读取数据的时候配合sendfile直接暴力输出。

40、kafka能不使用zookeeper吗?原因是什么

zookeeper 是一个分布式的协调组件,早期版本的kafka用zk做meta信息存储,consumer的消费状态,group的管理以及 offset的值。考虑到zk本身的一些因素以及整个架构较大概率存在单点问题,新版本中逐渐弱化了zookeeper的作用。新的consumer使用了kafka内部的group coordination协议,也减少了对zookeeper的依赖,
但是broker依然依赖于ZK,zookeeper 在kafka中还用来选举controller 和 检测broker是否存活等等。

41、为什么使用kafka

(1) 解耦

在项目启动之初来预测将来项目会碰到什么需求,是极其困难的。消息系统在处理过程中间插入了一个隐含的、基于数据的接口层,两边的处理过程都要实现这一接口。这允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束。

(2) 冗余

有些情况下,处理数据的过程会失败。除非数据被持久化,否则将造成丢失。消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险。许多消息队列所采用的"插入-获取-删除"范式中,在把一个消息从队列中删除之前,需要你的处理系统明确的指出该消息已经被处理完毕,从而确保你的数据被安全的保存直到你使用完毕。

(3) 扩展性

因为消息队列解耦了你的处理过程,所以增大消息入队和处理的频率是很容易的,只要另外增加处理过程即可。不需要改变代码、不需要调节参数。扩展就像调大电力按钮一样简单。

(4) 灵活性 & 峰值处理能力

在访问量剧增的情况下,应用仍然需要继续发挥作用,但是这样的突发流量并不常见;如果为以能处理这类峰值访问为标准来投入资源随时待命无疑是巨大的浪费。使用消息队列能够使关键组件顶住突发的访问压力,而不会因为突发的超负荷的请求而完全崩溃。

(5) 顺序保证

(6)缓冲

(7)容易扩展

42、Kafka中broker是做什么的

一个单独的Kafka Server就是一个Broker。Broker的主要工作就是接收生产者发过来的消息,分配offset,之后保存到磁盘中。
    同时,接收消费者、其他Broker的请求,根据请求类型进行相应处理并返回响应。在一般的生产环境中,一个Broker独占一台物理服务器。

43、Hive 基本概念

Hive是基于Hadoop的一个 数据仓库工具,可以将结构化的数据文件映射成一张表,并提供类SQL查询功能;

Hive是构建在Hadoop 之上的数据仓库;

使用HQL进行查询;
使用HDFS存储;
使用MapReduce计算;

简单来说,Hive就是在Hadoop上架了一层SQL接口,可以将SQL翻译成MapReduce去Hadoop上执行,这样就使得数据开发和分析人员很方便的使用SQL来完成海量数据的统计和分析,而不必使用编程语言开发MapReduce那么麻烦。

44、Hive和数据库比较

Hive 和数据库除了拥有类似的查询语言,再无类似之处。
1)数据存储位置
Hive 存储在 HDFS 。数据库将数据保存在块设备或者本地文件系统中。
2)数据更新
Hive中不建议对数据的改写。而数据库中的数据通常是需要经常进行修改的,
3)执行延迟
Hive 执行延迟较高。数据库的执行延迟较低。当然,这个是有条件的,即数据规模较小,当数据规模大到超过数据库的处理能力的时候,Hive的并行计算显然能体现出优势。
4)数据规模
Hive支持很大规模的数据计算;数据库可以支持的数据规模较小。

45、Hive文件存储格式

存储格式分为列式存储和行式存储
Hive支持的存储数的格式主要有:TEXTFILE 、SEQUENCEFILE、ORC、PARQUET。
TEXTFILE和SEQUENCEFILE的存储格式都是基于行存储的;
ORC和PARQUET是基于列式存储的。
存储文件的压缩比总结:
ORC > Parquet > textFile
存储文件的查询速度总结:查询速度相近。

在实际的项目开发当中,hive表的数据存储格式一般选择:orc或parquet。压缩方式一般选择snappy,lzo。

46、Hive内部表和外部表

1)内部表:当我们删除一个管理表时,Hive也会删除这个表中数据。管理表不适合和其他工具共享数据。
2)外部表:删除该表并不会删除掉原始数据,删除的是表的元数据

47、Hive4个By区别

1)Sort By:分区内有序;
2)Order By:全局排序,只有一个Reducer;
3)Distrbute By:类似MR中Partition,进行分区,结合sort by使用。
4) Cluster By:当Distribute by和Sorts by字段相同时,可以使用Cluster by方式。Cluster by除了具有Distribute by的功能外还兼具Sort by的功能。但是排序只能是升序排序,不能指定排序规则为ASC或者DESC。

48、HIve窗口函数

RANK(): 排序相同时会重复,总数不会变
DENSE_RANK() :排序相同时会重复,总数会减少
ROW_NUMBER(): 会根据顺序计算

一般用OVER():指定分析函数工作的数据窗口大小,这个数据窗口大小可能会随着行的变而变化,
还有其他CURRENT ROW()等

49、sql语句中count(*),count(1),count(id)区别详解

count(*) 和 count(1)其实并没有区别,这两者都会将表中所有行都算进来,也就是该表的总行数
    count(列名)时,如果该列的值为null时,该行不计入count总数中,这也就是count(列名)和count(1),count(*)等其他count(非列名和非null)的区别

50、Hive行转列

CONCAT(string A/col, string B/col…):返回输入字符串连接后的结果,支持任意个输入字符串;
    CONCAT_WS(separator, str1, str2,…):它是一个特殊形式的 CONCAT()。第一个参数剩余参数间的分隔符。分隔符可以是与剩余参数一样的字符串。如果分隔符是 NULL,返回值也将为 NULL。这个函数会跳过分隔符参数后的任何 NULL 和空字符串。分隔符将被加到被连接的字符串之间;
    COLLECT_SET(col):函数只接受基本数据类型,它的主要作用是将某字段的值进行去重汇总,产生array类型字段。

example:
select col1,col2,concat_ws(’,’,collect_set(col3))
from tmp_l_test
group by col1,col2;

51、Hive列转行

EXPLODE(col):将hive一列中复杂的array或者map结构拆分成多行。
    LATERAL VIEW 用于和split, explode等UDTF一起使用,它能够将一列数据拆成多行数据

example:
select col1, col2, col5
from tmp_c_test
lateral view explode(split(col3,’,’)) b AS col5

52、Hive的优化

(1)、Fetch抓取(配置)
Fetch抓取是指,Hive中对某些情况的查询(select * …)可以不必使用MapReduce计算。
(2)、采用压缩,减少网络io(配置)
(3)、并行执行(配置)
某个特定的job可能包含众多的阶段,而这些阶段可能并非完全互相依赖的,也就是说有些阶段是可以并行执行的,这样可能使得整个job的执行时间缩短。
(4)、本地模式
有时Hive的输入数据量是非常小的。在这种情况下,为查询触发执行任务消耗的时间可能会比实际job的执行时间要多的多。对于大多数这种情况,Hive可以通过本地模式在单台机器上处理所有的任务。对于小数据集,执行时间可以明显被缩短。
(5)、表的优化
①. 大表Join大表
a. 空KEY过滤
b. 空key转换
有时虽然某个key为空对应的数据很多,但是相应的数据不是异常数据,必须要包含在join的结果中,此时我们可以表a中key为空的字段赋一个随机的值,使得数据随机均匀地分不到不同的reducer上

②. MapJoin
如果不指定MapJoin或者不符合MapJoin的条件,那么Hive解析器会将Join操作转换成Common Join,即:在Reduce阶段完成join。容易发生数据倾斜。可以用MapJoin把小表全部加载到内存在map端进行join,避免reducer处理。

③. Group By
默认情况下,Map阶段同一Key数据分发给一个reduce,当一个key数据过大时就倾斜了。
并不是所有的聚合操作都需要在Reduce端完成,很多聚合操作都可以先在Map端进行部分聚合,最后在Reduce端得出最终结果。

④. Count(Distinct) 去重统计
数据量小的时候无所谓,数据量大的情况下,由于COUNT DISTINCT操作需要用一个Reduce Task来完成,这一个Reduce需要处理的数据量太大,就会导致整个Job很难完成,一般COUNT DISTINCT使用先GROUP BY再COUNT的方式替换

⑤. 行列过滤
列处理:在SELECT中,只拿需要的列,如果有,尽量使用分区过滤,少用SELECT *。
行处理:在分区剪裁中,当使用外关联时,如果将副表的过滤条件写在Where后面,那么就会先全表关联,之后再过滤

⑥. 动态分区调整

⑦. 采用分桶技术

⑧. 采用分区技术
分区表实际上就是对应一个HDFS文件系统上的独立的文件夹,该文件夹下是该分区所有的数据文件。Hive中的分区就是分目录,把一个大的数据集根据业务需要分割成小的数据集。在查询时通过WHERE子句中的表达式选择查询所需要的指定的分区,这样的查询效率会提高很多。

(6)、数据倾斜
合理设置Map数
小文件进行合并
复杂文件增加Map数
合理设置Reduce数

(7)、JVM重用
小文件的场景或task特别多的场景,这类场景大多数执行时间都很短。

53、hive数据倾斜

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

倾斜原因:
1.小文件多,大小不均匀
2.大表和小表进行join操作时
3.大量的null key

解决办法:
1.合理设置map数和reduce数

2.小文件过多,需要合并小文件,还有就是jvm重用

3.map join解决小表关联大表造成的数据倾斜问题,其是将其中做连接的小表(全量数据)分发到所有Map端进行Join,从而避免了reduce任务,当小表全量数据很小的时候可进行此操作

4.查询时出现空key的问题
没有用就过滤,有作用就添加随机数打伞

5.不同数据类型关联产生数据倾斜
把数字类型转换成字符串类型

6.当HiveQL中包含count(distinct)时
如果数据量非常大,执行如select a,count(distinct b) from t group by a;类型的SQL时,会出现数据倾斜的问题。
解决方法:使用sum…group by代替。如select a,sum(1) from (select a, b from t group by a,b) group by a;

7.对于Group操作,首先在map端聚合,最后在reduce端坐聚合

54、OLTP 与 OLAP

联机事务处理 OLTP,可以增删改查,用户较为关心操作的响应时间、数据的安全性、完整性和并发支持的用户数,性能要求高,数据量小
   联机分析处理 OLAP,一般对数据进行分析,支持管理决策。

55、星型模型和雪花模型的区别?

星型模式是维度模型中最简单的形式,也用得最广泛。星型模式由事实表和维度表组成,一个星型模式中可以有一个或多个事实表,每个事实表引用任意数量的维度表。星型模式的物理模型像一颗星星的形状,中心是一个事实表, 围绕在事实表周围的维度表表示星星的放射状分支,这就是星型模式这个名字的由来。
    雪花模式是一种多维模型中表的逻辑布局,其实体关系图有类似于雪花的形状,因此得名。雪花模式中,一个维度被规范化成多个关联的表,而在星型模式中,每个维度由一个单一的维度表所表示。
    星座模型由多个主题构成,包含多个事实表,而维表是公共的,可以共享,这种模式可以看做星型模式的汇集,因而称作星系模式或者事实星座模式。

模型的选择:
首先就是星座不星座这个只跟数据和需求有关系,跟设计没关系,不用选择。
星型还是雪花,取决于性能优先,还是避免冗余、灵活更优先。
目前实际企业开发中,不会绝对选择一种,根据情况灵活组合,甚至并存(一层维度和多层维度都保存)。但是整体来看,更倾向于维度更少的星型模型。尤其是hadoop体系,减少join就是减少shuffle,性能差距很大。(关系型数据可以依靠强大的主键索引)

区别:
    冗余:星星模式冗余相对于雪花模型多一些,雪花模型更符合三范式
    性能:雪花模型因为要关联维度表,使用三范式降低了冗余,所以查询时性能偏低,星星模式更快一些,这里就是时间换空间,还是空间换时间的选择了,而且一般bi工具对星型模型支持更好

ETL,雪花模型etl中编写简单,但是并行化低,星星模型编写略麻烦,但是并行化高

56、数据仓库分层

1.ODS(原始数据层)
2.DWD(数据ETL层)
将数据清理、整合、规范化,脏数据、垃圾数据、规范不一致的、状态定义不一致的、命名不规范的数据都会被处理
3.DWS(数据汇总层)
会进行轻度汇总,粒度比明细数据稍粗,会针对度量值进行汇总,目的是避免重复计算
4.DM(数据集市)(可以导入mysql进行数据展示)

57、Redis的5种数据类型

string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。

58、Redis 消息队列

Redis的列表类型键可以用来实现队列,并且支持阻塞式读取,可以很容易的实现一个高性能的优先队列。同时在更高层面上,Redis还支持"发布/订阅"的消息模式,可以基于此构建一个聊天系统。
redis的列表类型天生支持用作消息队列。(类似于MQ的队列模型–任何时候都可以消费,一条消息只能消费一次)

59、Redis的hash存储

redis的hash架构就是标准的hashtable的结构,通过挂链解决冲突问题。

60、REDIS缓存穿透,缓存击穿,缓存雪崩原因

1.前言
在我们日常的开发中,无不都是使用数据库来进行数据的存储,由于一般的系统任务中通常不会存在高并发的情况,所以这样看起来并没有什么问题,可是一旦涉及大数据量的需求,比如一些商品抢购的情景,或者是主页访问量瞬间较大的时候,单一使用数据库来保存数据的系统会因为面向磁盘,磁盘读/写速度比较慢的问题而存在严重的性能弊端,一瞬间成千上万的请求到来,需要系统在极短的时间内完成成千上万次的读/写操作,这个时候往往不是数据库能够承受的,极其容易造成数据库系统瘫痪,最终导致服务宕机的严重生产问题。

为了克服上述的问题,项目通常会引入NoSQL技术,这是一种基于内存的数据库,并且提供一定的持久化功能。

redis技术就是NoSQL技术中的一种,但是引入redis又有可能出现缓存穿透,缓存击穿,缓存雪崩等问题。本文就对这三种问题进行较深入剖析。

2.初认识
缓存穿透:key对应的数据在数据源并不存在,每次针对此key的请求从缓存获取不到,请求都会到数据源,从而可能压垮数据源。比如用一个不存在的用户id获取用户信息,不论缓存还是数据库都没有,若黑客利用此漏洞进行攻击可能压垮数据库。
缓存击穿:key对应的数据存在,但在redis中过期,此时若有大量并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。
缓存雪崩:当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,也会给后端系统(比如DB)带来很大压力。

61、Redis缓存穿透解决方案

一个一定不存在缓存及查询不到的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。
有很多种方法可以有效地解决缓存穿透问题,最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被 这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。另外也有一个更为简单粗暴的方法(我们采用的就是这种),如果一个查询返回的数据为空(不管是数据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。

62、redis缓存击穿解决方案

key可能会在某些时间点被超高并发地访问,是一种非常“热点”的数据。这个时候,需要考虑一个问题:缓存被“击穿”的问题。

使用互斥锁(mutex key)

63、redis缓存崩溃的解决方法

这里提出了三种方案:使用锁或队列、设置过期标志更新缓存、为key设置不同的缓存失效时间,还有一种被称为“二级缓存”的解决方法

64、redis集群模式

主从模式
Sentinel模式(哨兵模式)
cluster模式

65、Redis主从模式

Redis 提供了复制(replication)功能,可以实现当一台数据库中的数据更新后,自动将更新的数据同步到其他数据库上。

在复制的概念中,数据库分为两类,一类是主数据库(master),另一类是从数据库(slave)。主数据库可以进行读写操作,当写操作导致数据变化时会自动将数据同步给从数据库。而从数据库一般是只读的,并接受主数据库同步过来的数据。一个主数据库可以拥有多个从数据库,而一个从数据库只能拥有一个主数据库。

特点

  • 主数据库可以进行读写操作,当读写操作导致数据变化时会自动将数据同步给从数据库

  • 从数据库一般都是只读的,并且接收主数据库同步过来的数据

  • 一个master可以拥有多个slave,但是一个slave只能对应一个master

  • slave挂了不影响其他slave的读和master的读和写,重新启动后会将数据从master同步过来

  • master挂了以后,不影响slave的读,但redis不再提供写服务,master重启后redis将重新对外提供写服务

  • master挂了以后,不会在slave节点中重新选一个master

缺点:

从上面可以看出,master节点在主从模式中唯一,若master挂掉,则redis无法对外提供写服务。

66、Redis哨兵模式

主从模式的弊端就是不具备高可用性,当master挂掉以后,Redis将不能再对外提供写入操作,因此sentinel应运而生。

sentinel中文含义为哨兵,顾名思义,它的作用就是监控redis集群的运行状况,特点如下:

  • sentinel模式是建立在主从模式的基础上,如果只有一个Redis节点,sentinel就没有任何意义
  • 当master挂了以后,sentinel会在slave中选择一个做为master,并修改它们的配置文件,其他slave的配置文件也会被修改,比如slaveof属性会指向新的master
  • 当master重新启动后,它将不再是master而是做为slave接收新的master的同步数据
  • sentinel因为也是一个进程有挂掉的可能,所以sentinel也会启动多个形成一个sentinel集群
  • 多sentinel配置的时候,sentinel之间也会自动监控
  • 当主从模式配置密码时,sentinel也会同步将配置信息修改到配置文件中,不需要担心
  • 一个sentinel或sentinel集群可以管理多个主从Redis,多个sentinel也可以监控同一个redis
  • sentinel最好不要和Redis部署在同一台机器,不然Redis的服务器挂了以后,sentinel也挂了
    优点:
    哨兵模式是基于主从模式的,所有主从的优点,哨兵模式都具有。
    主从可以自动切换,系统更健壮,可用性更高。
    缺点:
    Redis较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。

67、Redis Cluster集群

Redis 的哨兵模式基本已经可以实现高可用,读写分离 ,但是在这种模式下每台 Redis 服务器都存储相同的数据,很浪费内存,所以在redis3.0上加入了 Cluster 集群模式,实现了 Redis 的分布式存储,也就是说每台 Redis 节点上存储不同的内容。
官方推荐,集群部署至少要 3 台以上的master节点,最好使用 3 主 3 从六个节点的模式。
特点:

  • 多个redis节点网络互联,数据共享
  • 所有的节点都是一主一从(也可以是一主多从),其中从不提供服务,仅作为备用
  • 不支持同时处理多个key(如MSET/MGET),因为redis需要把key均匀分布在各个节点上,
    并发量很高的情况下同时创建key-value会降低性能并导致不可预测的行为
  • 支持在线增加、删除节点
  • 客户端可以连接任何一个主节点进行读写

68、hdfs工作机制

1.HDFS集群分为两大角色:NameNode、DataNode、
2.NameNode负责管理整个文件系统的元数据(block日志,镜像文件fsimage )
3.DataNode 负责管理用户的文件数据块
4.文件会按照固定的大小(blocksize)切成若干块后分布式存储在若干台datanode上
5.每一个文件块可以有多个副本,并存放在不同的datanode上
6.Datanode会定期向Namenode汇报自身所保存的文件block信息,而namenode则会负责保持文件的副本数量
7.HDFS的内部工作机制对客户端保持透明,客户端请求访问HDFS都是通过向namenode申请来进行

69、tcp,udp的区别

Tcp会三次握手建立连接,而udp不会

70、网络七层和网络四层,它们的区别是什么

“七层”是OSI参考模型,即物理层 、 数据链路层 、 网络du层、传输层、 会话层zhi 、表示层、应用层 ;
“四层”是TCP/IP参考模型,即物理链路层、 网络层、传输层、应用层。
虽说有四层和七层之说,但是其实一样的,TCP/IP中的物理链路层对应OSI中的物理层和数据链路层 ,网络层对应网络层,传输层对应传输层,应用层对应会话层 、表示层、应用层 。

71、数据库存储数据的具体文件是什么,有几种

不同的引擎不一样,有两种,innodb和myisam
MyISAM:每个MyISAM在磁盘上存储成三个文件。分别为:表定义文件、数据文件、索引文件。第一个文件的名字以表的名字开始,扩展名指出文件类型。.frm文件存储表定义。数据文件的扩展名为.MYD (MYData)。索引文件的扩展名是.MYI (MYIndex)。
InnoDB:所有的表都保存在同一个数据文件中(也可能是多个文件,或者是独立的表空间文件),
InnoDB表的大小只受限于操作系统文件的大小,一般为2GB。

72、myisam和innodb的区别

1)InnoDB支持事务,MyISAM不支持,这一点是非常之重要。事务是一种高级的处理方式,如在一些列增删改中只要哪个出错还可以回滚还原,而MyISAM就不可以了。
2)MyISAM适合查询以及插入为主的应用,InnoDB适合频繁修改以及涉及到安全性较高的应用
3)InnoDB支持外键,MyISAM不支持
4)从MySQL5.5.5以后,InnoDB是默认引擎
5)InnoDB不支持FULLTEXT类型的索引
6)InnoDB中不保存表的行数,如select count() from table时,InnoDB需要扫描一遍整个表来计算有多少行,但是MyISAM只要简单的读出保存好的行数即可。注意的是,当count()语句包含where条件时MyISAM也需要扫描整个表
7)对于自增长的字段,InnoDB中必须包含只有该字段的索引,但是在MyISAM表中可以和其他字段一起建立联合索引
8)清空整个表时,InnoDB是一行一行的删除,效率非常慢。MyISAM则会重建表
9)InnoDB支持行锁(某些情况下还是锁整表,如 update table set a=1 where user like ‘%lee%’。

73、数据库锁的类型

锁是网络数据库中的一个非常重要的概念,当多个用户同时对数据库并发操作时,会带来数据不一致的问题,所以,锁主要用于多用户环境下保证数据库完整性和一致性。
    类型有共享锁,更新锁,排他锁

74、数据库explain和show profile的具体应用

使用explain关键字进行分析时,SQL语句并不会执行。只是模拟MySQL优化器的执行过程,所以用explain查看的结果是叫执行计划。
    explain关键字主要用来定性分析索引的使用情况,以及SQL语句的优劣,但是无法知道SQL语句的实际执行情况。
    而show profile命令可以做到定量分析SQL语句的执行情况。即使用者可以明确知道一条SQL到底执行了多久。

75、Hbase是什么

HBase是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统,利用HBASE技术可在廉价PC Server上搭建起大规模结构化存储集群。
    HBase的目标是存储并处理大型的数据,更具体来说是仅需使用普通的硬件配置,就能够处理由成千上万的行和列所组成的大型数据。

76、Hbase特点

1)海量存储
Hbase适合存储PB级别的海量数据,在PB级别的数据以及采用廉价PC存储的情况下,能在几十到百毫秒内返回数据。这与Hbase的极易扩展性息息相关。正式因为Hbase良好的扩展性,才为海量数据的存储提供了便利。
2)列式存储
这里的列式存储其实说的是列族存储,Hbase是根据列族来存储数据的。列族下面可以有非常多的列,列族在创建表的时候就必须指定。
3)极易扩展
Hbase的扩展性主要体现在两个方面,一个是基于上层处理能力(RegionServer)的扩展,一个是基于存储的扩展(HDFS)。
通过横向添加RegionSever的机器,进行水平扩展,提升Hbase上层的处理能力,提升Hbsae服务更多Region的能力。
备注:RegionServer的作用是管理region、承接业务的访问,这个后面会详细的介绍通过横向添加Datanode的机器,进行存储层扩容,提升Hbase的数据存储能力和提升后端存储的读写能力。
4)高并发
由于目前大部分使用Hbase的架构,都是采用的廉价PC,因此单个IO的延迟其实并不小,一般在几十到上百ms之间。这里说的高并发,主要是在并发的情况下,Hbase的单个IO延迟下降并不多。能获得高并发、低延迟的服务。
5)稀疏
稀疏主要是针对Hbase列的灵活性,在列族中,你可以指定任意多的列,在列数据为空的情况下,是不会占用存储空间的。

77、HBase中的角色

HMaster
功能:
1.监控RegionServer
2.处理RegionServer故障转移
3.处理元数据的变更
4.处理region的分配或转移
5.在空闲时间进行数据的负载均衡
6.通过Zookeeper发布自己的位置给客户端

RegionServer
功能:
1.负责存储HBase的实际数据
2.处理分配给它的Region
3.刷新缓存到HDFS
4.维护Hlog
5.执行压缩
6.负责处理Region分片

其他组件:
1.Write-Ahead logs
HBase的修改记录,当对HBase读写数据的时候,数据不是直接写进磁盘,它会在内存中保留一段时间(时间以及数据量阈值可以设定)。但把数据保存在内存中可能有更高的概率引起数据丢失,为了解决这个问题,数据会先写在一个叫做Write-Ahead logfile的文件中,然后再写入内存中。所以在系统出现故障的时候,数据可以通过这个日志文件重建。
2.Region
Hbase表的分片,HBase表会根据RowKey值被切分成不同的region存储在RegionServer中,在一个RegionServer中可以有多个不同的region。
3.Store
HFile存储在Store中,一个Store对应HBase表中的一个列族。
4.MemStore
顾名思义,就是内存存储,位于内存中,用来保存当前的数据操作,所以当数据保存在WAL中之后,RegsionServer会在内存中存储键值对。
5.HFile
这是在磁盘上保存原始数据的实际的物理文件,是实际的存储文件。StoreFile是以Hfile的形式存储在HDFS的。

78、hbase读写流程

读流程:
1)Client先访问zookeeper,从meta表读取region的位置,然后读取meta表中的数据。meta中又存储了用户表的region信息;
2)根据namespace、表名和rowkey在meta表中找到对应的region信息;
3)找到这个region对应的regionserver;
4)查找对应的region;
5)先从MemStore找数据,如果没有,再到BlockCache里面读;
6)BlockCache还没有,再到StoreFile上读(为了读取的效率);
7)如果是从StoreFile里面读取的数据,不是直接返回给客户端,而是先写入BlockCache,再返回给客户端。

写流程:
1)Client向HregionServer发送写请求;
2)HregionServer将数据写到HLog(write ahead log)(WAL)。为了数据的持久化和恢复;
3)HregionServer将数据写到内存(MemStore);
4)反馈Client写成功。

数据flush过程:
1)当MemStore数据达到阈值(默认是128M,老版本是64M),将数据刷到硬盘,将内存中的数据删除,同时删除HLog中的历史数据;
2)并将数据存储到HDFS中;

数据合并过程:
1)当数据块达到4块,Hmaster将数据块加载到本地,进行合并;
2)当合并的数据超过256M,进行拆分,将拆分后的Region分配给不同的HregionServer管理;
3)当HregionServer宕机后,将HregionServer上的hlog拆分,然后分配给不同的HregionServer加载,修改.META.;
4)注意:HLog会同步到HDFS。

79、hbase内部存储格式

HBase中的所有数据文件都存储在Hadoop HDFS文件系统上,主要包括上述提出的两种文件类型:

1)HFile, HBase中KeyValue数据的存储格式,HFile是Hadoop的二进制格式文件,实际上StoreFile就是对HFile做了轻量级包装,即StoreFile底层就是HFile

2) HLog File,HBase中WAL(Write Ahead Log) 的存储格式,物理上是Hadoop的Sequence File

80、hbase的 rowkey设计

HBase 中 rowkey 可以唯一标识一行记录,在 HBase 查询的时候,有以下几种方式:
1.通过 get 方式,指定 rowkey 获取唯一一条记录;
2.通过 scan 方式,设置 startRow 和 stopRow 参数进行范围匹配;
3.全表扫描,即直接扫描整张表中所有行记录;

设计原则:
1.Rowkey 长度原则
RowKey是一个二进制码流,可以是任意字符串,最大长度为64kb,实际应用中一般为10-100byte,以 byte[] 形式保存,一般设计成定长。建议越短越好,不要超过16个字节,原因如下:
  数据的持久化文件HFile中时按照Key-Value存储的,如果RowKey过长,例如超过100byte,那么1000w行的记录,仅RowKey就需占用近1GB的空间。这样会极大影响HFile的存储效率。
  MemStore会缓存部分数据到内存中,若RowKey字段过长,内存的有效利用率就会降低,就不能缓存更多的数据,从而降低检索效率。
  目前操作系统都是64位系统,内存8字节对齐,控制在16字节,8字节的整数倍利用了操作系统的最佳特性。

2.唯一原则
必须在设计上保证RowKey的唯一性。由于在HBase中数据存储是Key-Value形式,若向HBase中同一张表插入相同RowKey的数据,则原先存在的数据会被新的数据覆盖。

3.RowKey 散列原则
设计的RowKey应均匀的分布在各个HBase节点上。

4.排序原则
HBase的RowKey是按照ASCII有序排序的(字典序),因此我们在设计RowKey的时候要充分利用这点。

5.针对热点问题的 RowKey 设计原则:
我们设计的Rowkey应均匀的分布在各个HBase节点上。拿常见的时间戳举例,假如Rowkey是按系统时间戳的方式递增,Rowkey的第一部分如果是时间戳信息的话将造成所有新数据都在一个RegionServer上堆积的热点现象,也就是通常说的Region热点问题, 热点发生在大量的client直接访问集中在个别RegionServer上(访问可能是读,写或者其他操作),导致单个RegionServer机器自身负载过高,引起性能下降甚至Region不可用,常见的是发生jvm full gc或者显示region too busy异常情况,当然这也会影响同一个RegionServer上的其他Region。
①rowkey 的前面增加随机数,失去 get 快速定位数据的能力。
②rowkey 的前面增加哈希。哈希也可以使负载分散到整个集群,但是读却是可以预测的。使用确定的哈希可以让客户端重构完整的 rowkey,可以使用 get 操作准确获取某一个行数据。

6.反转
手机号反转,牺牲了rowkey的有序性

7.时间戳反转

8.组合 RowKey 设计原则
RowKey 为多个属性拼接而成时,将具有高标识度的、经常使用检索列的属性放在组合RowKey 的前面。

81、HBase优化

1.配置高可用
Hmaster负责监控RegionServer的生命周期,均衡RegionServer的负载,如果Hmaster挂掉了,那么整个HBase集群将陷入不健康的状态,并且此时的工作状态并不会维持太久。
配置高可用防止hmaster挂掉

2.预分区
每一个region维护着startRow与endRowKey,如果加入的数据符合某个region维护的rowKey范围,则该数据交给这个region维护。那么依照这个原则,我们可以将数据所要投放的分区提前大致的规划好,以提高HBase性能。

3.RowKey设计
hbase 存储的数据过亿。
一条数据的唯一标识就是rowkey,这条数据存储于哪个分区,取决于rowkey处于哪个一个预分区的区间内,设计rowkey的主要目的 ,就是让数据均匀的分布于所有的region中,在一定程度上防止数据倾斜。

4.内存优化
HBase操作过程中需要大量的内存开销,毕竟Table是可以缓存在内存中的,可以加大内存,但要保存够系统内存,不影响系统运行

5.基础优化
允许在HDFS的文件中追加内容
优化DataNode允许的最大文件打开数
优化延迟高的数据操作的等待时间
优化数据的写入效率
优化DataNode存储
设置RPC监听数量
优化HStore文件大小
优化hbase客户端缓存
指定scan.next扫描HBase所获取的行数
flush、compact、split机制

82、hbase的协处理器

协处理器有两种: ObserverEndpoint
(1) Observer 类似于传统数据库中的触发器,当发生某些事件的时候这类协处理器会被 Server 端调用
(2) Endpoint 协处理器类似传统数据库中的存储过程,客户端可以调用这些 Endpoint 协处 理器执行一段 Server 端代码,并将 Server 端代码的结果返回给客户端进一步处理,最常 见的用法就是进行聚集操作。
(3)总结:
Observer 允许集群在正常的客户端操作过程中可以有不同的行为表现
Endpoint 允许扩展集群的能力,对客户端应用开放新的运算命令

Observer 类似于 RDBMS 中的触发器,主要在服务端工作
Endpoint 类似于 RDBMS 中的存储过程,主要在 client 端工作

Observer 可以实现权限管理、优先级设置、监控、 ddl 控制、 二级索引等功能
Endpoint 可以实现 min、 max、 avg、 sum、 distinct、 group by 等功能

协处理器的加载方式:
   协处理器的加载方式有两种,我们称之为静态加载方式( Static Load,全局的) 和动态加载方式 ( Dynamic Load)

83、怎么理解scala的函数式编程

1.Scala中函数的地位:一等公民 ,像变量一样,既可以作为函数的参数使用,也可以将函数赋值给一个变量. ,函数的创建不用依赖于类、特质或者对象
2.Scala中的匿名函数(函数字面量)
3.Scala中的高阶函数
4.Scala中的闭包
5.Scala中的部分应用函数
6.Scala中的柯里化函数

84、Scala中的高阶函数

函数可以作为一个参数传入到一个方法当中去

85、Scala中的匿名函数(函数字面量)

匿名函数的定义格式为(形参列表) =>{函数体},左边是参数列表,右边是函数体
在spark中用的比较多,作为参数表达流程

86、Scala中的部分应用函数

部分应用函数, 是指一个函数有N个参数, 而我们为其提供少于N个参数, 那就得到了一个部分应用函数。

比如我先定义一个函数:
def sum(a:Int,b:Int,c:Int) = a b c;
那么就可以从这个函数衍生出一个偏函数是这样的:

def p_sum = sum(1, _:Int, _:Int)
于是就可以这样调用p_sum(2,3), 相当于调用sum(1,2,3) 得到的结果是6。这里的两个_分别对应函数sum对应位置的参数. 所以你也可以定义成

def p_sum = sum (_:Int, 1, _:Int)
这东西有啥用呢? 一个是当你在代码中需要多次调用一个函数, 而其中的某个参数又总是一样的时候, 使用这个可以使你少敲一些代码

87、Scala柯里化

函数编程中,接受多个参数的函数都可以转化为接受单个参数的函数,这个转化过程就叫柯里化,
def mulCurry(x: Int) = (y: Int) => x * y
println(mulCurry(10)(9))
def mulCurry2(x: Int)(y:Int) = x * y
println(mulCurry2(10)(8))
柯里化,是面向函数思想的必然产生结果。

88、Scala闭包

闭包是一个函数,返回值依赖于声明在函数外部的一个或多个变量。

闭包通常来讲可以简单的认为是可以访问一个函数里面局部变量的另外一个函数。

89、Scala样例类

样例类可以new, 也可以不用new
当一个类被定义成为case类后,Scala会自动帮你创建一个伴生对象并帮你实现了apply, unapply,setter, getter 和toString,equals,copy和hashCode等方法

90、case class (样本类)是什么?

样本类是一种不可变且可分解类的语法糖,这个语法糖的意思大概是在构建时,自动实现一些功能。样本类具有以下特性:
(1)自动添加与类名一致的构造函数(这个就是前面提到的伴生对象,通过apply方法实现),即构造对象时,不需要new;
(2)样本类中的参数默认添加val关键字,即参数不能修改;
(3)默认实现了toString,equals,hashcode,copy等方法;
(4)样本类可以通过==比较两个对象,并且不在构造方法中定义的属性不会用在比较上。

代码示例
//声明一个样本类
case class MyCaseClass(number: Int, text: String, others: List[Int]){
println(number)
}
//不需要new关键字,创建一个对象
val dto = MyCaseClass(3, “text”, List.empty) //打印结果3
//利用样本类默认实现的copy方法
dto.copy(number = 5) //打印结果5
val dto2 = MyCaseClass(3, “text”, List.empty)
pringln(dto == dto2) // 返回true,两个不同的引用对象
class MyClass(number: Int, text: String, others: List[Int]) {}
val c1 = new MyClass(1, “txt”, List.empty)
val c2 = new MyClass(1, “txt”, List.empty)
println(c1 == c2 )// 返回false,两个不同的引用对象

91、scala 伴生对象的作用

1.什么是伴生对象

scala中的类不能定义静态成员,而代之以定义单例对象来替代
单例对象通过object关键字来声明
单例对象中的所有方法,可以直接通过object单例对象的名字直接来调用。
一个单例对象可以绑定在一个类,当单例对象和某个类写在同一个源文件且共享一个名字,它们就产生了绑定关系。
此时单例对象称之为该类的伴生对象,类称之为该对象的伴生类。

2.伴生对象与伴生类

类和它的伴生对象可以互相访问其私有成员
单例对象不能new,所以也没有构造参数
可以把单例对象当做java中可能会用到的静态方法工具类。
作为程序入口的方法必须是静态的,所以main方法必须处在一个单例对象中,而不能写在一个类中。

3、单例对象在第一次被访问时才会被初始化,来自于scala自带的predef包。

92、Spark是什么?

Spark 是专为大规模数据处理而设计的快速通用的计算引擎,用scala开发的,基于内存计算的大数据并行计算框架。Spark基于内存计算,提高了在大数据环境下数据处理的实时性,同时保证了高容错性和高可伸缩性。
速度快:内存计算下,Spark 比 Hadoop 快100倍。
易用性:可以用Java,Scala,Python,R以及SQL开发,还有非常多的算子
通用性(支持SQL,流数据处理以及复杂分析):包括SQL和DataFrame,用于机器学习的MLib,支持图计算GraphX以及流计算模块Streaming。
支持多种模式运行:单机模式,Standalone,yarn,mesos

93、Spark核心组件

Driver
Spark驱动器节点,用于执行Spark任务中的main方法,负责实际代码的执行工作。Driver在Spark作业执行时主要负责:
1.将用户程序转化为作业(job);
2.在Executor之间调度任务(task);
3.跟踪Executor的执行情况;
4.通过UI展示查询运行情况;
Executor
Spark Executor节点是一个JVM进程,负责在 Spark 作业中运行具体任务,任务彼此之间相互独立。Spark 应用启动时,Executor节点被同时启动,并且始终伴随着整个 Spark 应用的生命周期而存在。如果有Executor节点发生了故障或崩溃,Spark 应用也可以继续执行,会将出错节点上的任务调度到其他Executor节点上继续运行。(spark的容错机制)
Executor有两个核心功能:

  1. 负责运行组成Spark应用的任务,并将结果返回给驱动器进程;
  2. 它们通过自身的块管理器(Block Manager)为用户程序中要求缓存的 RDD 提供内存式存储。RDD 是直接缓存在Executor进程内的,因此任务可以在运行时充分利用缓存数据加速运算。

94、Spark和mapreduce的区别

1.spark把中间计算结果存放在内存中,减少迭代过程中的数据落地
2.spark容错性高,支持DAG图
3.spark更加通用,api更多,spark提供了transformation和action这两大类的多个功能API
4.spark框架和生态更为复杂,很多时候spark作业都需要根据不同业务场景的需要进行调优已达到性能要求;mapreduce框架及其生态相对较为简单,对性能的要求也相对较弱,但是运行较为稳定,适合长期后台运行
5.Spark API方面- Scala: Scalable Language, 是进行并行计算的最好的语言. 与Java相比,极大的减少代码量(Hadoop框架的很多部分是用Java编写的)

95、Spark运行模式

本地模式:
Spark单机运行,一般用于开发测试。

Standalone模式:
构建一个由Master Slave构成的Spark集群,Spark运行在集群中。

Spark on Yarn模式:
Spark客户端直接连接Yarn。不需要额外构建Spark集群。

Spark on Mesos模式:
生产环境一般使用yarn-cluster,测试一个般用Client或者单机

96、Spark提交过程

YARN Cluster模式:

任务提交后会和ResourceManager,申请启动ApplicationMaster,随后ResourceManager分配container,在合适的NodeManager上启动ApplicationMaster,此时的ApplicationMaster就是Driver。
    Driver启动后向ResourceManager申请Executor,ResourceManager接到ApplicationMaster的资源申请后会分配container,然后在合适的NodeManager上启动Executor进程,Executor进程启动后会向Driver反向注册,Executor全部注册完成后Driver开始执行main函数,之后执行到Action算子时,触发一个job,并根据宽依赖开始划分stage,每个stage生成对应的taskSet,之后将task分发到各个Executor上执行。

97、java和scala的区别:

(1)scala是多范式编程语言(面向对象 函数式编程),Java是面向对象编程语言
(2)scala包含两种类型的变量,val想当于java中的常量,var为常规变量
(3)scala中通配符是 _,java中是 *
(4)scala中的unit想当于java中的 void
(5)scala支持关联映射,如可以用(key -> value)表示一个键值对
(6)scala具有类型推断功能,在可由上下文推断的情况下,可以省略类型,也可以省略分号
(7)类和方法修饰符的默认值:scala是public,java是protected
(8)scala不支持接口interface,采用trait(类似于Java的抽象类),Java支持接口。
(9)scala的return是可选的,方法调用会自动返回最后求值的表达式。如果scala使用了return,需要显示指定方法的返回值。java需要显示的使用return来进行值的返回。

持续更新中。。。。

来源:https://www.icode9.com/content-4-825701.html

(0)

相关推荐