简历 ——面试题1

熟练掌握java,熟悉scala、python语言, 了解Java和Scala的区别以及不同的使用场景,对JVM有一定程度的理解,掌握其类加载机制,运行时数据区。

●熟悉Hadoop生态圈,掌握HDFS、Yarn、MapReduce原理以及应用,

●熟练掌握 HBase 的读写过程、表的设计理念,协处理器的使用等操作。

●熟练操作 Hive 和 Spark SQL 的整合,进行数据查询,统计等并进行hive 调优等操作

●了解Zookeeper分布式协调框架,了解Zookeeper实现最终一致性的原理,知道如何利用Zookeeper构建高可用集群

●熟悉Kafka的运行机制,熟练掌握Kafka消息存储的原理,了解Consumer、Producer和Broker的各项参数及调优,知道Kafka的应用场景并与Spark Streaming整合

●熟悉Spark的整体架构、工作原理和RDD概念,具有Spark的调优经验,阅读过Spark Core的源码内容,对Spark的Shuffle机制有深刻理解,熟练使用Scala编写Spark程序

●熟悉Flink的整体架构和编程模型,熟练掌握Window的使用、Exactly-Once的原理和WaterMark解决乱序以及延迟数据的方法,知道Flink和Kafka的整合

●熟悉Flume日志采集、Sqoop数据迁移、Azkaban工作流任务调度器等工具的使用;


●熟悉相关模型搭建与训练过程,理解主流机器学习算法(SVM、Adaboost、GBDT、KNN、K-Means、CNN、RNN等)的原理及应用,能够利用训练模型,优化模型。

 

扫描二维码关注公众号,回复: 10528969 查看本文章

1、Java和Scala的区别

scala是运行在 JVM 上的多范式编程语言,同时支持面向对象面向函数编程 

scala最终被编译为.class文件,运行在JVM虚拟机中,其实本质上还是java, 所以在scala和java可以互调双方的api;兼容Java,可以访问庞大的Java类库

  1. scala中所有的类型都使用大写字母开头

  2. scala整型使用Int而不是Integer

  3. scala中定义变量可以不写类型,让scala编译器自动推断

  4. Scala函数,没有返回值用Unit,相当于java的void  。val 语句 定义函数。def 语句 定义方法。

  5. scala的return是可选的,方法调用会自动返回最后求值的表达式。如果scala使用了return则需要显示指定方法的返回值

  6. scala采用三个双引号“”“支持换行字符串,Java需要采用“+”进行字符串的连接。

      

2、JVM

  1. java文件经过编译之后变成class字节码文件
  2. 字节码文件通过类加载器被搬运到jvm虚拟机当中来
  3. 虚拟机当中主要有五大块
    1. 方法区:线程共享区域,存在多线程安全问题,主要存放全局变量,常量,静态变量等
    2. 堆:线程共享区域,存在多线程安全问题,主要存放对象实例和数组等
    3. 虚拟机栈:线程不同享区域,不存在多线程安全问题,主要存放局部变量等
    4. 本地方法栈:线程不共享区域,不存在多线程安全问题,主要负责去调用一些底层的C程序实现,一般不做研究
    5. 程序计数器:线程不共享区域,不存在多线程安全问题,一般不做研究

类加载机制:

类加载器负责加载class文件,将class文件字节码内容加载到内存中,并将这些内容转换成方法区中的运行时数据结构,并且ClassLoader只负责文件的加载,至于它是否可以运行,则由Execution Engine决定

从类被加载到虚拟机内存中开始,到卸御出内存为止,它的整个生命周期分为7个阶段:加载--验证--准备--解析--初始化--使用--卸御。其中验证、准备、解析三个部分统称为连接。

1、加载:

1、将class文件加载在内存中。

2、将静态数据结构(数据存在于class文件的结构)转化成方法区中运行时的数据结构。

3、在堆中生成一个代表这个类的java.lang.Class对象,作为数据访问的入口

2、连接:

1、验证:确保加载的类符合JVM规范与安全。保证被校验类的方法在运行时不会做出危害虚拟机安全的事件

2、准备:为static变量在方法区中分配空间,设置变量的初始值。例如static int a=3,在此阶段会a被初始化为0;

3、解析:解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。

3、初始化:为类的静态变量赋予正确的初始值

4、使用:正常使用

5、卸载:GC把无用的对象从内存中卸载

类的加载顺序:

1)Bootstrap ClassLoader:负责加载$JAVA_HOME中jre/lib/rt.jar里所有的 class,由 C++ 实现,不是 ClassLoader 子类。

2)Extension ClassLoader:负责加载Java平台中扩展功能的一些 jar 包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的 jar 包。

3)App ClassLoader:负责加载 classpath 中指定的 jar 包及目录中 class。

4)Custom ClassLoader:属于应用程序根据自身需要自定义的 ClassLoader,如 Tomcat、jboss 都会根据 J2EE 规范自行实现 ClassLoader。

先检查,再加载

检查类的顺序:是自底向上,从 Custom ClassLoader 到 BootStrap ClassLoader 逐层检查,只要某个 Classloader 已加载就视为已加载此类,保证此类只所有 ClassLoader 加载一次。

加载类的顺序:是自顶向下,也就是由上层来逐层尝试加载此类。

 

JVM在加载类时默认采用的是双亲委派机制

就是某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。

JVM运行时数据区域:由5块部分组成,分别是堆,方法区,虚拟机栈,本地方法栈,以及程序计数器组成。

可以根据内存是否线程共享划分成:线程独享内存区域/   线程共享内存区域。

栈管运行,堆管存储

1、堆

JVM内存,划分为堆内存和非堆内存,堆内存分为年轻代老年代,非堆内存就一个永久代

年轻代又分为EdenSurvivor区。Survivor区由FromSpaceToSpace组成。Eden区占大容量,Survivor两个区占小容量,默认比例是8:1:1。

堆内存用途:存放的是对象,垃圾收集器就是收集这些对象,然后根据GC算法回收。

非堆内存用途:永久代,也称为方法区,存储程序运行时长期存活的对象,比如类的元数据、方法、常量、属性等。

在jdk1.8当中已经不存在永久代这一说了,取而代之的是元数据区

2、方法区

方法区和java堆一样,是线程共享的区域;它存储了每一个类的结构信息

用来存储:已经被虚拟机加载的类信息、常量、静态变量等;

实例变量存在堆内存中,和方法区无关

3、虚拟机栈

虚拟机栈描述的是:Java方法执行的内存模型

虚拟机栈就是用来存储:局部变量、栈操作、动态链表、方法出口这些东西;这些东西有个特点:都是线程私有的,所以虚拟机栈是线程私有的

对于栈来说,不存在垃圾回收问题,只要程序执行结束,栈就over释放,生命周期和线程一致,是私有线程区域。

栈中的数据都是以栈帧(Stack Frame)的格式存在,栈帧是一个内存区块,是一个数据集,是一个有关方法(Method)和运行期数据的数据集,每个方法执行的同时都会创建一个栈帧,用于存储局部变量表等信息,每一个方法从调用直至执行完毕的过程,就对应着一个栈帧在虚拟机中入栈到出栈的过程。

栈的大小和具体JVM的实现有关,通常在256K~756K之间,与等于1Mb左右

4、本地方法栈

与虚拟机栈所发挥的作用是非常相似的,

区别是,虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native方法服务(比如C语言写的程序和C++写的程序)

5、程序计数器

是一块非常小的内存空间,主要是用来对当前线程所执行的字节码的行号指示器

程序计数器是内存区域中唯一 一块不存在OutOfMemoryError的区域

每个线程都有一个程序计数器,是线程私有的,就是一个指针,指向方法区中的方法字节码(用来存储指向下一条指令的地址,也即将要执行的指令代码),由执行引擎读取下一条指令,是一个非常小的内存空间,几乎可以忽略不记。

6、本地接口

作用是融合不同的编程语言为 Java 所用,它的初衷是融合 C/C++程序,目前该方法使用的越来越少了,除非是与硬件有关的应用

3、HDFS

Hadoop中的分布式文件系统,高容错(数据库blcok备份),可扩展

适合存储大文件,不适合存储小文件,不适合处理低延时的数据(HBase更好),

一次写入、多次读写,不支持多用户写入及任意修改文件

HDFS的三个核心组件是什么, 有什么作用?

(1)NameNode. 集群的核心, 是整个文件系统的管理节点. 负责存储HDFS集群的元数据,存在内存中 

(2)DataNode. 存放具体数据块的节点, 主要负责数据的读写, 定期向NameNode发送心跳,超过10分钟节点不可用,6小时上报当前DataNode上的块状态

(3)SecondaryNameNode. 辅助节点, 同步NameNode中的元数据信息, 辅助NameNode对fsimage和editsLog进行合,对HDFS元数据做checkpoint操作,每1分钟检查一次,每1小时创建一个检查点

集群的心跳机制,让集群中各节点形成一个整体;主节点知道从节点的死活

节点的上下线,导致存储的不均衡,可以手动触发负载均衡

元数据

关于文件或目录的描述信息,如文件所在路径、文件名称、文件类型等等,这些信息称为文件的元数据metadata
①编辑日志文件 edits log,保存至namenode中

edits log为hdfs-site.xml中属性dfs.namenode.edits.dir的值决定;用于namenode保存edits.log文件

②命名空间镜像文件 fsimage,保存磁盘中

将namenode内存中的元数据落入磁盘生成的文件;

fsimage为hdfs-site.xml中属性dfs.namenode.name.dir的值决定;用于namenode保存fsimage文件
 

HDFS写流程

请求上传——检查目录——可以上传——查询Datanode信息——分配datanode——建立数据流——发送数据

1、当客户端开始写入文件的时候,客户端会将文件切分成多个 packets,并在内部以数据队列“data queue(数据队列)”的形式管理这些 packets,并向 namenode 申请 blocks,获 取用来存储 replicas 的合适的 datanode 列表,列表的大小根据 namenode 中 replication 的设定而定;

2、开始以 pipeline(管道)的形式将 packet 写入所有的 replicas 中。客户端把 packet 以流的 方式写入第一个 datanode,该 datanode 把该 packet 存储之后,再将其传递给在此 pipeline 中的下一个 datanode,直到最后一个 datanode,这种写数据的方式呈流水线的形式。

3、最后一个 datanode 成功存储之后会返回一个 ack packet(确认队列),在 pipeline 里传递 至客户端,在客户端的开发库内部维护着"ack queue",成功收到 datanode 返回的 ack packet 后会从"data queue"移除相应的 packet。

4、如果传输过程中,有某个 datanode 出现了故障,那么当前的 pipeline 会被关闭,出现故 障的 datanode 会从当前的 pipeline 中移除,剩余的 block 会继续剩下的 datanode 中继续 以 pipeline 的形式传输,同时 namenode 会分配一个新的 datanode,保持 replicas 设定的 数量。

5、客户端完成数据的写入后,会对数据流调用 close()方法,关闭数据流;

HDFS读流程

1、客户端调用FileSystem 实例的open 方法,获得这个文件对应的输入流InputStream。

2、通过RPC 远程调用NameNode ,获得NameNode 中此文件对应的数据块保存位置,包括这个文件的副本的保存位置( 主要是各DataNode的地址) 。

3、获得输入流之后,客户端调用read 方法读取数据。选择最近的DataNode 建立连接并读取数据。如果客户端和其中一个DataNode 位于同一机器(比如MapReduce 过程中的mapper 和reducer),那么就会直接从本地读取数据。

4、到达数据块末端,关闭与这个DataNode 的连接,然后重新查找下一个数据块。不断执行第2 - 5 步直到数据全部读完。

5、客户端调用close ,关闭输入流DF S InputStream。
 

HDFS不适合存储小文件的原因:

NameNode存储着文件系统的元数据,每个文件、目录、块大概有150字节的元数据;

小文件数量多会大量占用namenode的内存; 使namenode读取元数据速度变慢, 启动时间延长; 还因为占用内存过大, 导致gc时间增加等.

解决办法:两个角度,

一是,从数据来源入手, 如每小时抽取一次改为每天抽取一次等方法来积累数据量.
二是,选择合并.HAR文件方案,Sequence Files方案

如果小文件无可避免, 一般就采用合并的方式解决. 可以写一个MR任务读取某个目录下的所有小文件, 并重写为一个大文件.

SequenceFile文件,是一种由header信息和一条条record记录组成的文件。每个record是键值对形式,小文件名作为当前record的键,小文件的内容作为当前record的值;
 

4、MapReduce

  •  是采用一种分而治之的思想设计出来的分布式计算框
  • 由两个阶段组成:
    • Map阶段(切分成一个个小的任务)
    • Reduce阶段(汇总小任务的结果)
  • MR输入的文件有几个block,就会生成几个map任务,MR的reduce任务的个数,由程序中编程指定:job.setNumReduceTasks(4)
  • map任务:
    • map任务一次读取block的一行数据,以kv对的形式输入map()
    • map()的输出作为reduce()的输入
  • reduce任务:
    • reduce任务通过网络将各map任务输出结果中,属于自己的数据取过来
    • key相同的键值对作为一组,调用一次reduce()
    • reduce任务生成一个结果文件
    • 文件写入HDFS
  • 1、shuffle

  • map端的shuffle
    (1)环形内存缓冲:

    每个map任务都有一个对应的环形内存缓冲区;map()输出kv对,先写入到环形缓冲区(默认大小100M),当内容占据80%缓冲区空间后,由一个后台线程将缓冲区中的数据溢出写到一个磁盘文件。

    在溢出写的过程中,map任务可以继续向环形缓冲区写入数据;但是若写入速度大于溢出写的速度,最终造成100m占满后,map任务会暂停向环形缓冲区中写数据的过程;只执行溢出写的过程;直到环形缓冲区的数据全部溢出写到磁盘,才恢复向缓冲区写入

    (2)后台线程溢写磁盘过程,

    (1)分区:先对每个溢写的kv对做分区;分区的个数由MR程序的reduce任务数决定;默认使用HashPartitioner计算当前kv对属于哪个分区;计算公式:(key.hashCode() & Integer.MAX_VALUE) % numReduceTasks

    (2)排序: 每个分区中,根据kv对的key做内存中排序;

    (3)combine(可选):若设置了map端本地聚合combiner,则对每个分区中,排好序的数据做combine操作;

    (4)压缩(可选):若设置了对map输出压缩的功能,会对溢写数据压缩

    reduce端的shuffle
    (1)拉取

    reduce task会在每个map task运行完成后,通过HTTP获得map task输出中,属于自己的分区数据(许多kv对)

    如果map输出数据比较小,先保存在reduce的jvm内存中,否则直接写入reduce磁盘

    (2)归并merge:

    一旦内存缓冲区达到阈值(默认0.66)或map输出数的阈值(默认1000),则触发归并merge,结果写到本地磁盘

    (3)combine(可选):若MR编程指定了combine,在归并过程中会执行combine操作

    2、什么是数据倾斜?

    数据中不可避免地会出现离群值(outlier),并导致数据倾斜。这些离群值会显著地拖慢MapReduce的执行。

    常见的数据倾斜有以下几类:

    数据频率倾斜——某一个区域的数据量要远远大于其他区域。比如某一个key对应的键值对远远大于其他键的键值对。

    数据大小倾斜——部分记录的大小远远大于平均值。

    在map端的数据倾斜可以考虑使用combine

    在reduce端的数据倾斜常常来源于MapReduce的默认分区器

    数据倾斜会导致map和reduce的任务执行时间大为延长,也会让需要缓存数据集的操作消耗更多的内存资源

  • 如何诊断是否存在数据倾斜
    如何诊断哪些键存在数据倾斜?

    发现倾斜数据之后,有必要诊断造成数据倾斜的那些键。有一个简便方法就是在代码里实现追踪每个键的最大值。

    为了减少追踪量,可以设置数据量阀值,只追踪那些数据量大于阀值的键,并输出到日志中。实现代码如下

    运行作业后就可以从日志中判断发生倾斜的键以及倾斜程度;跟踪倾斜数据是了解数据的重要一步,也是设计MapReduce作业的重要基础

  • 如何减缓数据倾斜
    Reduce数据倾斜,一般是指map的输出数据中存在数据频率倾斜的状况,即部分输出键的数据量远远大于其它的输出键

    如何减小reduce端数据倾斜的性能损失?常用方式有:

    一、自定义分区
    基于输出键的背景知识进行自定义分区。

    例如,如果map输出键的单词来源于一本书。其中大部分必然是省略词(stopword)。那么就可以将自定义分区将这部分省略词发送给固定的一部分reduce实例。而将其他的都发送给剩余的reduce实例。

    二、Combine
    使用Combine可以大量地减小数据频率倾斜和数据大小倾斜。

    combine的目的就是聚合并精简数据。

    三、抽样和范围分区
    Hadoop默认的分区器是HashPartitioner,基于map输出键的哈希值分区。这仅在数据分布比较均匀时比较好。在有数据倾斜时就很有问题。

    使用分区器需要首先了解数据的特性。TotalOrderPartitioner中,可以通过对原始数据进行抽样得到的结果集来预设分区边界值。

    TotalOrderPartitioner中的范围分区器可以通过预设的分区边界值进行分区。因此它也可以很好地用在矫正数据中的部分键的数据倾斜问题。

    四、数据大小倾斜的自定义策略
    在map端或reduce端的数据大小倾斜都会对缓存造成较大的影响,乃至导致OutOfMemoryError异常。处理这种情况并不容易。可以参考以下方法。

    设置mapreduce.input.linerecordreader.line.maxlength来限制RecordReader读取的最大长度

    RecordReader在TextInputFormat和KeyValueTextInputFormat类中使用。默认长度没有上限

5、YARN

主节点 ResourceManager:调度器Scheduler / Application Master应用程序的管理器,

从节点NodeManager

Client 向 ResourceManager 提交的每一个应用程序都必须有一个 ApplicationMaster,它经过 ResourceManager 分配资源后,运行于某一个 Slave 节点的 Container 中,具体做事情的 Task,同样也运行与某一个 Slave 节点的 Container 中。

1)Resource Manager:全局资源管理器
一个集群只有一个RM。
负责和AM(Application Master)交互,资源调度、资源分配等工
2)Node Manager:一台机器上的管理者,
类似于部门经理。
管理着本机上若干小弟Containers的生命周期、监视资源和跟踪节点健康并定时上报给RM;接收并处理来自AM的Container启动/停止等各种请求。
3)Application Master:应用程序的管理器,
类似项目经理,一个应用程序只有一个AM。
负责任务开始时找RM要资源,任务完成时向RM注销自己,释放资源;
与NM通信以启动/停止任务;接收NM同步的任务进度信息。
ApplicationMaster可以在容器内运行任何类型的任务,不同的 ApplicationMaster 被分布到不同的节点上,因此它们之间不会相互影响。
4)Container:一台机器上具体提供运算资源,
将设备上的内存、CPU、磁盘、网络等资源封装在一起的抽象概念——“资源容器”,
Container是一个动态资源分配单位,为了限定每个任务使用的资源量。

Application在Yarn中的执行过程,整个执行过程可以总结为三步:

应用程序提交
启动应用的ApplicationMaster实例
ApplicationMaster 实例管理应用程序的执行

精简版的:

步骤1:客户端程序向 ResourceManager 提交应用,请求一个 RM的ApplicationMaster 实例,并请求传递给RM的scheduler(调度器);调度器分配container(容器)
步骤2:ResourceManager 找到一个可以运行一个 Container 的 NodeManager,并在这个 Container 中启动 ApplicationMaster 实例;

步骤3:ApplicationMaster 与 ResourceManager 注册进行通信,为内部要执行的任务申请资源,一旦得到资源后,将于 NodeManager 通信,以启动对应的 Task;
步骤4:所有任务运行完成后,ApplicationMaster 向 ResourceManager 注销,整个应用程序运行结束。

在YARN中有三种调度器可以选择:FIFO Scheduler ,Capacity Scheduler,FairS cheduler

熟练掌握 HBase 的读写过程、表的设计理念,协处理器的使用等操作。

6、hbase

是构建在 HDFS上的分布式数据库

HDFS 缺点:不支持小文件,不支持并发写,不支持文件随机修改,查询效率也低 。

HBase 却是一个支持百万级别高并发写入,支持实时查询,适合存储稀疏数据的分布式数据库系统。

HBase 主要用于大数据领域,MySQL 是行式存储,HBase 是列式存储。

启动时,需要提前启动 HDFS 及 ZooKeeper集群

 rowkey行键 - Column - Family列族  - Column列 - cell单元格  - Timestamp时间戳

HMaster- HRegionServer- Region

Region

  • HBase集群中分布式存储的最小单元
  • 一个Region对应一个Table表的部分数据

HBase是一个分布式的NoSql数据库,在实际工作当中,我们一般都可以通过JavaAPI来进行各种数据的操作,包括创建表,以及数据的增删改查等等

在这里插入图片描述
一个HRegionServer会负责管理很多个region  ,一个region包含很多个store
  * 一个列族就划分成一个tore

一个store里面只有一个memstore
  * memstore是一块**内存区域**,写入的数据会先写入memstore进行缓冲,然后再把数据刷到磁盘


* 一个store里面有很多个**==StoreFile==**, 最后数据是以很多个**==HFile==**这种数据结构的文件保存在HDFS上
  * StoreFile是HFile的抽象对象,如果说到StoreFile就等于HFile
  * ==每次memstore刷写数据到磁盘,就生成对应的一个新的HFile文件出来==

hbase读取数据流程.png

hbase写数据流程.png

协处理器

Hbase 作为列族数据库最经常被人诟病的特性包括:无法轻易建立“二级索引”,难以执行求和、计数、排序等操作。

比如,在旧版本的(<0.92)Hbase 中,统计数据表的总行数,需 要使用 Counter 方法,执行一次 MapReduce Job 才能得到。
虽然 HBase 在数据存储层中集成了 MapReduce,能够有效用于数据表的分布式计算。然而在很多情况下,做一些简单的相加或者聚合计算的时候, 如果直接将计算过程放置在 server端,能够减少通讯开销,从而获得很好的性能提升。


于是, HBase 在 0.92 之后引入了协处理器(coprocessors),实现一些激动人心的新特性:能够轻易建立二次索引、复杂过滤器(谓词下推)以及访问控制等


协处理器有两种:Observer协处理器    endpoint协处理器

  • Observer协处理器:
    • 类似于 传统数据库中的触发器,主要在服务端工作
    • 允许集群在正常的客户端操作过程中,可以有不同的行为表现
    • 可以实现权限管理、优先级设置、监控、 ddl 控制、 二级索引等功能
  • endpoint协处理器
    • 类似于 传统数据库中的存储过程,主要在 client 端工作
    • 允许扩展集群的能力,对客户端应用开放新的运算命令
    • 可以实现 min、 max、 avg、 sum、 distinct、 group by 等功能

协处理器的加载方式有两种

  • 静态加载  修改 hbase-site.xml 
  • 动态加载 启用表aggregation,只对特定的表生效。


HBase表的rowkey设计 (三原则)
长度原则、散列原则、唯一原则

  • rowkey长度原则
    • rowkey是一个二进制码流,可以是任意字符串,最大长度64kb,实际应用中一般为10-100bytes,以byte[]形式保存,一般设计成定长。
    • 建议尽可能短;但是也不能太短,否则rowkey前缀重复的概率增大
    • 设计过长:会降低memstore内存的利用率和HFile存储数据的效率。
  • rowkey散列原则
    • 建议将rowkey的高位:作为散列字段,这样将提高数据均衡分布在每个RegionServer,以实现负载均衡的几率。
    • 如果没有散列字段,首字段直接是时间信息。所有的数据都会集中在一个RegionServer上,这样在数据检索的时候负载会集中在个别的RegionServer上,造成热点问题,会降低查询效率。
  •  rowkey唯一原则
    • 必须在设计上保证其唯一性,rowkey是按照字典顺序排序存储的
    • 因此,设计rowkey的时候,要充分利用这个排序的特点,可以将经常读取的数据存储到一块,将最近可能会被访问的数据放到一块

什么是热点
检索habse的记录首先要通过row key来定位数据行。
当大量的client访问hbase集群的一个或少数几个节点,造成少数region server的读/写请求过多、负载过大,而其他region server负载却很小,就造成了“热点”现象。
热点的解决方案(预分区 、加盐 、 哈希、 反转)

  • 预分区:目的让表的数据可以均衡的分散在集群中,而不是默认只有一个region分布在集群的一个节点上。
  • 加盐:在rowkey的前面增加随机数,具体就是给rowkey分配一个随机前缀以使得它和之前的rowkey的开头不同
  • 哈希:使同一行永远用一个前缀加盐。哈希也可以使负载分散到整个集群,但是读却是可以预测的。使用确定的哈希可以让客户端重构完整的rowkey,可以使用get操作准确获取某一个行数据。
  • 反转:反转固定长度或者数字格式的rowkey。这样可以使得rowkey中经常改变的部分(最没有意义的部分)放在前面。

5、Hive

熟练操作 Hive 和 Spark SQL 的整合,进行数据查询,统计等并进行hive 调优等操作

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

本质是:将SQL转换为MapReduce任务进行运算,底层由HDFS来提供数据的存储,

说白了hive可以理解为一个将SQL转换为MapReduce的任务的工具,甚至更进一步可以说hive就是一个MapReduce的客户端

mr代码非常复杂的通过hive大大的简化了mr的开发,基本上hive可以解决90%的企业开发需求,hive就是mr的一个客户端,没有集群

底层的hadoop:数据存储hdfs,数据的计算mr,运行在yarn上面的

怎么把hive翻译成的mr的

主要就是通过解析器的,就是将sql语法解析成为mr的任务
解析器:主要就是用于解析sql语法
编译器:将解析之后的sql语法进行编译成为MR的任务
优化器:有一定的优化功能,自动的会对我们写的sql语句进行调优,调优的功能有限的
执行器:提交mr的任务到yarn上面去执行的
 

大数据领域里面一个sql on hadoop的框架
主要的作用是:通过解析hql语句,实现hdfs上面的数据的查询操作
真实的数据保存在hdfs上面的,数据的计算,使用的mr的程序
hive不提供数据的存储,也不提供数据的计算
hive当中建库建表的元数据信息保存在mysql里面
Hive 只适合用来做海量离线数据统计分析,也就是数据仓库
每执行一次查询,就会有对应的mr任务执行吗?
不一定的,有些查询,不需要mr的参与

hive优缺点:

优点

(1)操作接口采用类SQL语法,提供快速开发的能力(简单、容易上手)。

(2)避免了去写MapReduce,减少开发人员的学习成本。

(3)Hive支持用户自定义函数,用户可以根据自己的需求来实现自己的函数。

缺点
(1)Hive 不支持记录级别的增删改操作

(2)Hive 的查询延迟很严重

(3)Hive 不支持事务
 

QL语言共分为四大类:数据查询语言DQL,数据操纵语言DML,数据定义语言DDL,数据控制语言DCL。

1. 数据查询语言DQL:SELECT子句,FROM子句,WHERE

2 .数据操纵语言DML:1) 插入:INSERT、2) 更新:UPDATE、3) 删除:DELETE

3. 数据定义语言DDL
来创建数据库中的各种对象-----表、视图、索引、同义词、聚簇等如:
CREATE TABLE/VIEW/INDEX/SYN/CLUSTER表 视图 索引 同义词 簇

DDL操作是隐性提交的!不能rollback

4. 数据控制语言DCL
用来授予或回收访问数据库的某种特权,并控制数据库操纵事务发生的时间及效果,对数据库实行监视等。如:

GRANT:授权、2) ROLLBACK 回滚、3) COMMIT :提交。
 

hive的几种表
内部表:

创建内部表的时候,没有external关键字;
删除内部表的时候,会同步的删除hdfs的数据
外部表:

创建外部表的时候有external关键字;
删除外部表的时候,不会删除hdfs的数据
外部表删的只是表结构, 数据存在hdfs,元数据在mysql
分区表:

实际工作当中,数据一般都是按照每天进行采集的,每天的数据都会放到某一个日期文件夹,
分区表,就是分文件夹
分桶表:

直接对数据进行分桶,分成多个文件,每个文件里面保存部分数据,到时候如果需要获取数据的时候,可以直接从对应的文件里面获取即可
分桶将整个数据内容,按照某列属性值取hash值进行区分,具有相同hash值的数据进入到同一个文件中
可以过滤掉大量不相关的文件,提高查询效率
分桶表就是分文件,将一个大的文件分成多个小的文件,提高查询效率
外部表一般都是用在数据仓库的ODS层

内部表一般都是用在数据仓库的DW层
 

4个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。
 

SparkSQL整合hive

由于hive原生是基于MapReduce的,导致其查询耗时较长。
为了保留Hive的架构解决方案,并优化查询速度,采用SparkSql与hive整合(spark on hive),通过SparkSql读取hive中表的元数据,把HiveHQL底层采用MapReduce处理任务导致性能慢的特点,改为更加强大的Spark引擎来进行相应的计算处理。

Spark SQL的其中一个分支就是Spark on Hive,就是使用Hive中HQL的解析逻辑、执行计划翻译、执行计划优化等逻辑,近似认为仅将物理执行计划从MR作业替换成了Spark作业。
Spark SQL整合hive就是获取hive表中的元数据信息(在mysql中),然后通过Spark SQL来操作数据。

整合步骤:

1、拷贝hive配置文件到spark

hive 目录中conf目录下的hive-site.xml,hive的元数据信息在node03的mysql数据库中,而整合需要spark能够读取找到Hive的元数据以及数据存放位置

2、拷贝mysql驱动到spark

3 启动:启动HDFS,YARN集群;启动spark集群;启动hive;启动spark sql

可以像在spark-sql中操作hive中的数据库和表,表明整合成功。
 

--数据操纵语言DML

--alter
--#将stu内部表改为外部表
alter table stu set tblproperties('EXTERNAL'='TRUE');
--#把emp外部表改为内部表
alter table teacher set tblproperties('EXTERNAL'='FALSE');
--#修改表的名称
alter table stu3 rename to stu4;
--#增加列
alter table stu4 add columns(address string);

--数据查询语言DQL
-- select
select * from stu;
select id,name as stuName from stu; -- "as" 列改名
select count(*) cnt from score;
select max(s_score) from score; --- min(s_score) sum(s_score) avg(s_score)
select  * from score limit 5;--limit子句用于限制返回的行数。
select  * from score where s_score > 60;

--计算每个学生的平均分数  	Group By 语句通常会和==聚合函数==一起使用
select s_id,avg(s_score) from score group by s_id;

--求每个学生平均分数大于60的人 having针对=查询结果中的列=发挥作用
select s_id,avg(s_score) as avgScore from score2
group by s_id having avgScore > 60;

--Hive支持通常的SQL JOIN语句,但是只支持等值连接,不支持非等值连接
--inner join(默认) left outer join  right outer join full outer join
--根据学生和成绩表,查询学生姓名对应的成绩
select * from stu left join score on stu.id = score.s_id;

--按照学生分数的平均值排序
select s_id,avg(s_score) avgscore  from score 
group by s_id
order by avgscore desc; --全局排序,只有一个reduce asc默认升序

--条件函数
select if(1=2,100,200) from tableName;--200  if
select coalesce(null,'100','50') from tableName;--100 非空查找函数: COALESCE
--、条件判断函数:CASE  
Select case 100 when 50 then 'tom' when 100 then 'mary' else 'tim' end from tableName;
select case when 1=2 then 'tom' when 2=2 then 'mary' else 'tim' end from tableName;

hive的企业级调优
1. Fetch抓取:对某些情况的查询可以不必使用MapReduce计算
配置:hive-default.xml.template文件中 hive.fetch.task.conversion默认是more
老版本hive默认是minimal,该属性修改为more以后,在全局查找、字段查找、limit查找等都不走mapreduce。
把 hive.fetch.task.conversion设置成none,然后执行查询语句,都会执行mapreduce程序
把hive.fetch.task.conversion设置成more,然后执行查询语句,查询方式都不会执行mr程序


2. 本地模式:如果数据量小,只启动一个Maptask

默认情况下是启用hadoop的job模式,把任务提交到集群中运行,这样会导致计算非常缓慢;
配置:开启本地模式,并执行查询语句   set hive.exec.mode.local.auto=true; //开启本地mr


3. 表的优化

老版本hive,大小表 join 时,小表放在join的左边

多个表关联时,最好分拆成小段,避免大sql(无法控制中间Job)

大表 join 大表 时,空 key 过滤 ,空 key 赋一个随机的值  配置:set hive.auto.convert.join = true;

map join ,在Map端先进行部分聚合,最后在Reduce端得出最终结果

count distinct,使用先group by 再count的方式替换

 

4、使用分区剪裁、列剪裁 ,尽可能早地过滤掉尽可能多的数据量,避免大量数据流入外层SQL。
尽量使用分区过滤,少用select *

5. 并行执行,把一个sql语句中没有相互依赖的阶段,并行去运行,提高集群资源利用率
配置:set hive.exec.parallel=true; set hive.exec.parallel.thread.number=16;


6.开启严格模式,防止用户执行,那些可能意想不到的不好的影响的查询。
配置:set hive.mapred.mode=strict; 默认是非严格模式nonstrict
开启严格模式可以禁止3种类型的查询。
对于分区表,除非where语句中含有分区字段过滤条件来限制范围,否则不允许执行
对于使用了order by语句的查询,要求必须使用limit语句
限制笛卡尔积的查询


9.开启数据的压缩,Hive表中间数据压缩Hive表最终输出结果压缩


10.避免数据倾斜

1 合理设置Map数  2 小文件合并 3 复杂文件增加Map数 4 合理设置Reduce数

了解Zookeeper分布式协调框架,了解Zookeeper实现最终一致性的原理,知道如何利用Zookeeper构建高可用集群

6、zookeeper

ZooKeeper 是分布式应用程序的协调服务(service)主从架构 leader;follower或observer

ZooKeeper 提供了文件系统通知机制,维护和监控 存储的数据的 状态变化,通过监控这些数据状态的变化,从而达到基于数据的 集群管理,主要用来解决分布式集群中应用系统的一致性问题

一致性,是指数据在多个副本之间保持一致的特性

为了保证事务的顺序一致性,ZooKeeper采用了递增的事务id号(zxid)来标识事务,所有提议(proposal)都有zxid

ZooKeeper = ① 简版文件系统(Znode) + ② 原语 基本命令 + ③通知机制(Watcher)。

zookeeper实现数据一致性的核心是ZAB协议(Zookeeper原子消息广播协议)。该协议需要做到以下几点:
(1)集群在半数以下节点宕机的情况下,能正常对外提供服务;
(2)客户端的写请求,全部转交给leader来处理,leader需确保写变更能实时同步给所有follower及observer;
(3)leader宕机或整个集群重启时,需要确保那些已经在leader服务器上提交的事务最终被所有服务器都提交,确保丢弃那些只在leader服务器上被提出的事务,并保证集群能快速恢复到故障前的状态。
       

Zab协议有两种模式, 恢复模式(选主),广播模式(同步)

选主分两种情况:全新集群leader选举、非全新集群leader选举

集群中过半数Server启动后,才能选举出Leader;

投票信息vote信息结构为(sid, zxid),服务器ID,事务ID

zxid大的server胜出;zxid相等,sid大的胜出

选主后的数据同步,

leader构建NEWLEADER封包,包含leader中最大的zxid值;广播给其它follower
follower收到后,如果自己的最大zxid小于leader的,则需要与leader状态同步;否则不需要
leader给需要同步的每个follower创建LearnerHandler线程,负责数据同步请求
leader主线程等待LearnHandler线程处理结果
只有多数follower完成同步,leader才开始对外服务,响应写请求
 

HDFS HA方案,主要分两部分:①元数据同步 ②主备切换

在同一个HDFS集群,运行两个互为主备的NameNode节点 ,在主备切换过程中,新的Active NameNode必须确保与原Active NamNode元数据同步完成,才能对外提供服务 。

JournalNode集群作为共享存储系统;,客户端对HDFS做操作 ,同时会记录到JournalNode集群,存储HDFS新产生的元数据

当有新数据写入JournalNode集群时,Standby NameNode能监听到此情况,将新数据同步过来 。这样,Active NameNode(写入)和Standby NameNode(读取)实现元数据同步 。

每个NameNode节点上各有一个ZKFC进程 ,ZKFC会监控NameNode的健康状况,当发现Active NameNode异常时,通过Zookeeper集群进行namenode主备选举,完成Active和Standby状态的切换

 

 

 

 

 

 

 

●熟悉Flink的整体架构和编程模型,熟练掌握Window的使用、Exactly-Once的原理和WaterMark解决乱序以及延迟数据的方法,知道Flink和Kafka的整合

●熟悉Flume日志采集、Sqoop数据迁移、Azkaban工作流任务调度器等工具的使用;


●熟悉相关模型搭建与训练过程,理解主流机器学习算法(SVM、Adaboost、GBDT、KNN、K-Means、CNN、RNN等)的原理及应用,能够利用训练模型,优化模型。

发布了77 篇原创文章 · 获赞 25 · 访问量 9202

猜你喜欢

转载自blog.csdn.net/TU_JCN/article/details/104841818