大数据知识点总结

前言

hi!我是啊晨 ,一个大数据分享者,好久没发博客了,最近忙于找工作,然后顺带整理了一些资料,相信也有一部分好兄弟,也在苦于找工作,或者正在学习大数据的知识,不太会总结的。我只能这样说,你来对了。
这里大概的罗列了一些,面试常会问频率高一些的点,或者我面试遇到的一些问题,不是很全面,后续会补充,很多但没废话。
也可以阅读我的其它大数据文章,抱拳!
中间有什么问题好兄弟们一定要留言:

在这里插入图片描述

正片

语言工具类

这里只针对可能会面试到的,像Scala、Python面试也没啥问的,这里就不列举了

Java

实现线程的两种方式

1、继承Thread类,重写run方法
2、实现Thread类的Runnable接口,重写run方法

两者区别:1不会共享线程,四个都是100张票,2会共享线程,多数采用第二种方式。

集合

List集合

有序可重复
add添加
get获取索引位置元素
remove 移除
set 设置
listiterator 特有迭代器

ArrayList

大小可变的数组的实现。
有序可重复,线程不安全。

初识为10,容量一般是1.5倍扩容。

遍历方式:
迭代器
list特有的
for:一般for和增强for(1.5jdk的新特性)

LinkedList

有序,可重复,底层双向链表。

和ArrayList、vector区别:
linkedlist 增删快,查询慢,线程不安全
ArrayList 增删慢,查询快,线程不安全
vector 线程安全,用法同ArrayList

Set集合

不重复,无序

HashSet

对于自定义类,需要手动进行去重的操作。
重写hashCode与equals方法。

储存原理:
① 调用对象的hashCode方法算出对象的哈希码值,通过该值经过哈希算法,算出该对象在该集合中存储的位置。
② 如果该位置没有元素,就直接放置在该位置,但是如果该位置有元素,此现象称为哈希冲突也叫哈希碰撞,会 通过equals方法比较该位置的两个对象,如果相等,则不插入。
③ 如果不相等,会在该位置下以线性链表的形式插入。但是在1.8jdk之后,当线性链表长度大于等于8时,该结构 改为 红黑树的结构。(1.8jdk之后,发生哈希冲突,以链表+红黑树的形式存储。)

构造方法:hashset()初识容量是16

二叉查找树

左侧的节点永远小于根节点,右侧的节点永远大于根节点。

红黑树 就是一种自平衡二叉查找树。

TreeSet

基于红黑树的实现,无序不重复,可排序

排序实现comparable接口,实现compareTo方法

LinkedHashset

用于购物车,有不重复
链表+哈希表

collections 集合工具类

Stack 栈:先进后出
Queue 队列:先进先出

Map集合

collection 单列集合:每个储存元素都是一个对象
map:双列集合,键值对

put 添加、get获取、remove 移除、size长度

map的子类:
HashMap:底层 哈希表结构。

遍历:
list集合遍历 : 1》 迭代器 2》 for循环 3 3》 ListIterator set集合 : 1》 迭代器 2》 for循环 (增强for循环 )

① keySet() 返回key的set集合形式。
② entrySet() 返回entry形式的set集合

TreeMap

HashMap: key的特性: 无序 不重复 .底层是哈希表

TreeMap: key的特性: 可排序 不重复 。底层是红黑树。

HashTable

HashTable :哈希表 。线程安全的
与HashMap区别 :
① HashMap 线程不安全的。
② HashTable 线程安全的。

JVM

JVM内存分哪几个区,每个区的作用是什么?
在这里插入图片描述

方法区:(被加载的信息,常量,静态变量编译后的代码等数据)

a.有时候也成为永久代,在该区内很少发生垃圾回收,但是并不代表不发生GC,在这里进行的GC主要是对方法区里的常量池和对类型的卸载

b.方法区主要用来存储已被虚拟机加载的类的信息、常量、静态变量和即时编译器编译后的代码等数据。

c.该区域是被线程共享的。

d.方法区里有一个运行时常量池,用于存放静态编译产生的字面量和符号引用。该常量池具有动态性,也就是说常量并不一定是编译时确定,运行时生成的常量也会存在这个常量池中。

虚拟机栈:(java方法服务,储存局部变量方法出口等)

所称的栈内存,它为java方法服务,每个方法在执行的时候都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接和方法出口等信息。
虚拟机栈是线程私有的,它的生命周期与线程相同。
局部变量表里存储的是基本数据类型、returnAddress类型(指向一条字节码指令的地址)
和对象引用,这个对象引用有可能是指向对象起始地址的一个指针,也有可能是代表对
象的句柄或者与对象相关联的位置。局部变量所需的内存空间在编译器间确定
操作数栈的作用主要用来存储运算结果以及运算的操作数,它不同于局部变量表通过索
引来访问,而是压栈和出栈的方式

本地方法栈

和虚拟机栈类似,只不过本地方法栈为Native(本地)方法服务。

堆(对象实例创建,垃圾回收操作)

所有线程所共享的一块内存,在虚拟机启动时创建,几乎所有的对象实例都在这里创建,因此该区域经常发生垃圾回收操作。

程序计数器

分支、循环、跳转、异常处理和线程恢复等功能都需要依赖这个计数器完成,该内存区
域是唯一一个java虚拟机规范没有规定任何OOM(内存用完了)情况的区域。

Java自带哪几种线程池?(4)

1)newCachedThreadPool(缓存)

可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
工作线程的【创建数量几乎没有限制】(其实也有限制的,数目为Interger.
MAX_VALUE),这样可灵活的往线程池中添加线程。【注意控制任务数量,同时大量运行可能系统瘫痪】

如果长时间没有往线程池中提交任务,即如果工作线程空闲了指定的时间(默认为1
分钟),则该工作线程将自动终止。终止后,如果你又提交了新的任务,则线程池重新创
建一个工作线程。
在使用CachedThreadPool时,一定要注意控制任务的数量,否则,由于大量线程同时
运行,很有会造成系统瘫痪。

2)newFixedThreadPool(固定)

创建一个指定工作线程数量的线程池。
没提交一个任务就创建一个工作线程,达到最大,将任务存入池队列。
典型优秀的线程池,提高程序效率节省创建开销。但是如果没【运行任务时,不会释放,占用系统资源。】

3)newSingleThreadExecutor(单线程)

单线程话的executor,唯一的线程执行任务,指定顺序(FIFO,LIFO,优先级)执行。
【顺序执行各个任务,任意时间不会有多个线程】

4)newScheduleThreadPool(时间)

创建一个【定长的线程池】,而且支持【定时的以及周期性的任务执行】,支持定时及周期性任务执行。【延迟3秒执行】。

HashMap和HashTable区别

1)线程安全性不同

【HashMap是线程不安全的】,【HashTable是线程安全的】,其中的方法是【Synchronize】的,【多线程并发】,可直接【hashtable】,【hashmap必须加同步处理】

2)是否提供contains方法

HashMap只有containsValue和containsKey方法;
HashTable有contains、containsKey
和containsValue三个方法,其中contains和containsValue方法功能相同。

3)key和value是否允许null值

HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。
Hashtable中,key和value都不允许出现null值。

4)数组初始化和扩容机制

HashMap不指定容量默认为16,HashTable为11。
Hashtable不要求底层数组的容量一定要为2的整数次幂,而HashMap则要求一定为2的整数次幂。
HashMap扩容变2倍,Hashtable2倍加1

TreeSet和HashSet区别

HashSet是采用【hash表】来实现的。其中的元素【没有按顺序排列】,add()、remove()以及contains()等方法都是复杂度为O(1)的方法。
【无序,访问遍历快】
TreeSet是采用树结构实现(【红黑树算法】)。元素是【按顺序进行排列】,但是add()、
remove()以及contains()等方法都是复杂度为O(log(n))的方法。
【有序,排序用】

Stringbuffer和Stringbuild区别

方法和功能是等价的
【StringBuffer】采用了synchronized关键字进行修饰,因此是【线程安全的】,而【StringBuilder】没有这个修饰,可以被认为是线程【不安全的。】
单线程程序下,StringBuilder效率快,StringBuffer相对慢

Final、Finally、Finalize

final:修饰符(关键字)有三种用法:修饰类、变量和方法。
(修饰类时,意味着它不能再派生出新的子类,即不能被继承,因此它和abstract是反义词。修饰变量时,该变量使用中不被改变,必须在声明时给定初值,在引用中只能读取不可修改,即为常量。修饰方法时,也同样只能使用,不能在子类中被重写。)
finally:通常放在【try…catch】的后面构造最终执行代码块,这就意味着程序【无论正常执
行还是发生异常,这里的代码只要JVM不关闭都能执行】,可以将【释放外部资源的代码写在
finally块中。】
finalize:Object类中定义的方法,Java中允许使用finalize()方法在垃圾收集器将对象
从【内存中清除】出去之前做必要的【清理工作】。这个方法是由【垃圾收集器】在销毁对象时调用的,通过重写finalize()方法可以【整理系统资源】或者执行【其他清理工作。】

==和Equals区别

== :如果比较的是基本数据类型,那么比较的是变量的值,如果比较的是引用数据类型,那么比较的是地址值(两个对象是否指向同一块内存) equals:如果没重写equals方法比较的是两个对象的地址值。如果重写了equals方法后我们往往比较的是对象中的属性的内容
equals方法是从Object类中继承的,默认的实现就是使用 ==

在这里插入图片描述

Java类加载过程?

1)加载

加载时类加载的第一个过程,在这个阶段,将完成一下三件事情:
a.通过一个类的全限定名获取该类的二进制流。
b.将该二进制流中的静态存储结构转化为方法去运行时数据结构。
c.在内存中生成该类的Class对象,作为该类的数据访问入口

2)验证

验证的目的是为了确保Class文件的字节流中的信息不回危害到虚拟机.在该阶段主要完成
以下四钟验证:
a.文件格式验证:验证字节流是否符合Class文件的规范,如主次版本号是否在当前虚拟
机范围内,常量池中的常量是否有不被支持的类型.
b.元数据验证:对字节码描述的信息进行语义分析,如这个类是否有父类,是否集成了不
被继承的类等。
c.字节码验证:是整个验证过程中最复杂的一个阶段,通过验证数据流和控制流的分析,确定程序语义是否正确,主要针对方法体的验证。如:方法中的类型转换是否正确,跳
转指令是否正确等。
d.符号引用验证:这个动作在后面的解析过程中发生,主要是为了确保解析动作能正确执
行。
e.准备
准备阶段是为类的静态变量分配内存并将其初始化为默认值,这些内存都将在方法区中进行
分配。准备阶段不分配类中的实例变量的内存,实例变量将会在对象实例化时随着对象一起
分配在Java堆中。

3)解析

该阶段主要完成符号引用到直接引用的转换动作。解析动作并不一定在初始化动作完成之前,也有可能在初始化之后。

4)初始化

初始化时类加载的最后一步,前面的类加载过程,除了在加载阶段用户应用程序可以通过自定义类加载器参与之外,其余动作完全由虚拟机主导和控制。到了初始化阶段,才真正开始执行类中定义的Java程序代码。

java中垃圾收集的方法?

1)引用计数法

(每引用回收,需要维护一个引用计算器)

应用于:微软的COM/ActionScrip3/Python等
a)如果对象没有被引用,就会被回收,缺点:需要维护一个引用计算器

2)复制算法

(效率高,内存需求大.使用在占空间比较小刷新次数多的新生区)

年轻代中使用的是MinorGC,这种GC算法采用的是复制算法(Copying)
a)效率高,缺点:需要内存容量大,比较耗内存
b)使用在占空间比较小、刷新次数多的新生区

3)标记清除

(效率低,会产生碎片)

老年代一般是由标记清除或者是标记清除与标记整理的混合实现
a)效率比较低,会差生碎片

4)标记压缩

(效率低速度慢,需要移动对象,但不会产生碎片)

老年代一般是由标记清除或者是标记清除与标记整理的混合实现
a)效率低速度慢,需要移动对象,但不会产生碎片。

5)标记清除压缩

(使用占空间大刷新次数小的养老区,3,4的集合体)

标记清除标记压缩的集合,多次GC后才Compact
a)使用于占空间大刷新次数少的养老区,是34的集合体

如何判断一个对象是否存活?(或者GC对象的判定方法)

引用计数法
可达性算法(引用链法)

什么是类加载器,类加载器有哪些?

实现通过类的权限定名获取该类的二进制字节流的代码块叫做类加载器。

主要有一下四种类加载器:
1)启动类加载器(BootstrapClassLoader)用来加载java核心类库,无法被java程序直接引用。

2)扩展类加载器(extensionsclassloader):它用来加载Java的扩展库。Java虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载Java类

3)系统类加载器(systemclassloader)也叫应用类加载器:它根据Java应用的类路径(CLASSPATH)来加载Java类。一般来说,Java应用的类都是由它来完成加载的。可以通过ClassLoader.getSystemClassLoader()来获取它。

4)用户自定义类加载器,通过继承java.lang.ClassLoader类的方式实现。

简述Java内存分配与回收策略以及MinorGC和MajorGC(fullGC)

内存分配

1)栈区:栈分为java虚拟机栈和本地方法栈

2)堆区:堆被所有线程共享区域,在虚拟机启动时创建,唯一目的存放对象实例。堆区是
gc的主要区域,通常情况下分为两个区块年轻代和年老代。更细一点年轻代又分为Eden
区,主要放新创建对象,Fromsurvivor和Tosurvivor保存gc后幸存下的对象,默认
情况下各自占比8:1:1。

3)方法区:被所有线程共享区域,用于存放已被虚拟机加载的类信息,常量,静态变量等
数据。被Java虚拟机描述为堆的一个逻辑部分。习惯是也叫它永久代(permanment
generation)

4)程序计数器:当前线程所执行的行号指示器。通过改变计数器的值来确定下一条指令,
比如循环,分支,跳转,异常处理,线程恢复等都是依赖计数器来完成。线程私有的。

回收策略以及Minor(次要)GC和Major(主要)GC:

1)对象优先在堆的Eden区分配。

2)大对象直接进入老年代。

3)长期存活的对象将直接进入老年代。当Eden区没有足够的空间进行分配时,虚拟机会执行一次MinorGC.MinorGC通常发生在新生代的Eden区,在这个区的对象生存期短,往往发生GC的频率较高,回收速度比较快;

FullGc/MajorGC发生在老年代,一般情况下,触发老年代GC的时候不会触发MinorGC,但是通过配置,可以在FullGC之前进行一次MinorGC这样可以加快老年代的回收速度

J.U.C(java.util.concurrent)

Synchronized与Lock的区别

1)Synchronized能实现的功能Lock都可以实现,而且Lock比Synchronized更好用,更灵活。
2)Synchronized可以自动上锁和解锁;Lock需要手动上锁和解锁

Runnable和Callable的区别

1)Runnable接口中的方法没有返回值;Callable接口中的方法有返回值
2)Runnable接口中的方法没有抛出异常;Callable接口中的方法抛出了异常
3)Runnable接口中的落地方法是run方法;Callable接口中的落地方法是call方法

什么是分布式锁

当在【分布式模型下,数据只有一份(或有限制)】,此时需要利用锁的技术控制【某一时刻
修改数据的进程数】。
分布式锁可以【将标记存在内存】,只是该内存不是某个进程分配的内存而是【公共内存】,如【Redis】,通过set(key,value,nx,px,timeout)方法添加分布式锁。

什么是分布式事务

事务的参与者,支持事务的服务器,资源服务器,以及事务管理器分别位于不同的分布式系统的不同节点。
(一次大操作,有不同小操作组成,这些小操作分布在不同的服务器上,且属于不同应用,分布式要保证这些操作全成功或全失败)

IO

① 功能(方向) :
1 输入流: InputStream/Reader
2 输出流: OutputStream/Writer
② 操作的数据的位数(数据类型):
1 字节流:InputStream/OutputStream
2 字符流:Reader/Writer

Linux

一般就直接问平常常用的命令有哪些?
不要说一些很掉价的命令:cd cd … ll ls mv cp.
说些高大上的:grep find tar -zxvf和-zcvf whereis kill-9 (这里不知道需要反思一下了)
top 查看内存 、df -h 查看磁盘储存情况 、iotop 磁盘io读写情况、ps aus和ps -ef 查看进程
shell高级命令:cut(剪数据)、sed(编辑器,一次一行)、awk(文本分析工具)、sort(排序)
以上高级awk,sed要一定记住的。
(shell开头:#!/bin/bash)

数据采集类

Flume

分布式的海量日志采集、聚合和传输的系统

Flume工作机制是什么?

核心概念是agent,里面包括source、chanel和sink三个组件。
source运行在日志收集节点进行日志采集,之后临时存储在chanel中,sink负责将chanel中的数据发送到目的地。
只有成功发送之后chanel中的数据才会被删除。
首先书写flume配置文件,定义agent、source、chanel和sink然后将其组装,执行flumeng命令。

Flume组成,Put事务,Take事务

source

TaildirSource:断点续传、(失败可从失败的地方继续上传)多目录。
【Flume1.6以前需要自己自定义Source记录每次读取文件位置,实现断点续传】

【Apache1.7版本产生的taildirsource】

如果挂了,可能重复数据,不会丢失。
不处理,企业中很多不处理,会影响性能。(一般不挂)
处理:增加事务:
在下一级处理:hive dwd 层;sparkstreaming(数据小),redis(大)。开窗取第一条,或分组。

是否支持递归?
默认不支持:自定义->递归代码(遍历文件夹)+读取文件(调用读取的方法)

channel

FileChannel:数据存储在磁盘,宕机数据可以保存。但是传输速率慢。适合对数据传输可靠性要求高的场景,比如,金融行业。

默认储存:100万

MemoryChannel:数据存储在内存中,宕机数据丢失。传输速率快。适合对数据传输可靠性要求不高的场景,比如,普通的日志数据。

默认储存:100个

KafkaChannel:减少了Flume的Sink阶段,提高了传输效率。

那个版本产生的?
1.6,开始没火,数据:topic+内容 =》还要清洗
1.7 时解决了bug

在生产环境怎么选?
下一级是Kafka,优先选择Kafkachannel

如果公司比较看重可靠性(金融公司,或者跟钱有关的);filechannel
如果公司比较看重效率(普通的日志)memory channel

sink

hdfs flume->Kafka->flume->hdfs
hdfs sink 小文件
三个参数:文件大小(128),时间(1-2小时),event个数(禁用)

事务

Source到Channel是Put(移动)事务
Channel到Sink是Take(取)事务

自定义拦截器&采集多条数据

采集多条自定义俩拦截器,ETL拦截器,日志类型区分拦截器
etl:主要过滤不合法的时间戳和json数据不完整的日志(判断是否{开头}结尾)

日志类型区分拦截器:将启动日志和事件日志区分开来,发往kafka的不同topic。
(start启动、和event事件)

作用于source之后,channel之前,不要太复杂占用时间

拦截器不要行不行?
可以=》在下一级处理:hive的dwd,sparksteaming

对传输要求不高,就可以使用,要求高的尤其是推荐,那就不在这做。

ETL工具类

sqoop

大数据生态体系中数据传输层的工具,完成Haoop文件存储体系(HDFS、Hive、HBase)与关系型数据库(MySQL)之间的数据导入导出。

Sqoop原理

将导入或导出命令翻译成MapReduce程序来实现(没有reducetask,不需要,因为Sqoop只是读取数据,输出数据,不需要合并计算等操作)
在翻译出的MapReduce中主要是对InputFormat和OutputFormat进行定制。
import(导入)原理:通过指定的分隔符进行数据切分,将分片传入各个map中,在map任务中在每行数据进行写入处理没有reduce。
export(导出)原理:根据要操作的表名生成一个java类,并读取其元数据信息和分隔符对非结构化的数据进行匹配,多个map作业同时执行写入关系型数据库

Sqoop参数

/opt/module/sqoop/bin/sqoopimport
–connect
–username
–password
–target-dir#路径,不能存在
–delete-target-dir#存在删掉
–num-mappers
–fields-terminated-by#分隔符
–query “$2” ‘and $CONDITIONS;’

Sqoop导入导出Null存储一致性问题

Hive中的Null在底层是以“”来存储,而MySQL中的Null在底层就是Null,为了保证数据两端的一致性。

在导出数据时采用inputnullstring和inputnullnonstring两个参数。
导入数据时采用nullstring和nullnonstring。

Sqoop数据导出一致性问题

1)场景1:如Sqoop在导出到Mysql时,使用4个Map任务,过程中有2个任务失败,
那此时MySQL中存储了另外两个Map任务导入的数据,此时老板正好看到了这个报表数据。而开发工程师发现任务失败后,会调试问题并最终将全部数据正确的导入MySQL,那后面老板再次看报表数据,发现本次看到的数据与之前的不一致,这在生产环境是不允许的。

2)场景2:设置map数量为1个(不推荐,面试官想要的答案不只这个)
多个Map任务时,采用–stagingtable方式,仍然可以解决数据一致性问题。

–staging-table方式:用作用于暂存导出数据的辅助表。最后,已分阶段处理的数据将在单个事务中移至目标表。

Sqoop底层运行的任务是什么

只有Map阶段,没有Reduce阶段的任务。

sqoop在导入数据的时候数据倾斜

涉及到俩参数:num-mappers:启动n个map来并行导入数据,默认4个;split-by:按照某一列来切分表的工作单位。
通过rownum()生成均匀的字段,然后指定为分割字段

sqoop数据导出parquet

ads层数据用sqoop往mysql导入的时候,如果用了orc(parquet)不能导入,需要转化text格式。

1.创建临时表,把parquet中数据导入到临时表,再导入。

2.sqoop里面有参数,可以直接把parquet转换为text

3.ads 层建表的时候就不要建parquet表。【推荐】

开源ETL工具Kettle

数据整合工具,Kettle中文名称叫水壶,描述你想做什么,而不是你想怎么做,etl数据预处理
Kettle目前包含五个产品:Spoon、Pan、Chef、Kithcen、Encr。

这里没涉及到什么问题,etl很流行,使用很简单,如不知道的,网上随意一搜就有,这里不过多讲解

数据储存类

Hadoop

Hadoop介绍

分布式系统基础架构
集群不一定是分布式,分布式一定是集群
谷歌的三驾马车

GFS>HDFSGFSGoogleFileSystem>hadoopdistributedFileSystem
MapReduce>MR>分析计算框架
BigTable>Hbase大数据领域的数据库

常用端口号?

2.x 50070 8088 9000 19888 重要
3.x 9870 8088 8082 19888

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

Hadoop启动的进程??

NameNode,DataNode,SecondaryNameNode

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

(1)配置文件:
2.x :coresite.xml、hdfssite.xml、mapredsite.xml、yarnsite.xml
hadoopenv.sh、yarnenv.sh、mapredenv.sh、slaves(不能用空行,不能有空格)
3.x:workers代替sh、slaves

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

hadoop优化&解决小文件??

MapReduce优化方法

数据输入

(1)合并小文件:对小文件进行归档(Har)、自定义Inputformat将小文件存储成SequenceFile文件。
(2)采用CombineTextInputFormat来作为输入,解决输入端大量小文件场景。
(3)对于大量小文件Job,可以开启JVM重用

Map阶段

增大环形缓冲区大小。由100m扩大到200m
增大环形缓冲区溢写的比例。由80%扩大到90%

通过调整io.sort.mb及sort.spill.percent参数值(在mapreddefault.xml),增大触发spill的内存上限,减少spill次数,从而减少磁盘IO。

减少合并(merge)次数(10个文件,一次20个merge)

通过调整io.sort.factor参数(在mapreddefault.xml),增大merge的文件数目,减少merge的次数,从而缩短MR处理时间

在map之后,不影响业务逻辑前提下,先进行combine处理,减少I/O。

Reduce阶段

合理设置map和reduce数

两个都不能设置太少,也不能设置太多。
太少,会导致task等待,延长处理时间;
太多,会导致map、reduce任务间竞争资源,造成处理超时等错误。

设置map、reduce共存

调整slowstart.completedmaps参数,使map运行到一定程度后,reduce也开始运行,减少reduce的等待时间。

规避使用Reduce,因为Reduce在用于连接数据集的时候将会产生大量的网络消耗。
增加每个Reduce去Map中拿数据的并行数
集群性能可以的前提下,增大Reduce端存储数据内存的大小。

IO传输

采用数据压缩的方式,减少网络IO的的时间。安装Snappy和LZOP压缩编码器。
使用SequenceFile二进制文件

整体

(1)MapTask默认内存大小为1G,可以增加MapTask内存大小为45g
(2)ReduceTask默认内存大小为1G,可以增加ReduceTask内存大小为45g
(3)可以增加MapTask的cpu核数,增加ReduceTask的CPU核数
(4)增加每个Container的CPU核数和内存大小
(5)调整每个MapTask和ReduceTask最大重试次数

Hadoop解决数据倾斜方法

一、提前在map进行Combine,减少传输量(如果大量key在不同mapper,不是很有效)

二、再不同mapper时,采用二次mr。
1、局部聚合加全局聚合。
第一次加1到n随机前缀,分布不同reduce达到负载均衡。
第二次去掉key的随机前缀,按原keyreduce处理,性能较差。

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

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

采用MapJoin,尽量避免ReduceJoin。
map端适合小表大表,只有map工作,有效避免数据倾斜。
reduce需要经过shuffle,非常耗资源。

HDFS

高可靠、高吞吐量的分布式文件系统
优缺点:

优点高容错,适合大数据处理,可构建廉价机器
缺点不适合低延迟,无法高效对小文件储存

HDFS写数据流程

在这里插入图片描述

(1)客户端通过DistributedFileSystem(分布式文件系统)模块向NameNode请求上传文件,NameNode检查目标文件是否已存在,父目录是否存在。
(2)NameNode返回是否可以上传。
(3)客户端请求第一个block上传到哪几个datanode服务器上。
(4)NameNode返回3个datanode节点,分别为dn1、dn2、dn3。
(5)客户端通过FSDataOutputStream(文件输出流)模块请求dn1上传数据,dn1收到请求会继续调用dn2,然后dn2调用dn3,将这个通信管道建立完成。
(6)dn1、dn2、dn3逐级应答客户端。
(7)客户端开始往dn1上传第一个block(先从磁盘读取数据放到一个本地内存缓存),以packet(数据包)为单位,dn1收到一个packet就会传给dn2,dn2传给dn3;
当一个block传输完成之后,客户端再次请求NameNode上传第二个block的服务器。(重复执行37步)。

HDFS的读数据流程

在这里插入图片描述

(1)客户端通过DistributedFileSystem(分布式文件系统)向NameNode请求下载文件,NameNode通过查询元数据,找到文件块所在的DataNode地址。
(2)挑选一台DataNode(就近原则,然后随机)服务器,请求读取数据。
(3)DataNode开始传输数据给客户端(从磁盘里面读取数据输入流,以packet(数据包)为单位来做校验)。
(4)客户端以packet为单位接收,先在本地缓存,然后写入目标文件(并行,快)。

NameNode和SecondaryNameNode工作机制,现在问的少了,生产是没有SecondaryNameNode的,放张我画的图大家有个印象就行。
在这里插入图片描述

MapReduce

(PB级以上海量数据的离线处理(分布式的离线并行编程计算框架)不擅长实时计算,流式计算,DAG(有向无环图))

架构

MrAppMaster:负责整个程序的过程调度及状态协调。
MapTask:负责map阶段的整个数据处理流程。
ReduceTask:负责reduce阶段的整个数据处理流程。

MapReduce工作流程

在这里插入图片描述

1,首先有一份文件,
2,客户端submit(提交文件)前,获取数据信息,根据参数配置形成任务分配的规划(分块0128)
3,然后提交切片信息到yarnRM
4,yarnRM找到闲着的机器,启动Mrappmaster(指挥mapperreduce),计算maptask数量
5,然后分好的机器开始运行,inputFormat接口TextInputFormat(默认)实现类里面的属性RecorderReader调用reader方法一行行读数据,封装成k,v
6,经过处理context.write写出数据
7,写出后会进入环形缓冲区,默认100M,如果到80%会将k,v,溢写(到磁盘)
8.(写出数据后,进入缓存前,可以编写分区)然后根据溢写分区排序,
9.溢写到文件(分区且区内有序)
10.merge归并排序
11.最后Combiner将相同合并(预先合并,可以有可以没有,只是当前一台的大小,减少文件的大小)

Shuffle机制

map方法后reduce方法前,map后首先到getpartition 标记数据是哪个分区,然后进入环形缓冲区,一边存数据,一边存索引,默认大小100m,80%会溢写,溢写前要排序,排序的手段:快排,对key的索引,按字典顺序排。溢写到文件,对数据归并排序,分区有序。reduce拉取map对应数据先放内存,内存不够放磁盘,然后归并写出。

优化:
100->200m,
80->90
默认归并10个->20个文件,
提前combinner不要影响业务逻辑,(求和可以平均值不行)
压缩格式减少磁盘io:snappy,lzo快,snappy多一些

推测执行(Speculative Execution)

如多个任务已经完成,有些只跑了10%,开启推测执行后,Hadoop会将为该task启动备份任务,让该task和原始同时处理一份数据,哪个个先处理完,就为最终结果,并且在运行完成后kill掉另外的一个任务。

是否启用推测执行,如果能根据资源情况来决定,如果在资源本身就不够的情况下,还要跑推测执行的任务,这样会导致后续启动的任务无法获取到资源,以导致无法执行。

Yarn

资源调度平台
架构

1.resourcemanager(RM):处理客户端请求,监控nodemanager,启动或监控applicationmater,资源分配与调度
2.nodemanager(NM):管理单个节点的资源,处理来自resourcemanager的命令,处理applicationmater的命令
3,applicationmaster(AM):负责读取客户端提交的切片规划,为应用程序申请资源并分配给内部的任务,任务的监控与容错
4,container:yarn中资源抽象,封装某个节点的多维度资源,如:内存,cpu,磁盘,网络等

Yarn工作机制

在这里插入图片描述
(1)Mr程序提交到客户端所在的节点。
(2)Yarnrunner向Resourcemanager申请一个Application。
(3)rm将该应用程序的资源路径返回给yarnrunner。
(4)该程序将运行所需资源提交到HDFS上。(jar(执行任务代码),xml(按照写的配置执行),切片信息)
(5)程序资源提交完毕后,申请运行mrAppMaster。
(6)RM将用户的请求初始化成一个task。
(7)其中一个NodeManager领取到task任务。
(8)该NodeManager创建容器Container,并产生MRAppmaster。
(9)Container从HDFS上拷贝资源到本地。
(10)MRAppmaster向RM申请运行maptask资源。
(11)RM将运行maptask任务分配给另外两个NodeManager,另两个NodeManager分别领取任务并创建容器。
(12)MRAppMaster向两个接收到任务的NodeManager发送程序启动脚本,这两个NodeManager分别启动maptask,maptask对数据分区排序。
(13)MrAppMaster等待所有maptask运行完毕后,向RM申请容器,运行reducetask。
(14)reducetask向maptask获取相应分区的数据。
(15)程序运行完毕后,MR会向RM申请注销自己。

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

Hadoop调度器重要分为三类:

FIFO(先进先出)、CapacityScheduler(容量调度器)和FairSceduler(公平调度器)。

Hadoop2.7.2后默认的资源调度器是容量调度器,之前是FIFO

Apache:默认容量,CDH:默认公平

区别:生产绝不会用FIFO

Hadoop宕机

1)如果MR造成系统宕机。
此时要控制Yarn同时运行的任务数,和每个任务申请的最大内存。调整参数:yarn.scheduler.maximumallocationmb(单个任务可申请的最多物理内存量,默认是8192MB)

2)如果写入文件过量造成NameNode宕机。那么调高Kafka的存储大小,控制从Kafka
到HDFS的写入速度。高峰期的时候用Kafka进行缓存,高峰期过去数据同步会自动跟上。

Hive

数据仓库

数据仓库是一个支持管理决策的数据集合。数据是面向主题的、集成的、不易丢失的并且是时变的。数据仓库是所有操作环境和外部数据源的快照集合。

概念

基于Hadoop的一个数据仓库工具,将结构化的数据文件映射为一张表,并提供类SQL查询功能,所提供的类SQL查询语言叫做HQL。
HQL语句转化为MapReduce程序在Hadoop平台执行,数据存储在Hdfs之上
Hive是针对数据仓库应用设计的,而数据仓库的内容是读多写少的

【facebook开发,统计海量数据的仓库,将结构化数据映射张表提供类sql查询叫HQL,将Hql转化为MapReduce程序在hadoop执行,储存在hdfs上。】

Hive中存放的是什么?

表。
存的是和hdfs的映射关系,hive是逻辑上的数据仓库,实际操作的都是hdfs上的文件,HQL就是用sql语法来写的mr程序。

!Hive与关系型数据库的关系?比较?

数据量:hive 大 mysql 小
速度:大数据场景快,小数据场景快

Hive和数据库除了拥有类似的查询语言,再无类似之处
1)数据存储位置

Hive存储在HDFS。
数据库将数据保存在块设备(硬盘,U盘,SD卡等)或者本地文件系统中。

2)数据更新

Hive中不建议对数据的改写。
而数据库中的数据通常是需要经常进行修改的,

3)执行延迟

Hive执行延迟较高。
数据库的执行延迟较低。当然,这个是有条件的,即数据规模较小,当数据规模大到超过数据库的处理能力的时候,Hive的并行计算显然能体现出优势。

4)数据规模

Hive支持很大规模的数据计算
数据库可以支持的数据规模较小。

请说明hive中4个by各代表什么意思?

orderby:全局排序,只有一个Reducer(多个reducer无法保证全局有序)。只有一个reducer,会导致当输入规模较大时,需要较长的计算时间。(很少用)

sortby:分区内有序

distributeby:类似MR中Partition,进行分区,结合sortby使用。(按照指定的字段对数据进行划分输出到不同的reduce中。)
(工作常用sortby+distributeby)

clusterby:当Distributeby和Sortsby字段相同时,可以使用Clusterby方式
除了具有distributeby的功能外还兼具sortby的功能。
只能升序,不能指定排序规则ASC或DESC

窗口函数

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

内表和外表的区别?

管理表(内部表,默认)删除是元数据和表数据都删除(很少使用,自己使用的临时表,才会创建内部表)

外部表,删除不会删除这份数据,描述表的元数据会被删掉(外部共享,一般都是外表)

Hive的架构原理

在这里插入图片描述

全面:

首先hive提供一系列的接口接受用户的sql语句,(clientjdbcCLI(命令行界面))通过自己的Driver,接受到
MetaStore(元数据),首先先解析是否有这个数据(SQLParser解析器),然后Physical(物理)Plan(编译器)生成逻辑计划,然后交给(QueryOptimizer优化器)优化,再交给(Execution)执行器翻译成mapreduce,交到yarn去执行,把执行的结果展示给客户端/HDFS

简洁:

Hive通过给用户提供的一系列交互接口,接收到用户的指令(SQL),使用自己的Driver,
结合元数据(MetaStore),将这些指令翻译成MapReduce,提交到Hadoop中执行,
最后,将执行返回的结果输出到用户交互接口

分区表和分桶表有什么区别?

分区针对的是数据的存储路径;分桶针对的是数据文件,相对分区更细粒度划分。

Hive虚拟列(很少问,也很少用)

Hive提供了三个虚拟列:

INPUTFILENAME
BLOCKOFFSETINSIDE__FILE
ROWOFFSETINSIDE__BLOCK

但ROWOFFSETINSIDE__BLOCK默认是不可用的,需要设置hive.exec.rowoffset为true才可以。
可以用来排查有问题的输入数据。

INPUTFILENAME, mapper任务的输出文件名。

BLOCKOFFSETINSIDE__FILE, 当前全局文件的偏移量。对于块压缩文件,就是当前块的文件偏移量,即当前块的第一个字节在文件中的偏移量。

hive自动使用索引

设置即可:一般不用,浪费资源

Hive调优

Fetch抓取

某些情况查询不必使用MapReduce计算

在hivedefault.xml.template文件中
hive.fetch.task.conversion默认是more,
老版本hive默认是minimal,该属性修改为more以后,在全局查找、字段查找、limit查找等都不走mapreduce。
hive(default)>sethive.fetch.task.conversion=none;

本地模式

针对小的输入数据量,可以通过本地模式在单台机器上处理所有的任务,执行明显缩短
设置hive.exec.mode.local.auto的值为true

//开启本地mr
sethive.exec.mode.local.auto=true;
//设置localmr的最大输入数据量,当输入数据量小于这个值时采用localmr的方式,默认为134217728,即128M
sethive.exec.mode.local.auto.inputbytes.max=50000000;
//设置localmr的最大输入文件个数,当输入文件个数小于这个值时采用localmr的方式,默认为4
sethive.exec.mode.local.auto.input.files.max=10;

严格模式

1.防止用户执行可能意向不到的影响,如orderby为了执行排序过程会将所有的结果数据分发到同一个Reducer中进行处理,使用limit,防止执行很长.
2,.限制笛卡尔积的查询

设置属性hive.mapred.mode值为默认是非严格模式nonstrict。开启严格模式需要修改hive.mapred.mode值为strict,开启严格模式可以禁止特定的查询

JOIN优化

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

尽量原子化操作

尽量避免一个SQL包含复杂逻辑,可以使用中间表来完成复杂的逻辑

行列过滤(分区剪裁、列剪裁)

分区剪裁: 只拿需要的分区,用什么拿什么。
列剪裁: 只拿需要的列,用什么拿什么。

分区剪裁:行处理,在分区剪裁中,使用外关联时,如果将副表的过滤条件写在Where后面,那么就会先全表关联,之后再过滤。
先关联再Where:

SELECT a.id FROM bigtable a  LEFT JOIN ori b ON a.id = b.id  WHERE b.id <= 10;

   
    
    
  • 1

正确的写法是写在ON后面:先Where再关联

SELECT a.id FROM ori a  LEFT JOIN bigtable b ON (b.id <= 10 AND a.id = b.id);

   
    
    
  • 1

或者直接写成子查询:

SELECT a.id FROM bigtable a RIGHT JOIN (SELECT id FROM ori WHERE id <= 10) b ON a.id = b.id;

   
    
    
  • 1

列剪裁:列处理,select中只拿需要的列,如果有尽量使用分区过滤,少用select*

采用分桶和分区技术

适当增加map数

使大数据量利用合适的map数;
使单个map任务处理合适的数据量;
是不是map数越多越好?
不是,如果有很多小文件,远小于128m,会每个小文件当一个块,浪费,而且同时执行的map是受限的
是不是保证每个map处理接近128m的文件块,就高枕无忧了?
不是,比如有个127,正常会一个map执行,但是这个文件只有一个或者俩小字段,有几千万记录,如果map处理逻辑复杂,用一个比较耗时

小文件进行合并

如何产生的?
1.动态分区
insert into partition(dt)select 2020-08-21 from

2.reduce 个数设置的过多,分区的key设计不合理

3.数据本身就是有问题 hdfs sink

小文件解决?

在Map执行前合并小文件,减少Map数:

1.CombineHiveInputFormat具有对小文件进行
合并的功能(系统默认的格式)。HiveInputFormat没有对小文件合并功能。

2.开启jvm重用:
set mapreduce.job.jvm.numtasks=10

3.merge 如果是maponly(只要一个map)任务,默认打开;
执行完任务,产生小文件,再开启一个作业,这个作业负责将小于16m的文件进行合并,默认合并到256m
如果是mr任务,merge(合并)功能需要打开;

4.在map阶段开启combiner

5.替换引擎
mr引擎:基于磁盘 慢 跨天 数据量大
tez引擎:基于内存 快 数据量小,临时测试,验证
spark引擎:基于磁盘+内存 较快 当天的定时任务;

合理设置map个数

max(1,min(块大小,Long的最大值))
128m数据=>一个maptask

控制hive任务的reduce数

设定参数
也不是越多越好,合理设置,有多少个reduce就有多少输出文件,也会照成小文件问题。
处理大文件利用合理reduce数,使单个reduce任务处理数据量大小要合适。

根据数据量大小适当增加reduce个数;

常用参数

//输出合并小文件
SEThive.merge.mapfiles=true;默认true,在maponly任务结束时合并
小文件
SEThive.merge.mapredfiles=true;默认false,在mapreduce任务结
束时合并小文件
SEThive.merge.size.per.task=268435456;默认256M
SEThive.merge.smallfiles.avgsize=16777216;当输出文件的平均大小
小于16m该值时,启动一个独立的mapreduce任务进行文件merg

列式储存(加快查询速度)

id name age
1 zs 18
2 list 20
列:1 2 zs list 18 20
行:1 zs 18 2 list 20

压缩(选择快的,减少磁盘io)

设置map端输出、中间结果压缩。(不完全是解决数据倾斜的问题,但是减少了IO读写和网络传输,能提高很多效率)

Hive解决数据倾斜方法

很多reduce任务都跑完了,就剩下其中一两个任务,一直卡着结束不了。

什么时候会产生数据倾斜?

1.不同数据类型关联产生数据倾斜
用户表id 为int,log表id为string,然后两表join的时候连接不上。
解决:on a.id=b(b.id as string)转换一样。

2.控制空值分布
空值较多会进入一个reduce
解决:加随机数

1)groupby

注:groupby优于distinctgroup
情形:groupby维度过小,某值的数量过多
后果:处理某值的reduce非常耗时
解决方式:采用sum()groupby的方式来替换count(distinct)完成计算。

2)count(distinct)

count(distinctxx)
情形:某特殊值过多
后果:处理此特殊值的reduce耗时;只有一个reduce任务
解决方式:countdistinct时,将值为空的情况单独处理,比如可以直接过滤空值的行,
在最后结果中加1。如果还有其他计算,需要进行groupby,可以先将值为空的记录单独处
理,再和其他计算结果进行union。

3)mapjoin

提前在map端聚合,如,hadoop 1,hadoop 1-》hadoop 2

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

情形:比如用户表中user_id字段为int,log表中user_id字段既有string类型也有int类
型。当按照user_id进行两个表的Join操作时。
后果:处理此特殊值的reduce耗时;只有一个reduce任务
默认的Hash操作会按int型的id来进行分配,这样会导致所有string类型id的记录都分配
到一个Reducer中。
解决方式:把数字类型转换成字符串类型
select*fromusersa
leftouterjoinlogsb
ona.usr_id=cast(b.user_idasstring)

5)开启数据倾斜时负载均衡

sethive.groupby.skewindata=true;

6)控制空值分布

将为空的key转变为字符串加随机数或纯随机数,将因空值而造成倾斜的数据分不到多个Reducer。
注:对于异常值如果不需要的话,最好是提前在where条件里过滤掉,这样可以使计算
量大大减少
实践中,可以使用casewhen对空值赋上随机值。此方法比直接写isnotnull更好,因
为前者job数为1,后者为2.

如果上述的方法还不能解决,比如当有多个JOIN的时候,建议建立临时表,然后拆分HIVESQL语句。

Hive的分层设计

建模工具EZDML,一个一个连线即可

原始数据层(ODS)

数据结构与源系统完全一致,不做修改
压缩lzo,减少磁盘空间
创建分区,减少后续的全表扫描

数据明细层(DWD)

对源系统数据进行了些清洗后的数据
1、etl清洗 清洗哪些数据?
根据业务,将字符代表的含义转换对应的业务,
核心字段不能为空,为空就清洗掉;
超时的数据过滤掉;
重复的数据过滤掉;

2.清洗工具?
hive sql ,spark sql,Python,mr,kettle

3.清洗多少脏数据?
1万条去除一条=》合理
不合理,找javaee 前端

4,维度退化
商品三级分类、二级、一级、商品表=》商品表
省、市、县=》地区
时间(年月日)=》时间表

5,为什么要退化》
防止后续的频繁join,减少重复join操作;

6.压缩
7.列式储存 parquet
8.创建分区表
9.脱敏(个人信息,身份证,手机号)
如有想用脱敏手机号,可以建一个非脱敏层(ranger/sentry加密加权限)

数据服务层(DWS)

数据的小粒度聚合,预汇总和预加工
依赖对应用的共性提炼,而不是某个具体应用
每日,每周,每月的各种指标

数据应用层(ADS)

面向应用,按需定制,前端直接读取的数据

日,周,月,等

建模

事实表:储存各维度表的主键
维度表:包含事实记录的特性

星型模型:一个事实表多个维度表联系(常用)
雪花模型:一个事实表多个维度表,维度之间还有关系
星座模型:和星型模型区别是事实表的数量。星座多个事实表

建模方法:(业务过程>粒度>维度>事实)
建模方法比较:维度模型简单,适合业务模式快速变化的行业,关系型模型实现复杂,适合业务模式比较成熟的行业。
阿里原来是关系建模。现在都是维度模型。

derby:hive元数据储存地方不支持多客户端访问

放mysql

Hbase

面向列的,非结构化数据存储的数据库,构建在Hdfs基础之上的非关系型(NoSql,NotOnlySql)数据库,列式存储其实说的是列族存储。实时随机读写海量数据。(数百万列,数十亿行的实时随机读写)

Hbase的储存原理

在这里插入图片描述

集群中有一个老大负责管理HMaster,小弟HRegionServer实际工作的,还有Zookeeper,
ZK有三个作用,Hmater高可用,让Hmaster感知HRegionServer上线的,维护元数据的入口。
客户端写数据,HRegionServer首先先把数据写到hlog里(磁盘或hdfs同步的)然后生成HRegion,
HRegion会有多个Store(储存),store里会有memstore(内存中)内存满会溢出,
产生多个storefile,会进一步演变Hfile最后将多个合并一个大的并压缩,上传到hdfs上

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(缓存),再返回给客户端。

HBase原理之写流程

在这里插入图片描述

1)Client向HRegionServer发送写请求;
2)HRegionServer将数据写到HLog(writeaheadlog)。为了数据的持久化和恢复;
3)HRegionServer将数据写到内存(MemStore);
4)反馈Client写成功。

HBase原理之数据Flush流程

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

数据合并

1)当数据块达到4块(一个store中的Hfile),HMaster将数据块加载到本地,进行合并;
2)当合并的数据(store数据)超过256M,HregionServer将region进行拆分,HMaster将拆分后的region分配给不同的HRegionServer管理(一个store列族数据超过256m会对整个region进行切分,此处可以预分区);
3)当HRegionServer宕机后,HMaster将该HRegionServer对应的HLog拆分,然后分配给不同的HRegionServer加载,修改.META.;
4)注意:HLog会同步到HDFS。(memstore在一个server上也会有很多,所以HLog丢失会不安全)

如何解决Hbase中region太小和region太大带来的结果??

Region过大会发生多次compaction,将数据读一遍并写一遍到hdfs上,占用io。
region过小会造成多次split,region会下线,影响访问服务,
调整hbase.heregion.max.filesize为256m

RowKey设计原则(多问)

长度,唯一,散列

RowKey如何设计

1)生成随机数、hash、散列值
2)字符串反转

Phoenix二级索引

对于HBase而言,如果想精确地定位到某行记录,唯一的办法是通过rowkey来查询。如果不通过rowkey来查找数据,就必须逐行地比较每一列的值,即全表扫瞄。对于较大的表,全表扫瞄的代价是不可接受的。

GlobalIndexing(全局索引)

多读少写的业务场景
在读数据的时候Phoenix会选择索引表来降低查询消耗的时间
在默认情况下如果想查询的字段不是索引字段的话索引表不会被使用,也就是说不会带来查询速度的提升

LocalIndexing(本地索引)

写操作频繁的场景以及空间受限制的场景
使用Localindexing时,索引数据和数据表的数据存放在相同的服务器中,避免了在写操作的时候往不同服务器的索引表中写索引带来的额外开销
使用Localindexing的时候即使查询的字段不是索引字段索引表也会被使用,这会带来查询速度的提升,这点跟Globalindexing不同

列族的设计原则?

尽可能少(按照列族进行存储,按照region进行读取,不必要的io操作),经常和不经常使用的两类数据放入不同列族中,列族名字尽可能短。

hbase的LSM树?

LSM树(Log-Structured Merge Tree)存储引擎和B树存储引擎一样,同样支持增、删、读、改、顺序扫描操作。而且通过批量存储技术规避磁盘随机写入问题。当然凡事有利有弊,LSM树和B+树相比,LSM树牺牲了部分读性能,用来大幅提高写性能

Redis

基于内存单线程key-value高性能数据库,在20年5月2日更新支持多线程,默认不开启,原理还是单线程,针对更大需求设定,还有个keydb多线程的,fork出来的分支。

优势

性能极高–Redis能读的速度是110000次/s,写的速度是81000次/s。
丰富的数据类型–Redis支持二进制案例的Strings,Lists,Hashes,Sets及OrderedSets数据类型操作。
原子–Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
丰富的特性–Redis还支持publish/subscribe,通知,key过期等等特性。

类型(常问)

字符串(string):用于缓存数据,可以存储对象序列化
列表(list):链表结构,用于模拟栈和队列,微博关注列表,粉丝列表,消息列表等
集合(set):去重,抽奖。
有序集合(sortedset)(zset):排序用,直播系统中,实时的排行信息,包含直播间在线用户列表,各种礼物排行榜
哈希(散列)(hash):做缓存,放java对象,会占用更少的内存,存储用户信息,商品信息。
(hash是一个string类型的field和value的映射表。它的添加、删除操作都是0(1)(平均操作)。)

redis中数据类型指的是value的数据类型,而key只有String,string类型的值最大能存储512MB

缓存穿透:

大量缓存中不存在的请求key访问直接落到数据库,一般是恶意攻击;
(将空对象也缓存起来,并设置很短的过期时间,最长不超过5分钟。
使用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap(位图)中,一个一定不存在的会被拦截掉,从而避免对底层储存系统的查询压力)

缓存雪崩:

缓存集中一段时间失效,发生大量缓存穿透,所有查询落在数据库上
(尽量让失效的时间点不分布再同一时间点)

缓存击穿:

热点key在请求高峰失效,瞬间大量请求落到数据库;
(可以设置key永不过期)

哨兵模式

主机down掉,哨兵会从从机选择一台作为主机,并设置为其他从机的主机,原来主机再次启动也就变从机

持久化

RDB 方式(默认)
AOF 方式

RDB持久化(间隔性):

在内存中的的状态保存到硬盘中,它可以手动执行,也可以再redis.conf中配置,定期执行。

RDB持久化产生的RDB文件是一个经过压缩的二进制文件,这个文件被保存在硬盘中,redis可以通过这个文件还原数据库当时的状态。

①在指定的时间间隔内持久化
②服务shutdown(关机)会自动持久化
③输入bgsave也会持久化

AOF:以日志形式记录每个更新操作

重新启动时读取这个文件,重新执行新建、修改数据的命令恢复数据。
默认每秒持久化一次,比RDB占用更多磁盘空间
备份恢复慢,性能压力,存在个别bug。

对数据不敏感,可以选单独用RDB;
不建议单独用AOF,因为可能出现Bug;
如果只是做纯内存缓存,可以都不用

对比

在RDB和AOF备份文件都有的情况下,redis会优先载入AOF备份文件

RDB持久化,安全性较差,它是正常时期数据备份及 master-slave数据同步的最佳手段,文件尺寸较小,恢复数度较快。

AOF更安全,可将数据及时同步到文件中,但需要较多的磁盘IO,AOF文件尺寸较大,文件内容恢复相对较慢, 也更完整。

悲观锁

执行操作前假设当前的操作肯定(或有很大几率)会被打断(悲观)。
基于这个假设,我们在做操作前就会把相关资源锁定,不允许自己执行期间有其他操作干扰。

乐观锁

执行操作前假设当前操作不会被打断(乐观)。
基于这个假设,我们在做操作前不会锁定资源,万一发生了其他操作的干扰,那么本次操作将被放弃。
Redis使用的就是乐观锁。

redis是单线程的,为什么那么快?

完全基于内存,
数据结构简单,操作简单,
单线程,不考虑多进程线程的切换消耗cpu,加锁等性能消耗,
使用多路I/O复用模型,非阻塞io
底层模型,通信协议不同,直接构造vm机制。

Kafka

在这里插入图片描述

分布式消息队列,本质是缓冲数据,因为提供消息(数据)管理功能才叫消息队列,记录上次读数据的偏移量、消息读取之后是否删除、消息的备份和安全等机制
mq,message,queue(都叫消息队列)

注意!

zookeeper储存的没有生产者的有关信息,储存broker数量消费者,topic。消费组对应的相关信息。

模式

点对点模式(一对一,消费者主动拉取数据,消息收到后消息清除)

发布/订阅模式(一对多,数据生产后,推送给所有订阅者)

架构

Producer:消息生产者,就是向kafkabroker发消息的客户端;
Consumer:消息消费者,从kafkabroker取消息的客户端;
Topic:可以理解为一个队列(就是同一个业务的数据放在一个topic下);
ConsumerGroup(CG):topic消息的广播(发给所有的consumer)和单播(发给任意一个consumer)的手段。
一个topic可以有多个CG,但每个partion只会把消息发给该CG中的一个consumer。如果需要实现广播,只要每个consumer有一个独立的CG就可以了。要实现单播只要所有的consumer在同一个CG
Broker:一台kafka服务器就是一个broker。一个集群由多个broker组成。一个broker可以容纳多个topic;
Partition:为了实现扩展性,一个非常大的topic可以分布到多个broker(即服务器)上,一个topic可以分为多个partition,每个partition是一个有序的队列
Offset:偏移量。
0.9版本之前存储在zk
0.9版本后存储在本地

写入方式

采用推(push)模式将消息发布到broker,每条消息都被追加(append)到分区(patition)中,属于顺序写磁盘(顺序写磁盘效率比随机写速度快,保障Kafka吞吐率)。

kafka工作原理?

producer(生产者)向broker发送事件,consumer(消费者)从broker消费事件。
事件由topic区分开,每个consumer(消费者)都会属于一个group。
相同group中的consumer(消费者)不能重复消费事件,而同一事件将会发送给每个不同group的consumer(消费者)。

Kafka的机器数量?

Kafka机器数量=2*(峰值生产速度*副本数/100)+1

Kafka的日志保存时间

默认7天;生产环境一般3天

Kafka丢不丢数据

producerkafka生产者发送数据给kafka可能会丢数据?
通过ACK机制确保数据不丢失。

kafka接收到数据之后,消息存储在kafka中kafka可能会丢数据?
kafka通过副本机制保证数据不丢失(leaderfollower)

消费者消费数据的时候可能会丢数据
kafkaconsumer

Ack=0,相当于异步发送,消息发送完毕即offset增加,继续生产。(最快,可靠最差,生产不用)

Ack=1,leader收到leaderreplica对一个消息的接受ack才增加offset,然后继续生产。(较快,可靠可以,大多选择)

Ack=-1,leader收到所有replica对一个消息的接受ack才增加offset,然后继续生产。(慢,可靠,安全选择)

Kafka的ISR副本同步队列

ISR(InSyncReplicas),副本同步队列。
ISR中包括Leader和Follower。
如果Leader进程挂掉,会在ISR队列中选择一个服务作为新的Leader。有replica.lag.max.messages(延迟条数)和replica.lag.time.max.ms(延迟时间)两个参数决定一台服务是否可以加入ISR副本队列,在0.10版本移除了replica.lag.max.messages参数,防止服务频繁的进去队列。
任意一个维度超过阈值都会把Follower剔除出ISR,存入OSR(OutofSyncReplicas)列表,新加入的Follower也会先存放在OSR中。

isr leader挂了谁当老大??
在isr队列里面都有机会。
怎么进入:
旧版本:延迟时间,延迟条数
新版本:只有延迟时间

Kafka分区分配策略

在Kafka内部存在两种默认的分区分配策略:Range和RoundRobin。
Range是默认策略。Range是对每个Topic而言的(即一个Topic一个Topic分),首先对同一个Topic里面的分区按照序号进行排序,并对消费者按照字母顺序进行排序。然后用Partitions分区的个数除以消费者线程的总数来决定每个消费者线程消费几个分区。如果除不尽,那么前面几个消费者线程将会多消费一个分区。

RoundRobin:所有分区采用hash随机打散,轮询方式;

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

1)如果是Kafka消费能力不足,则可以考虑增加Topic的分区数,并且同时提升消费组的消费者数量,消费者数=分区数。(两者缺一不可)

2)如果是下游的数据处理不及时:提高每批次拉取的数量。批次拉取数据过少(拉取数据/处理时间<生产速度),使处理的数据小于生产的数据,也会造成数据积压。

加分区、加消费者条数

Kafka数据重复

幂等性+ack1+事务

Kafka数据重复,可以再下一级:SparkStreaming、redis或者hive中dwd(细节层)层去重,去重的手段:分组、按照id开窗只取第一个值;

幂等性:单分区,在一个会话内 ,效率高
事务:整个Kafka内部,全局维护id,效率低

Kafka支持传输?

对于消费体大小默认单条最大值是1m,但是常常遇到一条大于1m,如果不对Kafka进行配置,会照成生产者推送消息,消费也无法消费数据。
设置参数

Kafka过期数据清理

直接删除,启动删除策略(推荐,前面日志服务器有)
log.cleanup.policy=delete

压缩策略
log.cleanup.policy=compact

kafka保证数据有序?

分区内有序,分区间无序,业务逻辑可以无序,就不处理。
业务逻辑必须有序,如果数据小,搞一个单分区的主题,大的话,生产者记录位置信息,消费者根据位置信息指定分区进行读取数据

单分区有序,多分区间无序

怎么保证kafaka业务的不丢失?

重新分区,增加消费者

优化政策

针对Partitions的最佳实践

了解分区的数据速率,“平均消息大小”乘以“每秒消息数”得出 能标识单个consumer不延时所需要的支持的最低性能值。
除非有其他架构上的需要,否则在写topic时请使用随机分区

针对Consumers的最佳实践

consumer比0.10底的要升级版本,0.8.x使用zookeeper协调consumergroup会出现bug,长期处于再均衡状态,或者导致再均衡算法失败(再均衡风暴),因此再均衡期间一个多个分区会被分配同一组的每个consumer,再均衡风暴中会在各个cs之间流转。
调优consumer的套接字缓存区(socketbuffers),应对数据高速流入。

针对Producers的最佳实践

配置producer,以等待各种确认。

针对Brokers的最佳实践

在各个brokers上,请压缩topics所需的内存和CPU资源 通过网络吞吐量来监控brokers。

Mysql

DB:数据库,储存数据的容器
DBMS:数据库管理系统,用于创建管理DB
SQL:结构化查询语言

四层逻辑
连接层-服务层-引擎层-储存层

事务的并发问题

更新丢失:两同时修改同一文件,每个独立修改其副本,然后保存,最后一个保存的覆盖前一个做的更改。
解决:在第一个完成提交前,另一个不能访问同一文件。

脏读:事务A读取了事务B已修改但尚未提交的,那么A读取到的数据是脏数据

不可重复读:事务A多次读取同一数据,事务B在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果不一致
事务A读取到了事务B已经提交的修改数据,不符合隔离性。

幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。
事务A读取了事务B的新增

注:不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表

MySQL 事务隔离级别

默认可重复读的隔离级别

在这里插入图片描述

SQL索引优化(数据结构:B+Tree)

1、在表中建立索引,优先考虑where、groupby使用到的字段。

2、尽量避免使用select**,返回无用的字段会降低查询效率。如下: SELECTFROMt
优化方式:使用具体的字段代替
,只返回使用到的字段。

3、使用表或列的别名 如果表或列的名称太长了,使用一些简短的别名也能稍微提高一些SQL的性能。毕竟要扫描的字符长度就变少了

4、SQL写大写 我们在编写SQL的时候,官方推荐的是使用大写来写关键字,因为Oracle服务器总是先将小写字母转成大写后,才执行

5、用>=替代> 低效: SELECTFROMEMPWHEREDEPTNO>3
首先定位到DEPTNO=3的记录并且扫描到第一个DEPT大于3的记录 高效: SELECT
FROMEMPWHEREDEPTNO>=4
直接跳到第一个DEPT等于4的记录

6、尽量避免使用in和notin,会导致数据库引擎放弃索引进行全表扫描。如下:(B>Ain,B<aexists)
SELECTFROMtWHEREidIN(2,3)
SELECT
FROMt1WHEREusernameIN(SELECTusernameFROMt2)
优化方式:如果是连续数值,可以用between代替。如下: SELECTFROMtWHEREidBETWEEN2AND3
如果是子查询,可以用exists代替。如下:
SELECT
FROMt1WHEREEXISTS(SELECT*FROMt2WHEREt1.username=t2.username)

7、尽量避免使用or,会导致数据库引擎放弃索引进行全表扫描。如下: SELECTFROMtWHEREid=1ORid=3
优化方式:可以用union代替or。如下: SELECT
FROMtWHEREid=1 UNION
SELECT*FROMtWHEREid=3
(PS:如果or两边的字段是同一个,如例子中这样。貌似两种方式效率差不多,即使union扫描的是索引,or扫描的是全表)

8、尽量避免在字段开头模糊查询,会导致数据库引擎放弃索引进行全表扫描。如下:
SELECTFROMtWHEREusernameLIKE’%li%’ 优化方式:尽量在字段后面使用模糊查询。如下:
SELECT
FROMtWHEREusernameLIKE’li%’

9、尽量避免进行null值的判断,会导致数据库引擎放弃索引进行全表扫描。如下: SELECTFROMtWHEREscoreISNULL
优化方式:可以给字段添加默认值0,对0值进行判断。如下: SELECT
FROMtWHEREscore=0

10、尽量避免在where条件中等号的左侧进行表达式、函数操作,会导致数据库引擎放弃索引进行全表扫描。如下:
SELECTFROMt2WHEREscore/10=9
SELECT
FROMt2WHERESUBSTR(username,1,2)=‘li’
优化方式:可以将表达式、函数操作移动到等号右侧。如下: SELECTFROMt2WHEREscore=109
SELECT*FROMt2WHEREusernameLIKE’li%’

11、当数据量大时,避免使用where1=1的条件。通常为了方便拼装查询条件,我们会默认使用该条件,数据库引擎会放弃索引进行全表扫描。如下:
SELECT*FROMtWHERE1=1 优化方式:用代码拼装sql时进行判断,没where加where,有where加and。

12、服务器硬件优化 花钱

分析计算类

结构化数据:

类似数据库,行数据,由二维表结构

半结构化数据:

通过键可以获取相应值,且数据格式不相同,如json,文本型或者字典型或者列表

非结构化数据:

音乐,图片,视频等

Spark(2010发布)

基于内存计算的大数据并行计算框架,惰性计算模式,scala语言编写,也可以java,java麻烦

在这里插入图片描述

driver(驱动器)+executor(执行器)

webui界面

spark的UI界面:http://00.0.000.00:18080/

Spark与Hadoop区别??

核心区别:内存和磁盘的区别;job中途失败重新计算的区别。
某一部分丢失或者出错,可以通过整个数据集的计算流程的血缘关系来实现重建;
mapreduce的话容错可能只能重新计算了,成本较高。

MRShuffle和SparkShuffle差别总结如下:

1、Hadoop的有一个Map完成,Reduce便可以去fetch(取)数据了,不必等到所有Map任务完成,而Spark的必须等到父stage(阶段)完成,也就是父stage的map操作全部完成才能去fetch(取)数据。
2、Hadoop的Shuffle是sortbase的,那么不管是Map的输出,还是Reduce的输出,都是partion内有序的,而spark不要求这一点。
3、Hadoop的Reduce要等到fetch(取)完全部数据,才将数据传入reduce函数进行聚合,而spark是一边fetch(取)一边聚合。

shuffle是【划分DAG中stage的标识】,同时影响Spark执行速度的关键步骤

有明显阶段吗?没有明显阶段。
遇到【宽依赖的时候,会有数据的shuffle,遇到宽依赖的时候才划分stage。】
从【上一个stage到下一个stage就是一个shuffle的过程】。
shuffle指的就是数据的重新分配的一个过程,也就是说如果RDD的分区数据有交叉变化(遇到宽依赖,父RDD的分区和子RDD的分区是多对多),那么这个变化过程中就存在着shuffle过程。只要是宽依赖,就一定存在shuffle过程,两个stage之间一定存在shuffle过程。
Spark中的shuffle操作由【shufflemanager负责,默认使用sort机制】

spark几种部署模式

Local:本地模式,用于本地开发测试
Standlone:集群模式,Spark自带的资源调度框架,存在master单点故障,可由zookeeper实现HA,学习用
Yarn:集群模式,运行yarn之上,由yarn负责资源管理,spark负责任务调度和计算,生产用
有yarnclient和yarncluster

(两种模式,主要区别在于:Driver程序的运行节点。
Yarncluster适用于生产环境,而YarnCluster更适用于交互,调试模式)

Spark中job,stage,task等等

job:提交给spark的任务
stage:job处理过程中需要分为的几个阶段
task:task是每个job处理分几次任务的最小单位,运行在executor中
job>一个或多个stage>一个或多个task

简述Spark的架构与作业提交流程

1.首先spark在yarn下的作业提交分两种,一种是yarncluster模式,一种是yarnclient模式。yarnclient模式主要是用于测试,
yarncluster模式主要是用于生产。
在这里插入图片描述

在这里插入图片描述

2.当我们用sparksubmit提交任务的时候,会请求ResourceManager分配一个executor,用于启动ApplicationMaster,接着启动driver(yarnclient模式driver在提交作业的终端启动,yarncluster模式driver在AM处启动)。
接着AM找RM要资源,RM给分配相应数量的executor。
开始执行任务,拆分stage,提交stage的task,进行task的调度,分配到各个executor上面去执行。
执行完成后,driver会通知RM回收资源。

transformation算子,并简述功能

1)map(func):返回一个新的RDD,该RDD由每一个输入元素经过func函数转换后组成.
2)filter(func):返回一个新的RDD,该RDD由经过func函数计算后返回值为true的输入元素组成,(过滤)
3)flatMap(func):类似于map,但是每一个输入元素可以被映射为0或多个输出元素(所以func应该返回一个序列,而不是单一元素)
4)mapPartitions(func):类似于map,但独立地在RDD的每一个分片上运行,因此在类型为T的RDD上运行时,func的函数类型必须是Iterator[T]=>Iterator[U]。假设有N个元素,有M个分区,那么map的函数的将被调用N次,而mapPartitions被调用M次,一个函数一次处理所有分区。(一个函数一次处理所有分区)
5)mapPartitionsWithIndex(func):类似于mapPartitions,但func带有一个整数参数表示分片的索引值,因此在类型为T的RDD上运行时,func的函数类型必须是(Int,Interator[T])=>Iterator[U](描述分区信息)
6)union(otherDataset):对源RDD和参数RDD求并集后返回一个新的RDD
7)reduceByKey(func,[numTasks]):在一个(K,V)的RDD上调用,返回一个(K,V)的RDD,使用指定的reduce函数,将相同key的值聚合到一起,reduce任务的个数可以通过第二个可选的参数来设置。(相同key聚合)
8)groupByKey([numTasks]):在一个(K,V)的RDD上调用,返回一个(K,Iterator[V])的RDD,将相同key的value放到Iterator中。
groupByKey也是对每个key进行操作分组,但只生成一个sequence(序列)。
9)sortByKey([ascending],[numTasks]):在一个(K,V)的RDD上调用,K必须实现Ordered接口,返回一个按照key进行排序的(K,V)的RDD
(按照key排序)

action算子,并简述功能

1)reduce:通过func函数聚集RDD中的所有元素,这个功能必须是可交换且可并联的(计算)

2)collect:在驱动程序中,以数组的形式返回数据集的所有元素(收集)

3)first:返回RDD的第一个元素(类似于take(1))(选择)

4)take:返回一个由数据集的前n个元素组成的数组(选择)

5)count():返回RDD的元素个数(计数)

6)countByKey:针对(K,V)类型的RDD,返回一个(K,Int)的map,表示每一个key对应的元素个数。(对key计数)

7)foreach:在数据集的每一个元素上,运行函数func进行更新(遍历)

8)saveAsTextFile:将数据集的元素以textfile的形式保存到HDFS文件系统或者其他支持的文件系统,对于每个元素,Spark将会调用toString方法,将它装换为文件中的文本
(保存)

9)aggregate:给一个初始值,每个分区和初值聚合

会引起Shuffle过程的Spark算子,并简述功能。

reduceBykey:在一个(K,V)的RDD上调用,返回一个(K,V)的RDD,使用指定的reduce函数,将相同key的值聚合到一起,reduce任务的个数可以通过第二个可选的参数来设置。(相同key聚合,有map端聚合,高于groupbykey)

reduceByKey有map端的聚合操作,使得网络传输的数据量减小,效率要高于groupByKey
groupByKey不会进行map端的聚合,而是讲map端的数据shuffle到reduce端,在reduce端进行数据的聚合操作

groupByKey:groupByKey也是对每个key进行操作分组,但只生成一个sequence(序列),reduce端聚合
sortByKey([ascending],[numTasks]):在一个(K,V)的RDD上调用,K必须实现Ordered接口,返回一个按照key进行排序的(K,V)的RDD
(按key进行排序)
countByKey():计算个key的元素个数
…ByKey:

核心Shuffle(HashShuffle与SortShuffle)的工作流程(包括未优化的HashShuffle、优化的HashShuffle、普通的SortShuffle与bypass(分流)的SortShuffle)

spark1.6版本之前,一直使用HashShuffle,在spark1.6版本之后使用SortBaseShuffle,因为HashShuffle存在的不足所以就替换了HashShuffle.

未优化的hashshuffle:根据task划分文件,小文件太多。
优化后:根据core划分,但是core多也会有很多小文件。
SortBaseShuffle:加入排序,内存不够溢写磁盘,合成索引文件和数据文件。
bypass:有时是不需要排序的,这里参数小于200使用它,功能除了没排序都一样。

Spark reduceByKey与groupByKey的区别,哪一种更具优势?

reduceByKey:按照key进行聚合,在shuffle之前有combine(预聚合)操作,返回结果是RDD[k,v]。

groupByKey:按照key进行分组,直接进行shuffle。
建议使用reducebykey,但是注意是否会影响业务逻辑

Repartition(重新分区)和Coalesce(合并)关系与区别

1)关系:都是改变RDD的partition数量,reparation底层调用coalesce方法:
coalesce(numPartitions,shuffle=true)

2)区别:repartition一定shuffle,coalesce根据传入参数来判断是否发生shuffle
一般增大rdd的partition使用reparation,减少partition使用coalesce

12种缓存级别

在这里插入图片描述

none:不缓存
disk_only 缓存磁盘一份
disk_only_2缓存磁盘二份
memory_only缓存内存一份
memory_only_2缓存内存二分
memory_only_ser缓存内存,存放序列化后的数据
memory_only_ser_2缓存内存,存放序列化后的数据2
memory_and_disk缓存内存,放不下放磁盘
memory_and_disk_2缓存内存,放不下放磁盘2
memory_and_disk_ser缓存内存,放不下放磁盘,内存存放序列化后的数据
memory_and_disk_ser_2缓存内存,放不下放磁盘,内存存放序列化后的数据2份

简述Spark中共享变量(广播变量和累加器)的基本原理与用途。

累加器(accumulator):对事件计数
广播变量(broadcast):分发较大的对象。

SparkShuffle默认并行度

参数spark.sql.shuffle.partitions决定默认并行度200

SparkStreaming精准一次消费

1.手动维护偏移量

2.处理完业务数据后,再进行提交偏移量操作
极端情况下,如在提交偏移量时断网或停电会造成spark程序第二次启动时重复消费问题,所以在涉及到金额或精确性非常高的场景会使用事务保证精准一次消费

解决数据倾斜

原因:key分布不均匀,建表不周,业务数据激增

数据预处理、异常值的过滤、调参并行度、定位数据倾斜代码,一般在shuffle过程中、两阶段聚合(局部聚合+全局聚合)、reducejoin转为mapjoin(广播分发)、多种组合使用。

在这里插入图片描述

spark的优化怎么做?

常规调优:

避免重复加载RDD,重复的RDD需要缓存

(1)计算量大,形成的lineage(血脉关系)过大应该给已经缓存了的rdd添加checkpoint(检查点),以减少容错带来的开销。
(2)小分区合并,过小的分区造成过多的切换任务开销,使用repartition(分区)。

警惕shuffle操作性能问题:
reduceByKe优于groupByKey

广播变量:一个Executor中的所有task共享一个副本。

序列化:
在DataFrames和DataSet当中自动实现了kryo序列化。kryo序列化比java序列化更快更紧凑

使用DataSet对数据操作更简单,类型检查更安全。

通过sparkenv文件、程序中sparkconf和setproperty设置。
参数调优等:
并行度200默认,调优800

算子调优
mapPartitions:

一个task处理一个RDD的partition,那么一个task只会执行一次function,function一次接收所有的partition数据,效率比较高;但是如果使用mapPartitions算子,但数据量非常大时,function一次处理一个分区的数据,如果一旦内存不足,此时无法回收内存,就可能会OOM,即内存溢出。

foreachPartition优化数据库操作

在生产环境中,通常使用foreachPartition算子来完成数据库的写入,通过foreachPartition算子的特性,可以优化写数据库的性能

filter与coalesce的配合使用

我们可以在filter操作之后,使用coalesce算子针对每个partition的数据量各不相同的情况,压缩partition的数量,而且让每个partition的数据量尽量均匀紧凑,以便于后面的task进行计算操作,在某种程度上能够在一定程度上提升性能

repartition解决SparkSQL低并行度问题

对于Spark SQL查询出来的RDD,立即使用repartition算子,去重新进行分区,这样可以重新分区为多个partition,从repartition之后的RDD操作,由于不再设计Spark SQL,因此stage的并行度就会等于你手动设置的值

reduceByKey预聚合

map端会先对本地的数据进行combine操作,然后将数据写入给下个stage的每个task创建的文件中

shuffle调优
调节map端缓冲区大小

通过调节map端缓冲的大小,可以避免频繁的磁盘IO操作,进而提升Spark任务的整体性能

val conf = new SparkConf()
  .set("spark.shuffle.file.buffer", "64")

   
    
    
  • 1
  • 2
调节reduce端拉取数据缓冲区大小

如果内存资源较为充足,适当增加拉取数据缓冲区的大小,可以减少拉取数据的次数,也就可以减少网络传输的次数,进而提升性能

val conf = new SparkConf()
  .set("spark.reducer.maxSizeInFlight", "96")

   
    
    
  • 1
  • 2
调节reduce端拉取数据重试次数

对于那些包含了特别耗时的shuffle操作的作业,建议增加重试最大次数(比如60次),以避免由于JVM的full gc或者网络不稳定等因素导致的数据拉取失败

val conf = new SparkConf()
  .set("spark.shuffle.io.maxRetries", "6")

   
    
    
  • 1
  • 2
调节reduce端拉取数据等待间隔

Spark Shuffle过程中,reduce task拉取属于自己的数据时,如果因为网络异常等原因导致失败会自动进行重试,在一次失败后,会等待一定的时间间隔再进行重试,可以通过加大间隔时长(比如60s),以增加shuffle操作的稳定性

val conf = new SparkConf()
  .set("spark.shuffle.io.retryWait", "60s")

   
    
    
  • 1
  • 2
调节SortShuffle排序操作阈值

如果shuffle reduce task的数量小于某一阈值则shuffle write过程中不会进行排序操作,而是直接按照未经优化的HashShuffleManager的方式去写数据,但是最后会将每个task产生的所有临时磁盘文件都合并成一个文件,并会创建单独的索引文件

val conf = new SparkConf()
  .set("spark.shuffle.sort.bypassMergeThreshold", "400")

   
    
    
  • 1
  • 2
JVM调优

对于JVM调优,首先应该明确,full gc/minor gc,都会导致JVM的工作线程停止工作,即stop the world

降低cache操作的内存占比

如果发现gc太频繁,时间太长,就可以考虑调节Storage的内存占比,让task执行算子函数式,有更多的内存可以使用

val conf = new SparkConf()
  .set("spark.storage.memoryFraction", "0.4")

   
    
    
  • 1
  • 2
调节Executor堆外内存

Executor的堆外内存主要用于程序的共享库、Perm Space、 线程Stack和一些Memory mapping等, 或者类C方式allocate object。

--conf spark.yarn.executor.memoryOverhead=2048

   
    
    
  • 1
调节连接等待时长

垃圾回收会导致工作现场全部停止,也就是说,垃圾回收一旦执行,Spark的Executor进程就会停止工作,无法提供相应,此时,由于没有响应,无法建立网络连接,会导致网络连接超时

--conf spark.core.connection.ack.wait.timeout=300

   
    
    
  • 1

RDD分区

分为hash分区和range分区和自定义分区
默认hash分区

range保证数据量的均匀

自定义分区:
继承 org.apache.spark.Partitioner 类实现三个方法
numpartition:int 返回创建出来的分区数
getpartition(key:any):int 返回给定键的分区编号(0到numpartition-1)
equals():java判断相等性的标准方法。

Fink(15年发行)

Flink 在运行时主要包含:Jobmanager、Taskmanager 和 Slot

流式计算性能更高、可靠性更高

集群架构

在这里插入图片描述

client客户端提交任务给JobManager hadoop fs -mkdir -p /test/input
JobManager负责Flink集群计算资源管理,并分发任务给TaskManager执行
TaskManager定期向JobManager汇报状态

有界流和无界流

Flink将批处理(即处理有限的静态数据)视作一种特殊的流处理

Flink+Kafka如何实现exactly-once语义

内部–利用checkpoint机制,把状态存盘,保证内部的状态一致性。
source–Kafka consumer作为source,将偏移量保存下来,出现故障恢复可以有连接器重置偏移量,重新消费数据,保证一致性。
sink–Kafka producer 作为sink,采用两阶段提交sink,需要实现一个TwoPhaseCommitSinkFunction。

Flink相比传统的SparkStreaming区别?

Flink是标准的实时处理引擎,基于事件驱动。而SparkStreaming是微批(MicroBatch)的模型。(最大区别)

Flink的基础编程模型了解吗?

基本构建是数据输入来自一个source,代表输入端。
经过transformation转换,在一个或者多个sink接收器结束。
数据流(stream)就是一组永远不会停止的数据记录流,而转换(transformation)试将一个或者多个流作为输入,生成一或多个输出流的操作。
执行时,flink程序映射到streamingdataflow,就流(streams)和转换操作(transformationoperators)组成

说说Flink中的窗口?

划分窗口的方式,time和count
滚动窗口(TumblingEventTimeWindows)
滑动窗口(SlidingEventTimeWindows)
会话窗口(EventTimeSessionWindows)

窗口函数分两种:增量和全量
增量:reduce和eggregate(每个窗口先计算)
全量:process(先缓存该窗口所有元素,触发再算)

Flink中水印是什么概念,起到什么作用?

Watermark是ApacheFlink为了【处理EventTime窗口计算提出的一种机制】,本质上是一种【时间戳】。一般来讲Watermark经常和Window一起被用来【处理乱序事件。】

事件时间-摄入时间-处理时间

Flink是如何保证Exactlyonce语义的?

两阶段提交和状态保存来实现端到端的一致性语义

开始事务,【创建一个临时文件】,把数据写入文件夹。
【预提交将内存缓存的数据写入文件并关闭】。
【正式提交将之前写完的临时放到目标目录下】,最终会有些延迟。
【丢弃临时文件】。
若发生在预提交成功后,正式提交前。可以根据状态来提交预提交的数据,也可以删除预提交数据。

开始事务(beginTransaction)创建一个临时文件夹,来写把数据写入到这个文件夹里面
预提交(preCommit)将内存中缓存的数据写入文件并关闭
正式提交(commit)将之前写完的临时文件放入目标目录下。这代表着最终的数据会有一些延迟
丢弃(abort)丢弃临时文件
若失败发生在预提交成功后,正式提交前。可以根据状态来提交预提交的数据,也可删除预提交的数据

Flink中的Window出现了数据倾斜,你有什么解决办法?

window产生数据倾斜指的是数据在不同的窗口内堆积的数据量相差过多。本质上产生这种情况的原因是数据源头发送的数据量速度不同导致的。出现这种情况一般通过两种方式来解决:
在数据进入【窗口前做预聚合】。
【重新设计窗口聚合的key】

Flink中在使用聚合函数GroupBy、Distinct、KeyBy等函数时出现数据热点该如何解决?

在业务上规避这类问题
(把热点单独处理)

key设计
(把key拆分聚合)

参数设置【1.9.0SQL(BlinkPlanner),升级了微批模型MiniBatch】(缓存一定数据后再处理,减少state访问,提升吞吐和减少数据的输出量)

FlinkJob的提交流程(三层图)

【用户提交】的FlinkJob会被【转化成一个DAG任务运行】,分别是:【StreamGraph、JobGraph、ExecutionGraph】,Flink中【JobManager与TaskManager】,【JobManager与Client的交互是基于Akka(实时事务处理)工具包的,是通过消息驱动】。整个FlinkJob的提交还【包含着ActorSystem(调度)的创建,JobManager的启动,TaskManager的启动和注册】

三层图:StreamGraph->JobGraph->ExecutionGraph

查询应用类(扩展)

superset可视化

Python编写的web应用
能够对接常用的大数据分析工具,如hive,kylin,Druid等,数仓的可视化工具

ElasticSearch搜索

ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式、支持多用户的全文搜索引擎,基于RESTful Web接口。ElasticSearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索、稳定、可靠、快速、安装使用方便。

与mysql区别?

在这里插入图片描述

即席查询

presto (基于内存)

开源分布式sql查询引擎,数据量支持GB到PB字节,主要来处理秒级查询的场景,可以跨数据源查询

注:虽然可以解析sql,但它不是标准的数据库,不是mysql和oracle的替代品,也不能用来处理在线事务(OLTP)
一个数据源是catalog(目录)

impala也可以做

和presto类似架构,但优于它,但是数据源比impala数据源多

Druid(预计算)

快速的列式分布式的支持实时分析的数据储存系统,在处理PB级数据,毫秒级查询,数据实时处理方面,比传统OLAP显著的改进。

需要清洗的数据,和只读分析的。
实时比较高,数据质量不高的场景

DataSource(表)+segment(时间分块)

Kylin(预计算)

Kylin是一个开源的分布式分析引擎,提供了基于Hadoop的超大型数据集(TB/PB级别)的SQL接口以及多维度的OLAP分布式联机分析。最初由eBay开发并贡献至开源社区。它能在亚秒内查询巨大的Hive表。默认计算引擎hadoop,也可以spark,sql查询接口。

核心是cube(立方体),储存使用hbase

支持类型:prosto->sparksql->kylin->druid
查询效率:druid->kylin->prosto->sparksql

数据管理类(扩展)

这些都蛮简单,网上自行搜索

1、Azkaban(任务调度)

Azkaban是由linked开源的一个批量工作流任务调度器,它是由三个部分组成:Azkaban Web Server(管理服务器)、Azkaban Executor Server(执行管理器)和MySQL(关系数据库),可用于在一个工作流内以一个特定的顺序运行一组工作和流程,可以利用Azkaban来完成大数据的任务调度,大数据开发需掌握Azkaban的相关配置及语法规则。

2、EasyScheduler(任务调度)

在这里插入图片描述

3、AirFlow(任务调度)

airflow是一款开源的,分布式任务调度框架,它将一个具有上下级依赖关系的工作流,组装成一个有向无环图。
特点:
分布式任务调度:允许一个工作流的task在多台worker上同时执行
可构建任务依赖:以有向无环图的方式构建任务依赖关系
task原子性:工作流上每个task都是原子可重试的,一个工作流某个环节的task失败可自动或手动进行重试,不必从头开始任务
工作流示意图
在这里插入图片描述

4、数据治理

Atlas(元数据管理)

0.84最新

元数据打通了数据源、数据仓库、数据应用,记录了数据从产生到消费的全过程。因此,数据治理的核心就是元数据管理。

Atlas是一个可伸缩和可扩展的核心基础治理服务集合,使企业能够有效地和高效地满足Hadoop中的合规性要求,并允许与整个企业数据生态系统的集成。

ApacheAtlas为组织提供开放式元数据管理和治理功能,用以构建其数据资产目录,对这些资产进行分类和管理,并为数据科学家,数据分析师和数据治理团队提供围绕这些数据资产的协作功能。

元数据在hive里面用Kafka去读,读完直接到内核储存到hbase里面,然后用solr查询对应的元数据,然后支持二次开发的功能,最后图形化展示。

数据质量监控(Griffin)

0.4/0.5版本 对网络要求高,需要重新编译,用自己写脚本

分为batch(批)streaming(流),实时数据检测未有界面配置,可以通过api的方式提交。
Apache可视化监控工具,一步一步走,最终呈现监控画面

为什么要做数据质量监控(2019 年下半年)

1)数据不一致
2)数据不完整
3)数据不合规
4)数据不可控
5)数据冗余

建设方法

在这里插入图片描述

质量监管平台建设,主要包含如下 8 大流程步骤:

质量需求:发现数据问题;信息提报、收集需求;检核规则的需求等;

提炼规则:梳理规则指标、确定有效指标、检核指标准确度和衡量标准;

规则库构建:检核对象配置、调度配置、规则配置、检核范围确认、检核标准确定
等;

执行检核:调度配置、调度执行、检核代码;

问题检核:检核问题展示、分类、质量分析、质量严重等级分类等;

分析报告:数据质量报告、质量问题趋势分析,影响度分析,解决方案达成共识;

落实处理:方案落实执行、跟踪管理、解决方案 Review 及标准化提炼;

知识库体系形成:知识经验总结、标准方案沉淀、知识库体系建设。

权限管理

ranger ,sertry,人物认证

5、数据中台

https://mp.weixin.qq.com/s/nXI0nSSOneteIClA7dming
将相同模块提取,共同的

6、数据湖

数据湖(Data Lake)是一个存储企业的各种各样原始数据的大型仓库,其中的数据可供存取、处理、分析及传输。

数据湖是一个概念,而 Hadoop 是用于实现这个概念的技术。

7、OLAP(联机分析处理)

On line Analytical Processing
是一种软件技术,它使分析人员能够迅速、一致、交互地从【各个方面观察信息】,以达到深入理解数据的目的。【多维度分析】
维度2的n次方-1 种

OLAP类型:
ROLAP:基于关系型数据库,不需要预计算
MOLAP:基于多维数据集,需要预计算

它具有FASMI(Fast Analysis of Shared Multidimensional Information),即共享多维信息的快速分析的特征。
其中F是快速性(Fast),指系统能在数秒内对用户的多数分析要求做出反应;
A是可分析性(Analysis),指用户无需编程就可以定义新的专门计算,将其作为分析的一部 分,并以用户所希望的方式给出报告;
M是多维性(Multi—dimensional),指提供对数据分析的多维视图和分析;
I是信息性(Information),指能及时获得信息,并且管理大容量信息。

OLAP展现在用户面前的是一幅幅多维视图

OLTP:像mysql 专门处理后台业务的数据,GB
OLAP:擅长分析的,hive,spark,TB到PB

运维(扩展)

Zabbix监控集群(运维)

监控某些进程出现问题,进行通知

官方网站:https://www.zabbix.com/
Zabbix是一个基于WEB界面的提供分布式系统监控以及网络监控功能的企业级开源运维平台,也是目前国内互联网用户中使用最广的监控软件,云智慧遇到的85%以上用户在使用Zabbix做监控解决方案。
用户群:90%以上中小型的泛互联网企业
在这里插入图片描述

Ganglia

官方网站:http://ganglia.info/
Ganglia是加州大学伯克利分校发起的一个开源集群监控项目,设计之初是用于监控数以千计的网络节点。Ganglia是一个跨平台可扩展的,高性能计算系统下的分布式监控系统。它已被广泛移植到各种操作系统和处理器架构上。
用户群:适用于大型服务器集群用户。

版本控制(要会)

不懂的兄弟们,网上搜索,大概花个三个小时,就差不多了,常用性就不说了,可从gitee码云上手,毕竟中文。

Git版本控制

开源的分布式版本控制系统,也是个内容管理系统(CMS),工作管理系统等。

Git与SVN区别

Git是分布式的,SVN不是:
这是Git和其它非分布式的版本控制系统,例如SVN,CVS等,最核心的区别。

Git把内容按元数据方式存储,而SVN是按文件:
所有的资源控制系统都是把文件的元信息隐藏在一个类似.svn、.cvs等的文件夹里。

Git分支和SVN的分支不同:
分支在SVN中一点都不特别,其实它就是版本库中的另外一个目录。

Git没有一个全局的版本号,而SVN有:
目前为止这是跟SVN相比Git缺少的最大的一个特征。
Git的内容完整性要优于SVN:
Git的内容存储使用的是SHA1哈希算法。这能确保代码内容的完整性,确保在遇到磁盘故障和网络问题时降低对版本库的破坏。

在这里插入图片描述

呼!!暂时就到这吧,后续如有或小伙伴在工作面试遇到的可以留言这里,给大家再补充。刚好参加了这个活动,大家记得关注点赞收藏三连支持下哈,整理不易,感谢兄弟们!

单是说不行,要紧的是做。——鲁迅

前言

hi!我是啊晨 ,一个大数据分享者,好久没发博客了,最近忙于找工作,然后顺带整理了一些资料,相信也有一部分好兄弟,也在苦于找工作,或者正在学习大数据的知识,不太会总结的。我只能这样说,你来对了。
这里大概的罗列了一些,面试常会问频率高一些的点,或者我面试遇到的一些问题,不是很全面,后续会补充,很多但没废话。
也可以阅读我的其它大数据文章,抱拳!
中间有什么问题好兄弟们一定要留言:

在这里插入图片描述

正片

语言工具类

这里只针对可能会面试到的,像Scala、Python面试也没啥问的,这里就不列举了

Java

实现线程的两种方式

1、继承Thread类,重写run方法
2、实现Thread类的Runnable接口,重写run方法

两者区别:1不会共享线程,四个都是100张票,2会共享线程,多数采用第二种方式。

集合

List集合

有序可重复
add添加
get获取索引位置元素
remove 移除
set 设置
listiterator 特有迭代器

ArrayList

大小可变的数组的实现。
有序可重复,线程不安全。

初识为10,容量一般是1.5倍扩容。

遍历方式:
迭代器
list特有的
for:一般for和增强for(1.5jdk的新特性)

LinkedList

有序,可重复,底层双向链表。

和ArrayList、vector区别:
linkedlist 增删快,查询慢,线程不安全
ArrayList 增删慢,查询快,线程不安全
vector 线程安全,用法同ArrayList

Set集合

不重复,无序

HashSet

对于自定义类,需要手动进行去重的操作。
重写hashCode与equals方法。

储存原理:
① 调用对象的hashCode方法算出对象的哈希码值,通过该值经过哈希算法,算出该对象在该集合中存储的位置。
② 如果该位置没有元素,就直接放置在该位置,但是如果该位置有元素,此现象称为哈希冲突也叫哈希碰撞,会 通过equals方法比较该位置的两个对象,如果相等,则不插入。
③ 如果不相等,会在该位置下以线性链表的形式插入。但是在1.8jdk之后,当线性链表长度大于等于8时,该结构 改为 红黑树的结构。(1.8jdk之后,发生哈希冲突,以链表+红黑树的形式存储。)

构造方法:hashset()初识容量是16

二叉查找树

左侧的节点永远小于根节点,右侧的节点永远大于根节点。

红黑树 就是一种自平衡二叉查找树。

TreeSet

基于红黑树的实现,无序不重复,可排序

排序实现comparable接口,实现compareTo方法

LinkedHashset

用于购物车,有不重复
链表+哈希表

collections 集合工具类

Stack 栈:先进后出
Queue 队列:先进先出

Map集合

collection 单列集合:每个储存元素都是一个对象
map:双列集合,键值对

put 添加、get获取、remove 移除、size长度

map的子类:
HashMap:底层 哈希表结构。

遍历:
list集合遍历 : 1》 迭代器 2》 for循环 3 3》 ListIterator set集合 : 1》 迭代器 2》 for循环 (增强for循环 )

① keySet() 返回key的set集合形式。
② entrySet() 返回entry形式的set集合

TreeMap

HashMap: key的特性: 无序 不重复 .底层是哈希表

TreeMap: key的特性: 可排序 不重复 。底层是红黑树。

HashTable

HashTable :哈希表 。线程安全的
与HashMap区别 :
① HashMap 线程不安全的。
② HashTable 线程安全的。

JVM

JVM内存分哪几个区,每个区的作用是什么?
在这里插入图片描述

方法区:(被加载的信息,常量,静态变量编译后的代码等数据)

a.有时候也成为永久代,在该区内很少发生垃圾回收,但是并不代表不发生GC,在这里进行的GC主要是对方法区里的常量池和对类型的卸载

b.方法区主要用来存储已被虚拟机加载的类的信息、常量、静态变量和即时编译器编译后的代码等数据。

c.该区域是被线程共享的。

d.方法区里有一个运行时常量池,用于存放静态编译产生的字面量和符号引用。该常量池具有动态性,也就是说常量并不一定是编译时确定,运行时生成的常量也会存在这个常量池中。

虚拟机栈:(java方法服务,储存局部变量方法出口等)

所称的栈内存,它为java方法服务,每个方法在执行的时候都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接和方法出口等信息。
虚拟机栈是线程私有的,它的生命周期与线程相同。
局部变量表里存储的是基本数据类型、returnAddress类型(指向一条字节码指令的地址)
和对象引用,这个对象引用有可能是指向对象起始地址的一个指针,也有可能是代表对
象的句柄或者与对象相关联的位置。局部变量所需的内存空间在编译器间确定
操作数栈的作用主要用来存储运算结果以及运算的操作数,它不同于局部变量表通过索
引来访问,而是压栈和出栈的方式

本地方法栈

和虚拟机栈类似,只不过本地方法栈为Native(本地)方法服务。

堆(对象实例创建,垃圾回收操作)

所有线程所共享的一块内存,在虚拟机启动时创建,几乎所有的对象实例都在这里创建,因此该区域经常发生垃圾回收操作。

程序计数器

分支、循环、跳转、异常处理和线程恢复等功能都需要依赖这个计数器完成,该内存区
域是唯一一个java虚拟机规范没有规定任何OOM(内存用完了)情况的区域。

Java自带哪几种线程池?(4)

1)newCachedThreadPool(缓存)

可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
工作线程的【创建数量几乎没有限制】(其实也有限制的,数目为Interger.
MAX_VALUE),这样可灵活的往线程池中添加线程。【注意控制任务数量,同时大量运行可能系统瘫痪】

如果长时间没有往线程池中提交任务,即如果工作线程空闲了指定的时间(默认为1
分钟),则该工作线程将自动终止。终止后,如果你又提交了新的任务,则线程池重新创
建一个工作线程。
在使用CachedThreadPool时,一定要注意控制任务的数量,否则,由于大量线程同时
运行,很有会造成系统瘫痪。

2)newFixedThreadPool(固定)

创建一个指定工作线程数量的线程池。
没提交一个任务就创建一个工作线程,达到最大,将任务存入池队列。
典型优秀的线程池,提高程序效率节省创建开销。但是如果没【运行任务时,不会释放,占用系统资源。】

3)newSingleThreadExecutor(单线程)

单线程话的executor,唯一的线程执行任务,指定顺序(FIFO,LIFO,优先级)执行。
【顺序执行各个任务,任意时间不会有多个线程】

4)newScheduleThreadPool(时间)

创建一个【定长的线程池】,而且支持【定时的以及周期性的任务执行】,支持定时及周期性任务执行。【延迟3秒执行】。

HashMap和HashTable区别

1)线程安全性不同

【HashMap是线程不安全的】,【HashTable是线程安全的】,其中的方法是【Synchronize】的,【多线程并发】,可直接【hashtable】,【hashmap必须加同步处理】

2)是否提供contains方法

HashMap只有containsValue和containsKey方法;
HashTable有contains、containsKey
和containsValue三个方法,其中contains和containsValue方法功能相同。

3)key和value是否允许null值

HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。
Hashtable中,key和value都不允许出现null值。

4)数组初始化和扩容机制

HashMap不指定容量默认为16,HashTable为11。
Hashtable不要求底层数组的容量一定要为2的整数次幂,而HashMap则要求一定为2的整数次幂。
HashMap扩容变2倍,Hashtable2倍加1

TreeSet和HashSet区别

HashSet是采用【hash表】来实现的。其中的元素【没有按顺序排列】,add()、remove()以及contains()等方法都是复杂度为O(1)的方法。
【无序,访问遍历快】
TreeSet是采用树结构实现(【红黑树算法】)。元素是【按顺序进行排列】,但是add()、
remove()以及contains()等方法都是复杂度为O(log(n))的方法。
【有序,排序用】

Stringbuffer和Stringbuild区别

方法和功能是等价的
【StringBuffer】采用了synchronized关键字进行修饰,因此是【线程安全的】,而【StringBuilder】没有这个修饰,可以被认为是线程【不安全的。】
单线程程序下,StringBuilder效率快,StringBuffer相对慢

Final、Finally、Finalize

final:修饰符(关键字)有三种用法:修饰类、变量和方法。
(修饰类时,意味着它不能再派生出新的子类,即不能被继承,因此它和abstract是反义词。修饰变量时,该变量使用中不被改变,必须在声明时给定初值,在引用中只能读取不可修改,即为常量。修饰方法时,也同样只能使用,不能在子类中被重写。)
finally:通常放在【try…catch】的后面构造最终执行代码块,这就意味着程序【无论正常执
行还是发生异常,这里的代码只要JVM不关闭都能执行】,可以将【释放外部资源的代码写在
finally块中。】
finalize:Object类中定义的方法,Java中允许使用finalize()方法在垃圾收集器将对象
从【内存中清除】出去之前做必要的【清理工作】。这个方法是由【垃圾收集器】在销毁对象时调用的,通过重写finalize()方法可以【整理系统资源】或者执行【其他清理工作。】

==和Equals区别

== :如果比较的是基本数据类型,那么比较的是变量的值,如果比较的是引用数据类型,那么比较的是地址值(两个对象是否指向同一块内存) equals:如果没重写equals方法比较的是两个对象的地址值。如果重写了equals方法后我们往往比较的是对象中的属性的内容
equals方法是从Object类中继承的,默认的实现就是使用 ==

在这里插入图片描述

Java类加载过程?

1)加载

加载时类加载的第一个过程,在这个阶段,将完成一下三件事情:
a.通过一个类的全限定名获取该类的二进制流。
b.将该二进制流中的静态存储结构转化为方法去运行时数据结构。
c.在内存中生成该类的Class对象,作为该类的数据访问入口

2)验证

验证的目的是为了确保Class文件的字节流中的信息不回危害到虚拟机.在该阶段主要完成
以下四钟验证:
a.文件格式验证:验证字节流是否符合Class文件的规范,如主次版本号是否在当前虚拟
机范围内,常量池中的常量是否有不被支持的类型.
b.元数据验证:对字节码描述的信息进行语义分析,如这个类是否有父类,是否集成了不
被继承的类等。
c.字节码验证:是整个验证过程中最复杂的一个阶段,通过验证数据流和控制流的分析,确定程序语义是否正确,主要针对方法体的验证。如:方法中的类型转换是否正确,跳
转指令是否正确等。
d.符号引用验证:这个动作在后面的解析过程中发生,主要是为了确保解析动作能正确执
行。
e.准备
准备阶段是为类的静态变量分配内存并将其初始化为默认值,这些内存都将在方法区中进行
分配。准备阶段不分配类中的实例变量的内存,实例变量将会在对象实例化时随着对象一起
分配在Java堆中。

3)解析

该阶段主要完成符号引用到直接引用的转换动作。解析动作并不一定在初始化动作完成之前,也有可能在初始化之后。

4)初始化

初始化时类加载的最后一步,前面的类加载过程,除了在加载阶段用户应用程序可以通过自定义类加载器参与之外,其余动作完全由虚拟机主导和控制。到了初始化阶段,才真正开始执行类中定义的Java程序代码。

java中垃圾收集的方法?

1)引用计数法

(每引用回收,需要维护一个引用计算器)

应用于:微软的COM/ActionScrip3/Python等
a)如果对象没有被引用,就会被回收,缺点:需要维护一个引用计算器

2)复制算法

(效率高,内存需求大.使用在占空间比较小刷新次数多的新生区)

年轻代中使用的是MinorGC,这种GC算法采用的是复制算法(Copying)
a)效率高,缺点:需要内存容量大,比较耗内存
b)使用在占空间比较小、刷新次数多的新生区

3)标记清除

(效率低,会产生碎片)

老年代一般是由标记清除或者是标记清除与标记整理的混合实现
a)效率比较低,会差生碎片

4)标记压缩

(效率低速度慢,需要移动对象,但不会产生碎片)

老年代一般是由标记清除或者是标记清除与标记整理的混合实现
a)效率低速度慢,需要移动对象,但不会产生碎片。

5)标记清除压缩

(使用占空间大刷新次数小的养老区,3,4的集合体)

标记清除标记压缩的集合,多次GC后才Compact
a)使用于占空间大刷新次数少的养老区,是34的集合体

如何判断一个对象是否存活?(或者GC对象的判定方法)

引用计数法
可达性算法(引用链法)

什么是类加载器,类加载器有哪些?

实现通过类的权限定名获取该类的二进制字节流的代码块叫做类加载器。

主要有一下四种类加载器:
1)启动类加载器(BootstrapClassLoader)用来加载java核心类库,无法被java程序直接引用。

2)扩展类加载器(extensionsclassloader):它用来加载Java的扩展库。Java虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载Java类

3)系统类加载器(systemclassloader)也叫应用类加载器:它根据Java应用的类路径(CLASSPATH)来加载Java类。一般来说,Java应用的类都是由它来完成加载的。可以通过ClassLoader.getSystemClassLoader()来获取它。

4)用户自定义类加载器,通过继承java.lang.ClassLoader类的方式实现。

简述Java内存分配与回收策略以及MinorGC和MajorGC(fullGC)

内存分配

1)栈区:栈分为java虚拟机栈和本地方法栈

2)堆区:堆被所有线程共享区域,在虚拟机启动时创建,唯一目的存放对象实例。堆区是
gc的主要区域,通常情况下分为两个区块年轻代和年老代。更细一点年轻代又分为Eden
区,主要放新创建对象,Fromsurvivor和Tosurvivor保存gc后幸存下的对象,默认
情况下各自占比8:1:1。

3)方法区:被所有线程共享区域,用于存放已被虚拟机加载的类信息,常量,静态变量等
数据。被Java虚拟机描述为堆的一个逻辑部分。习惯是也叫它永久代(permanment
generation)

4)程序计数器:当前线程所执行的行号指示器。通过改变计数器的值来确定下一条指令,
比如循环,分支,跳转,异常处理,线程恢复等都是依赖计数器来完成。线程私有的。

回收策略以及Minor(次要)GC和Major(主要)GC:

1)对象优先在堆的Eden区分配。

2)大对象直接进入老年代。

3)长期存活的对象将直接进入老年代。当Eden区没有足够的空间进行分配时,虚拟机会执行一次MinorGC.MinorGC通常发生在新生代的Eden区,在这个区的对象生存期短,往往发生GC的频率较高,回收速度比较快;

FullGc/MajorGC发生在老年代,一般情况下,触发老年代GC的时候不会触发MinorGC,但是通过配置,可以在FullGC之前进行一次MinorGC这样可以加快老年代的回收速度

J.U.C(java.util.concurrent)

Synchronized与Lock的区别

1)Synchronized能实现的功能Lock都可以实现,而且Lock比Synchronized更好用,更灵活。
2)Synchronized可以自动上锁和解锁;Lock需要手动上锁和解锁

Runnable和Callable的区别

1)Runnable接口中的方法没有返回值;Callable接口中的方法有返回值
2)Runnable接口中的方法没有抛出异常;Callable接口中的方法抛出了异常
3)Runnable接口中的落地方法是run方法;Callable接口中的落地方法是call方法

什么是分布式锁

当在【分布式模型下,数据只有一份(或有限制)】,此时需要利用锁的技术控制【某一时刻
修改数据的进程数】。
分布式锁可以【将标记存在内存】,只是该内存不是某个进程分配的内存而是【公共内存】,如【Redis】,通过set(key,value,nx,px,timeout)方法添加分布式锁。

什么是分布式事务

事务的参与者,支持事务的服务器,资源服务器,以及事务管理器分别位于不同的分布式系统的不同节点。
(一次大操作,有不同小操作组成,这些小操作分布在不同的服务器上,且属于不同应用,分布式要保证这些操作全成功或全失败)

IO

① 功能(方向) :
1 输入流: InputStream/Reader
2 输出流: OutputStream/Writer
② 操作的数据的位数(数据类型):
1 字节流:InputStream/OutputStream
2 字符流:Reader/Writer

Linux

一般就直接问平常常用的命令有哪些?
不要说一些很掉价的命令:cd cd … ll ls mv cp.
说些高大上的:grep find tar -zxvf和-zcvf whereis kill-9 (这里不知道需要反思一下了)
top 查看内存 、df -h 查看磁盘储存情况 、iotop 磁盘io读写情况、ps aus和ps -ef 查看进程
shell高级命令:cut(剪数据)、sed(编辑器,一次一行)、awk(文本分析工具)、sort(排序)
以上高级awk,sed要一定记住的。
(shell开头:#!/bin/bash)

数据采集类

Flume

分布式的海量日志采集、聚合和传输的系统

Flume工作机制是什么?

核心概念是agent,里面包括source、chanel和sink三个组件。
source运行在日志收集节点进行日志采集,之后临时存储在chanel中,sink负责将chanel中的数据发送到目的地。
只有成功发送之后chanel中的数据才会被删除。
首先书写flume配置文件,定义agent、source、chanel和sink然后将其组装,执行flumeng命令。

Flume组成,Put事务,Take事务

source

TaildirSource:断点续传、(失败可从失败的地方继续上传)多目录。
【Flume1.6以前需要自己自定义Source记录每次读取文件位置,实现断点续传】

【Apache1.7版本产生的taildirsource】

如果挂了,可能重复数据,不会丢失。
不处理,企业中很多不处理,会影响性能。(一般不挂)
处理:增加事务:
在下一级处理:hive dwd 层;sparkstreaming(数据小),redis(大)。开窗取第一条,或分组。

是否支持递归?
默认不支持:自定义->递归代码(遍历文件夹)+读取文件(调用读取的方法)

channel

FileChannel:数据存储在磁盘,宕机数据可以保存。但是传输速率慢。适合对数据传输可靠性要求高的场景,比如,金融行业。

默认储存:100万

MemoryChannel:数据存储在内存中,宕机数据丢失。传输速率快。适合对数据传输可靠性要求不高的场景,比如,普通的日志数据。

默认储存:100个

KafkaChannel:减少了Flume的Sink阶段,提高了传输效率。

那个版本产生的?
1.6,开始没火,数据:topic+内容 =》还要清洗
1.7 时解决了bug

在生产环境怎么选?
下一级是Kafka,优先选择Kafkachannel

如果公司比较看重可靠性(金融公司,或者跟钱有关的);filechannel
如果公司比较看重效率(普通的日志)memory channel

sink

hdfs flume->Kafka->flume->hdfs
hdfs sink 小文件
三个参数:文件大小(128),时间(1-2小时),event个数(禁用)

事务

Source到Channel是Put(移动)事务
Channel到Sink是Take(取)事务

自定义拦截器&采集多条数据

采集多条自定义俩拦截器,ETL拦截器,日志类型区分拦截器
etl:主要过滤不合法的时间戳和json数据不完整的日志(判断是否{开头}结尾)

日志类型区分拦截器:将启动日志和事件日志区分开来,发往kafka的不同topic。
(start启动、和event事件)

作用于source之后,channel之前,不要太复杂占用时间

拦截器不要行不行?
可以=》在下一级处理:hive的dwd,sparksteaming

对传输要求不高,就可以使用,要求高的尤其是推荐,那就不在这做。

ETL工具类

sqoop

大数据生态体系中数据传输层的工具,完成Haoop文件存储体系(HDFS、Hive、HBase)与关系型数据库(MySQL)之间的数据导入导出。

Sqoop原理

将导入或导出命令翻译成MapReduce程序来实现(没有reducetask,不需要,因为Sqoop只是读取数据,输出数据,不需要合并计算等操作)
在翻译出的MapReduce中主要是对InputFormat和OutputFormat进行定制。
import(导入)原理:通过指定的分隔符进行数据切分,将分片传入各个map中,在map任务中在每行数据进行写入处理没有reduce。
export(导出)原理:根据要操作的表名生成一个java类,并读取其元数据信息和分隔符对非结构化的数据进行匹配,多个map作业同时执行写入关系型数据库

Sqoop参数

/opt/module/sqoop/bin/sqoopimport
–connect
–username
–password
–target-dir#路径,不能存在
–delete-target-dir#存在删掉
–num-mappers
–fields-terminated-by#分隔符
–query “$2” ‘and $CONDITIONS;’

Sqoop导入导出Null存储一致性问题

Hive中的Null在底层是以“”来存储,而MySQL中的Null在底层就是Null,为了保证数据两端的一致性。

在导出数据时采用inputnullstring和inputnullnonstring两个参数。
导入数据时采用nullstring和nullnonstring。

Sqoop数据导出一致性问题

1)场景1:如Sqoop在导出到Mysql时,使用4个Map任务,过程中有2个任务失败,
那此时MySQL中存储了另外两个Map任务导入的数据,此时老板正好看到了这个报表数据。而开发工程师发现任务失败后,会调试问题并最终将全部数据正确的导入MySQL,那后面老板再次看报表数据,发现本次看到的数据与之前的不一致,这在生产环境是不允许的。

2)场景2:设置map数量为1个(不推荐,面试官想要的答案不只这个)
多个Map任务时,采用–stagingtable方式,仍然可以解决数据一致性问题。

–staging-table方式:用作用于暂存导出数据的辅助表。最后,已分阶段处理的数据将在单个事务中移至目标表。

Sqoop底层运行的任务是什么

只有Map阶段,没有Reduce阶段的任务。

sqoop在导入数据的时候数据倾斜

涉及到俩参数:num-mappers:启动n个map来并行导入数据,默认4个;split-by:按照某一列来切分表的工作单位。
通过rownum()生成均匀的字段,然后指定为分割字段

sqoop数据导出parquet

ads层数据用sqoop往mysql导入的时候,如果用了orc(parquet)不能导入,需要转化text格式。

1.创建临时表,把parquet中数据导入到临时表,再导入。

2.sqoop里面有参数,可以直接把parquet转换为text

3.ads 层建表的时候就不要建parquet表。【推荐】

开源ETL工具Kettle

数据整合工具,Kettle中文名称叫水壶,描述你想做什么,而不是你想怎么做,etl数据预处理
Kettle目前包含五个产品:Spoon、Pan、Chef、Kithcen、Encr。

这里没涉及到什么问题,etl很流行,使用很简单,如不知道的,网上随意一搜就有,这里不过多讲解

数据储存类

Hadoop

Hadoop介绍

分布式系统基础架构
集群不一定是分布式,分布式一定是集群
谷歌的三驾马车

GFS>HDFSGFSGoogleFileSystem>hadoopdistributedFileSystem
MapReduce>MR>分析计算框架
BigTable>Hbase大数据领域的数据库

常用端口号?

2.x 50070 8088 9000 19888 重要
3.x 9870 8088 8082 19888

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

Hadoop启动的进程??

NameNode,DataNode,SecondaryNameNode

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

(1)配置文件:
2.x :coresite.xml、hdfssite.xml、mapredsite.xml、yarnsite.xml
hadoopenv.sh、yarnenv.sh、mapredenv.sh、slaves(不能用空行,不能有空格)
3.x:workers代替sh、slaves

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

hadoop优化&解决小文件??

MapReduce优化方法

数据输入

(1)合并小文件:对小文件进行归档(Har)、自定义Inputformat将小文件存储成SequenceFile文件。
(2)采用CombineTextInputFormat来作为输入,解决输入端大量小文件场景。
(3)对于大量小文件Job,可以开启JVM重用

Map阶段

增大环形缓冲区大小。由100m扩大到200m
增大环形缓冲区溢写的比例。由80%扩大到90%

通过调整io.sort.mb及sort.spill.percent参数值(在mapreddefault.xml),增大触发spill的内存上限,减少spill次数,从而减少磁盘IO。

减少合并(merge)次数(10个文件,一次20个merge)

通过调整io.sort.factor参数(在mapreddefault.xml),增大merge的文件数目,减少merge的次数,从而缩短MR处理时间

在map之后,不影响业务逻辑前提下,先进行combine处理,减少I/O。

Reduce阶段

合理设置map和reduce数

两个都不能设置太少,也不能设置太多。
太少,会导致task等待,延长处理时间;
太多,会导致map、reduce任务间竞争资源,造成处理超时等错误。

设置map、reduce共存

调整slowstart.completedmaps参数,使map运行到一定程度后,reduce也开始运行,减少reduce的等待时间。

规避使用Reduce,因为Reduce在用于连接数据集的时候将会产生大量的网络消耗。
增加每个Reduce去Map中拿数据的并行数
集群性能可以的前提下,增大Reduce端存储数据内存的大小。

IO传输

采用数据压缩的方式,减少网络IO的的时间。安装Snappy和LZOP压缩编码器。
使用SequenceFile二进制文件

整体

(1)MapTask默认内存大小为1G,可以增加MapTask内存大小为45g
(2)ReduceTask默认内存大小为1G,可以增加ReduceTask内存大小为45g
(3)可以增加MapTask的cpu核数,增加ReduceTask的CPU核数
(4)增加每个Container的CPU核数和内存大小
(5)调整每个MapTask和ReduceTask最大重试次数

Hadoop解决数据倾斜方法

一、提前在map进行Combine,减少传输量(如果大量key在不同mapper,不是很有效)

二、再不同mapper时,采用二次mr。
1、局部聚合加全局聚合。
第一次加1到n随机前缀,分布不同reduce达到负载均衡。
第二次去掉key的随机前缀,按原keyreduce处理,性能较差。

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

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

采用MapJoin,尽量避免ReduceJoin。
map端适合小表大表,只有map工作,有效避免数据倾斜。
reduce需要经过shuffle,非常耗资源。

HDFS

高可靠、高吞吐量的分布式文件系统
优缺点:

优点高容错,适合大数据处理,可构建廉价机器
缺点不适合低延迟,无法高效对小文件储存

HDFS写数据流程

在这里插入图片描述

(1)客户端通过DistributedFileSystem(分布式文件系统)模块向NameNode请求上传文件,NameNode检查目标文件是否已存在,父目录是否存在。
(2)NameNode返回是否可以上传。
(3)客户端请求第一个block上传到哪几个datanode服务器上。
(4)NameNode返回3个datanode节点,分别为dn1、dn2、dn3。
(5)客户端通过FSDataOutputStream(文件输出流)模块请求dn1上传数据,dn1收到请求会继续调用dn2,然后dn2调用dn3,将这个通信管道建立完成。
(6)dn1、dn2、dn3逐级应答客户端。
(7)客户端开始往dn1上传第一个block(先从磁盘读取数据放到一个本地内存缓存),以packet(数据包)为单位,dn1收到一个packet就会传给dn2,dn2传给dn3;
当一个block传输完成之后,客户端再次请求NameNode上传第二个block的服务器。(重复执行37步)。

HDFS的读数据流程

在这里插入图片描述

(1)客户端通过DistributedFileSystem(分布式文件系统)向NameNode请求下载文件,NameNode通过查询元数据,找到文件块所在的DataNode地址。
(2)挑选一台DataNode(就近原则,然后随机)服务器,请求读取数据。
(3)DataNode开始传输数据给客户端(从磁盘里面读取数据输入流,以packet(数据包)为单位来做校验)。
(4)客户端以packet为单位接收,先在本地缓存,然后写入目标文件(并行,快)。

NameNode和SecondaryNameNode工作机制,现在问的少了,生产是没有SecondaryNameNode的,放张我画的图大家有个印象就行。
在这里插入图片描述

MapReduce

(PB级以上海量数据的离线处理(分布式的离线并行编程计算框架)不擅长实时计算,流式计算,DAG(有向无环图))

架构

MrAppMaster:负责整个程序的过程调度及状态协调。
MapTask:负责map阶段的整个数据处理流程。
ReduceTask:负责reduce阶段的整个数据处理流程。

MapReduce工作流程

在这里插入图片描述

1,首先有一份文件,
2,客户端submit(提交文件)前,获取数据信息,根据参数配置形成任务分配的规划(分块0128)
3,然后提交切片信息到yarnRM
4,yarnRM找到闲着的机器,启动Mrappmaster(指挥mapperreduce),计算maptask数量
5,然后分好的机器开始运行,inputFormat接口TextInputFormat(默认)实现类里面的属性RecorderReader调用reader方法一行行读数据,封装成k,v
6,经过处理context.write写出数据
7,写出后会进入环形缓冲区,默认100M,如果到80%会将k,v,溢写(到磁盘)
8.(写出数据后,进入缓存前,可以编写分区)然后根据溢写分区排序,
9.溢写到文件(分区且区内有序)
10.merge归并排序
11.最后Combiner将相同合并(预先合并,可以有可以没有,只是当前一台的大小,减少文件的大小)

Shuffle机制

map方法后reduce方法前,map后首先到getpartition 标记数据是哪个分区,然后进入环形缓冲区,一边存数据,一边存索引,默认大小100m,80%会溢写,溢写前要排序,排序的手段:快排,对key的索引,按字典顺序排。溢写到文件,对数据归并排序,分区有序。reduce拉取map对应数据先放内存,内存不够放磁盘,然后归并写出。

优化:
100->200m,
80->90
默认归并10个->20个文件,
提前combinner不要影响业务逻辑,(求和可以平均值不行)
压缩格式减少磁盘io:snappy,lzo快,snappy多一些

推测执行(Speculative Execution)

如多个任务已经完成,有些只跑了10%,开启推测执行后,Hadoop会将为该task启动备份任务,让该task和原始同时处理一份数据,哪个个先处理完,就为最终结果,并且在运行完成后kill掉另外的一个任务。

是否启用推测执行,如果能根据资源情况来决定,如果在资源本身就不够的情况下,还要跑推测执行的任务,这样会导致后续启动的任务无法获取到资源,以导致无法执行。

Yarn

资源调度平台
架构

1.resourcemanager(RM):处理客户端请求,监控nodemanager,启动或监控applicationmater,资源分配与调度
2.nodemanager(NM):管理单个节点的资源,处理来自resourcemanager的命令,处理applicationmater的命令
3,applicationmaster(AM):负责读取客户端提交的切片规划,为应用程序申请资源并分配给内部的任务,任务的监控与容错
4,container:yarn中资源抽象,封装某个节点的多维度资源,如:内存,cpu,磁盘,网络等

Yarn工作机制

在这里插入图片描述
(1)Mr程序提交到客户端所在的节点。
(2)Yarnrunner向Resourcemanager申请一个Application。
(3)rm将该应用程序的资源路径返回给yarnrunner。
(4)该程序将运行所需资源提交到HDFS上。(jar(执行任务代码),xml(按照写的配置执行),切片信息)
(5)程序资源提交完毕后,申请运行mrAppMaster。
(6)RM将用户的请求初始化成一个task。
(7)其中一个NodeManager领取到task任务。
(8)该NodeManager创建容器Container,并产生MRAppmaster。
(9)Container从HDFS上拷贝资源到本地。
(10)MRAppmaster向RM申请运行maptask资源。
(11)RM将运行maptask任务分配给另外两个NodeManager,另两个NodeManager分别领取任务并创建容器。
(12)MRAppMaster向两个接收到任务的NodeManager发送程序启动脚本,这两个NodeManager分别启动maptask,maptask对数据分区排序。
(13)MrAppMaster等待所有maptask运行完毕后,向RM申请容器,运行reducetask。
(14)reducetask向maptask获取相应分区的数据。
(15)程序运行完毕后,MR会向RM申请注销自己。

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

Hadoop调度器重要分为三类:

FIFO(先进先出)、CapacityScheduler(容量调度器)和FairSceduler(公平调度器)。

Hadoop2.7.2后默认的资源调度器是容量调度器,之前是FIFO

Apache:默认容量,CDH:默认公平

区别:生产绝不会用FIFO

Hadoop宕机

1)如果MR造成系统宕机。
此时要控制Yarn同时运行的任务数,和每个任务申请的最大内存。调整参数:yarn.scheduler.maximumallocationmb(单个任务可申请的最多物理内存量,默认是8192MB)

2)如果写入文件过量造成NameNode宕机。那么调高Kafka的存储大小,控制从Kafka
到HDFS的写入速度。高峰期的时候用Kafka进行缓存,高峰期过去数据同步会自动跟上。

Hive

数据仓库

数据仓库是一个支持管理决策的数据集合。数据是面向主题的、集成的、不易丢失的并且是时变的。数据仓库是所有操作环境和外部数据源的快照集合。

概念

基于Hadoop的一个数据仓库工具,将结构化的数据文件映射为一张表,并提供类SQL查询功能,所提供的类SQL查询语言叫做HQL。
HQL语句转化为MapReduce程序在Hadoop平台执行,数据存储在Hdfs之上
Hive是针对数据仓库应用设计的,而数据仓库的内容是读多写少的

【facebook开发,统计海量数据的仓库,将结构化数据映射张表提供类sql查询叫HQL,将Hql转化为MapReduce程序在hadoop执行,储存在hdfs上。】

Hive中存放的是什么?

表。
存的是和hdfs的映射关系,hive是逻辑上的数据仓库,实际操作的都是hdfs上的文件,HQL就是用sql语法来写的mr程序。

!Hive与关系型数据库的关系?比较?

数据量:hive 大 mysql 小
速度:大数据场景快,小数据场景快

Hive和数据库除了拥有类似的查询语言,再无类似之处
1)数据存储位置

Hive存储在HDFS。
数据库将数据保存在块设备(硬盘,U盘,SD卡等)或者本地文件系统中。

2)数据更新

Hive中不建议对数据的改写。
而数据库中的数据通常是需要经常进行修改的,

3)执行延迟

Hive执行延迟较高。
数据库的执行延迟较低。当然,这个是有条件的,即数据规模较小,当数据规模大到超过数据库的处理能力的时候,Hive的并行计算显然能体现出优势。

4)数据规模

Hive支持很大规模的数据计算
数据库可以支持的数据规模较小。

请说明hive中4个by各代表什么意思?

orderby:全局排序,只有一个Reducer(多个reducer无法保证全局有序)。只有一个reducer,会导致当输入规模较大时,需要较长的计算时间。(很少用)

sortby:分区内有序

distributeby:类似MR中Partition,进行分区,结合sortby使用。(按照指定的字段对数据进行划分输出到不同的reduce中。)
(工作常用sortby+distributeby)

clusterby:当Distributeby和Sortsby字段相同时,可以使用Clusterby方式
除了具有distributeby的功能外还兼具sortby的功能。
只能升序,不能指定排序规则ASC或DESC

窗口函数

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

内表和外表的区别?

管理表(内部表,默认)删除是元数据和表数据都删除(很少使用,自己使用的临时表,才会创建内部表)

外部表,删除不会删除这份数据,描述表的元数据会被删掉(外部共享,一般都是外表)

Hive的架构原理

在这里插入图片描述

全面:

首先hive提供一系列的接口接受用户的sql语句,(clientjdbcCLI(命令行界面))通过自己的Driver,接受到
MetaStore(元数据),首先先解析是否有这个数据(SQLParser解析器),然后Physical(物理)Plan(编译器)生成逻辑计划,然后交给(QueryOptimizer优化器)优化,再交给(Execution)执行器翻译成mapreduce,交到yarn去执行,把执行的结果展示给客户端/HDFS

简洁:

Hive通过给用户提供的一系列交互接口,接收到用户的指令(SQL),使用自己的Driver,
结合元数据(MetaStore),将这些指令翻译成MapReduce,提交到Hadoop中执行,
最后,将执行返回的结果输出到用户交互接口

分区表和分桶表有什么区别?

分区针对的是数据的存储路径;分桶针对的是数据文件,相对分区更细粒度划分。

Hive虚拟列(很少问,也很少用)

Hive提供了三个虚拟列:

INPUTFILENAME
BLOCKOFFSETINSIDE__FILE
ROWOFFSETINSIDE__BLOCK

但ROWOFFSETINSIDE__BLOCK默认是不可用的,需要设置hive.exec.rowoffset为true才可以。
可以用来排查有问题的输入数据。

INPUTFILENAME, mapper任务的输出文件名。

BLOCKOFFSETINSIDE__FILE, 当前全局文件的偏移量。对于块压缩文件,就是当前块的文件偏移量,即当前块的第一个字节在文件中的偏移量。

hive自动使用索引

设置即可:一般不用,浪费资源

Hive调优

Fetch抓取

某些情况查询不必使用MapReduce计算

在hivedefault.xml.template文件中
hive.fetch.task.conversion默认是more,
老版本hive默认是minimal,该属性修改为more以后,在全局查找、字段查找、limit查找等都不走mapreduce。
hive(default)>sethive.fetch.task.conversion=none;

本地模式

针对小的输入数据量,可以通过本地模式在单台机器上处理所有的任务,执行明显缩短
设置hive.exec.mode.local.auto的值为true

//开启本地mr
sethive.exec.mode.local.auto=true;
//设置localmr的最大输入数据量,当输入数据量小于这个值时采用localmr的方式,默认为134217728,即128M
sethive.exec.mode.local.auto.inputbytes.max=50000000;
//设置localmr的最大输入文件个数,当输入文件个数小于这个值时采用localmr的方式,默认为4
sethive.exec.mode.local.auto.input.files.max=10;

严格模式

1.防止用户执行可能意向不到的影响,如orderby为了执行排序过程会将所有的结果数据分发到同一个Reducer中进行处理,使用limit,防止执行很长.
2,.限制笛卡尔积的查询

设置属性hive.mapred.mode值为默认是非严格模式nonstrict。开启严格模式需要修改hive.mapred.mode值为strict,开启严格模式可以禁止特定的查询

JOIN优化

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

尽量原子化操作

尽量避免一个SQL包含复杂逻辑,可以使用中间表来完成复杂的逻辑

行列过滤(分区剪裁、列剪裁)

分区剪裁: 只拿需要的分区,用什么拿什么。
列剪裁: 只拿需要的列,用什么拿什么。

分区剪裁:行处理,在分区剪裁中,使用外关联时,如果将副表的过滤条件写在Where后面,那么就会先全表关联,之后再过滤。
先关联再Where:

SELECT a.id FROM bigtable a  LEFT JOIN ori b ON a.id = b.id  WHERE b.id <= 10;

   
  
  
  • 1

正确的写法是写在ON后面:先Where再关联

SELECT a.id FROM ori a  LEFT JOIN bigtable b ON (b.id <= 10 AND a.id = b.id);

   
  
  
  • 1

或者直接写成子查询:

SELECT a.id FROM bigtable a RIGHT JOIN (SELECT id FROM ori WHERE id <= 10) b ON a.id = b.id;

   
  
  
  • 1

列剪裁:列处理,select中只拿需要的列,如果有尽量使用分区过滤,少用select*

采用分桶和分区技术

适当增加map数

使大数据量利用合适的map数;
使单个map任务处理合适的数据量;
是不是map数越多越好?
不是,如果有很多小文件,远小于128m,会每个小文件当一个块,浪费,而且同时执行的map是受限的
是不是保证每个map处理接近128m的文件块,就高枕无忧了?
不是,比如有个127,正常会一个map执行,但是这个文件只有一个或者俩小字段,有几千万记录,如果map处理逻辑复杂,用一个比较耗时

小文件进行合并

如何产生的?
1.动态分区
insert into partition(dt)select 2020-08-21 from

2.reduce 个数设置的过多,分区的key设计不合理

3.数据本身就是有问题 hdfs sink

小文件解决?

在Map执行前合并小文件,减少Map数:

1.CombineHiveInputFormat具有对小文件进行
合并的功能(系统默认的格式)。HiveInputFormat没有对小文件合并功能。

2.开启jvm重用:
set mapreduce.job.jvm.numtasks=10

3.merge 如果是maponly(只要一个map)任务,默认打开;
执行完任务,产生小文件,再开启一个作业,这个作业负责将小于16m的文件进行合并,默认合并到256m
如果是mr任务,merge(合并)功能需要打开;

4.在map阶段开启combiner

5.替换引擎
mr引擎:基于磁盘 慢 跨天 数据量大
tez引擎:基于内存 快 数据量小,临时测试,验证
spark引擎:基于磁盘+内存 较快 当天的定时任务;

合理设置map个数

max(1,min(块大小,Long的最大值))
128m数据=>一个maptask

控制hive任务的reduce数

设定参数
也不是越多越好,合理设置,有多少个reduce就有多少输出文件,也会照成小文件问题。
处理大文件利用合理reduce数,使单个reduce任务处理数据量大小要合适。

根据数据量大小适当增加reduce个数;

常用参数

//输出合并小文件
SEThive.merge.mapfiles=true;默认true,在maponly任务结束时合并
小文件
SEThive.merge.mapredfiles=true;默认false,在mapreduce任务结
束时合并小文件
SEThive.merge.size.per.task=268435456;默认256M
SEThive.merge.smallfiles.avgsize=16777216;当输出文件的平均大小
小于16m该值时,启动一个独立的mapreduce任务进行文件merg

列式储存(加快查询速度)

id name age
1 zs 18
2 list 20
列:1 2 zs list 18 20
行:1 zs 18 2 list 20

压缩(选择快的,减少磁盘io)

设置map端输出、中间结果压缩。(不完全是解决数据倾斜的问题,但是减少了IO读写和网络传输,能提高很多效率)

Hive解决数据倾斜方法

很多reduce任务都跑完了,就剩下其中一两个任务,一直卡着结束不了。

什么时候会产生数据倾斜?

1.不同数据类型关联产生数据倾斜
用户表id 为int,log表id为string,然后两表join的时候连接不上。
解决:on a.id=b(b.id as string)转换一样。

2.控制空值分布
空值较多会进入一个reduce
解决:加随机数

1)groupby

注:groupby优于distinctgroup
情形:groupby维度过小,某值的数量过多
后果:处理某值的reduce非常耗时
解决方式:采用sum()groupby的方式来替换count(distinct)完成计算。

2)count(distinct)

count(distinctxx)
情形:某特殊值过多
后果:处理此特殊值的reduce耗时;只有一个reduce任务
解决方式:countdistinct时,将值为空的情况单独处理,比如可以直接过滤空值的行,
在最后结果中加1。如果还有其他计算,需要进行groupby,可以先将值为空的记录单独处
理,再和其他计算结果进行union。

3)mapjoin

提前在map端聚合,如,hadoop 1,hadoop 1-》hadoop 2

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

情形:比如用户表中user_id字段为int,log表中user_id字段既有string类型也有int类
型。当按照user_id进行两个表的Join操作时。
后果:处理此特殊值的reduce耗时;只有一个reduce任务
默认的Hash操作会按int型的id来进行分配,这样会导致所有string类型id的记录都分配
到一个Reducer中。
解决方式:把数字类型转换成字符串类型
select*fromusersa
leftouterjoinlogsb
ona.usr_id=cast(b.user_idasstring)

5)开启数据倾斜时负载均衡

sethive.groupby.skewindata=true;

6)控制空值分布

将为空的key转变为字符串加随机数或纯随机数,将因空值而造成倾斜的数据分不到多个Reducer。
注:对于异常值如果不需要的话,最好是提前在where条件里过滤掉,这样可以使计算
量大大减少
实践中,可以使用casewhen对空值赋上随机值。此方法比直接写isnotnull更好,因
为前者job数为1,后者为2.

如果上述的方法还不能解决,比如当有多个JOIN的时候,建议建立临时表,然后拆分HIVESQL语句。

Hive的分层设计

建模工具EZDML,一个一个连线即可

原始数据层(ODS)

数据结构与源系统完全一致,不做修改
压缩lzo,减少磁盘空间
创建分区,减少后续的全表扫描

数据明细层(DWD)

对源系统数据进行了些清洗后的数据
1、etl清洗 清洗哪些数据?
根据业务,将字符代表的含义转换对应的业务,
核心字段不能为空,为空就清洗掉;
超时的数据过滤掉;
重复的数据过滤掉;

2.清洗工具?
hive sql ,spark sql,Python,mr,kettle

3.清洗多少脏数据?
1万条去除一条=》合理
不合理,找javaee 前端

4,维度退化
商品三级分类、二级、一级、商品表=》商品表
省、市、县=》地区
时间(年月日)=》时间表

5,为什么要退化》
防止后续的频繁join,减少重复join操作;

6.压缩
7.列式储存 parquet
8.创建分区表
9.脱敏(个人信息,身份证,手机号)
如有想用脱敏手机号,可以建一个非脱敏层(ranger/sentry加密加权限)

数据服务层(DWS)

数据的小粒度聚合,预汇总和预加工
依赖对应用的共性提炼,而不是某个具体应用
每日,每周,每月的各种指标

数据应用层(ADS)

面向应用,按需定制,前端直接读取的数据

日,周,月,等

建模

事实表:储存各维度表的主键
维度表:包含事实记录的特性

星型模型:一个事实表多个维度表联系(常用)
雪花模型:一个事实表多个维度表,维度之间还有关系
星座模型:和星型模型区别是事实表的数量。星座多个事实表

建模方法:(业务过程>粒度>维度>事实)
建模方法比较:维度模型简单,适合业务模式快速变化的行业,关系型模型实现复杂,适合业务模式比较成熟的行业。
阿里原来是关系建模。现在都是维度模型。

derby:hive元数据储存地方不支持多客户端访问

放mysql

Hbase

面向列的,非结构化数据存储的数据库,构建在Hdfs基础之上的非关系型(NoSql,NotOnlySql)数据库,列式存储其实说的是列族存储。实时随机读写海量数据。(数百万列,数十亿行的实时随机读写)

Hbase的储存原理

在这里插入图片描述

集群中有一个老大负责管理HMaster,小弟HRegionServer实际工作的,还有Zookeeper,
ZK有三个作用,Hmater高可用,让Hmaster感知HRegionServer上线的,维护元数据的入口。
客户端写数据,HRegionServer首先先把数据写到hlog里(磁盘或hdfs同步的)然后生成HRegion,
HRegion会有多个Store(储存),store里会有memstore(内存中)内存满会溢出,
产生多个storefile,会进一步演变Hfile最后将多个合并一个大的并压缩,上传到hdfs上

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(缓存),再返回给客户端。

HBase原理之写流程

在这里插入图片描述

1)Client向HRegionServer发送写请求;
2)HRegionServer将数据写到HLog(writeaheadlog)。为了数据的持久化和恢复;
3)HRegionServer将数据写到内存(MemStore);
4)反馈Client写成功。

HBase原理之数据Flush流程

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

数据合并

1)当数据块达到4块(一个store中的Hfile),HMaster将数据块加载到本地,进行合并;
2)当合并的数据(store数据)超过256M,HregionServer将region进行拆分,HMaster将拆分后的region分配给不同的HRegionServer管理(一个store列族数据超过256m会对整个region进行切分,此处可以预分区);
3)当HRegionServer宕机后,HMaster将该HRegionServer对应的HLog拆分,然后分配给不同的HRegionServer加载,修改.META.;
4)注意:HLog会同步到HDFS。(memstore在一个server上也会有很多,所以HLog丢失会不安全)

如何解决Hbase中region太小和region太大带来的结果??

Region过大会发生多次compaction,将数据读一遍并写一遍到hdfs上,占用io。
region过小会造成多次split,region会下线,影响访问服务,
调整hbase.heregion.max.filesize为256m

RowKey设计原则(多问)

长度,唯一,散列

RowKey如何设计

1)生成随机数、hash、散列值
2)字符串反转

Phoenix二级索引

对于HBase而言,如果想精确地定位到某行记录,唯一的办法是通过rowkey来查询。如果不通过rowkey来查找数据,就必须逐行地比较每一列的值,即全表扫瞄。对于较大的表,全表扫瞄的代价是不可接受的。

GlobalIndexing(全局索引)

多读少写的业务场景
在读数据的时候Phoenix会选择索引表来降低查询消耗的时间
在默认情况下如果想查询的字段不是索引字段的话索引表不会被使用,也就是说不会带来查询速度的提升

LocalIndexing(本地索引)

写操作频繁的场景以及空间受限制的场景
使用Localindexing时,索引数据和数据表的数据存放在相同的服务器中,避免了在写操作的时候往不同服务器的索引表中写索引带来的额外开销
使用Localindexing的时候即使查询的字段不是索引字段索引表也会被使用,这会带来查询速度的提升,这点跟Globalindexing不同

列族的设计原则?

尽可能少(按照列族进行存储,按照region进行读取,不必要的io操作),经常和不经常使用的两类数据放入不同列族中,列族名字尽可能短。

hbase的LSM树?

LSM树(Log-Structured Merge Tree)存储引擎和B树存储引擎一样,同样支持增、删、读、改、顺序扫描操作。而且通过批量存储技术规避磁盘随机写入问题。当然凡事有利有弊,LSM树和B+树相比,LSM树牺牲了部分读性能,用来大幅提高写性能

Redis

基于内存单线程key-value高性能数据库,在20年5月2日更新支持多线程,默认不开启,原理还是单线程,针对更大需求设定,还有个keydb多线程的,fork出来的分支。

优势

性能极高–Redis能读的速度是110000次/s,写的速度是81000次/s。
丰富的数据类型–Redis支持二进制案例的Strings,Lists,Hashes,Sets及OrderedSets数据类型操作。
原子–Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
丰富的特性–Redis还支持publish/subscribe,通知,key过期等等特性。

类型(常问)

字符串(string):用于缓存数据,可以存储对象序列化
列表(list):链表结构,用于模拟栈和队列,微博关注列表,粉丝列表,消息列表等
集合(set):去重,抽奖。
有序集合(sortedset)(zset):排序用,直播系统中,实时的排行信息,包含直播间在线用户列表,各种礼物排行榜
哈希(散列)(hash):做缓存,放java对象,会占用更少的内存,存储用户信息,商品信息。
(hash是一个string类型的field和value的映射表。它的添加、删除操作都是0(1)(平均操作)。)

redis中数据类型指的是value的数据类型,而key只有String,string类型的值最大能存储512MB

缓存穿透:

大量缓存中不存在的请求key访问直接落到数据库,一般是恶意攻击;
(将空对象也缓存起来,并设置很短的过期时间,最长不超过5分钟。
使用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap(位图)中,一个一定不存在的会被拦截掉,从而避免对底层储存系统的查询压力)

缓存雪崩:

缓存集中一段时间失效,发生大量缓存穿透,所有查询落在数据库上
(尽量让失效的时间点不分布再同一时间点)

缓存击穿:

热点key在请求高峰失效,瞬间大量请求落到数据库;
(可以设置key永不过期)

哨兵模式

主机down掉,哨兵会从从机选择一台作为主机,并设置为其他从机的主机,原来主机再次启动也就变从机

持久化

RDB 方式(默认)
AOF 方式

RDB持久化(间隔性):

在内存中的的状态保存到硬盘中,它可以手动执行,也可以再redis.conf中配置,定期执行。

RDB持久化产生的RDB文件是一个经过压缩的二进制文件,这个文件被保存在硬盘中,redis可以通过这个文件还原数据库当时的状态。

①在指定的时间间隔内持久化
②服务shutdown(关机)会自动持久化
③输入bgsave也会持久化

AOF:以日志形式记录每个更新操作

重新启动时读取这个文件,重新执行新建、修改数据的命令恢复数据。
默认每秒持久化一次,比RDB占用更多磁盘空间
备份恢复慢,性能压力,存在个别bug。

对数据不敏感,可以选单独用RDB;
不建议单独用AOF,因为可能出现Bug;
如果只是做纯内存缓存,可以都不用

对比

在RDB和AOF备份文件都有的情况下,redis会优先载入AOF备份文件

RDB持久化,安全性较差,它是正常时期数据备份及 master-slave数据同步的最佳手段,文件尺寸较小,恢复数度较快。

AOF更安全,可将数据及时同步到文件中,但需要较多的磁盘IO,AOF文件尺寸较大,文件内容恢复相对较慢, 也更完整。

悲观锁

执行操作前假设当前的操作肯定(或有很大几率)会被打断(悲观)。
基于这个假设,我们在做操作前就会把相关资源锁定,不允许自己执行期间有其他操作干扰。

乐观锁

执行操作前假设当前操作不会被打断(乐观)。
基于这个假设,我们在做操作前不会锁定资源,万一发生了其他操作的干扰,那么本次操作将被放弃。
Redis使用的就是乐观锁。

redis是单线程的,为什么那么快?

完全基于内存,
数据结构简单,操作简单,
单线程,不考虑多进程线程的切换消耗cpu,加锁等性能消耗,
使用多路I/O复用模型,非阻塞io
底层模型,通信协议不同,直接构造vm机制。

Kafka

在这里插入图片描述

分布式消息队列,本质是缓冲数据,因为提供消息(数据)管理功能才叫消息队列,记录上次读数据的偏移量、消息读取之后是否删除、消息的备份和安全等机制
mq,message,queue(都叫消息队列)

注意!

zookeeper储存的没有生产者的有关信息,储存broker数量消费者,topic。消费组对应的相关信息。

模式

点对点模式(一对一,消费者主动拉取数据,消息收到后消息清除)

发布/订阅模式(一对多,数据生产后,推送给所有订阅者)

架构

Producer:消息生产者,就是向kafkabroker发消息的客户端;
Consumer:消息消费者,从kafkabroker取消息的客户端;
Topic:可以理解为一个队列(就是同一个业务的数据放在一个topic下);
ConsumerGroup(CG):topic消息的广播(发给所有的consumer)和单播(发给任意一个consumer)的手段。
一个topic可以有多个CG,但每个partion只会把消息发给该CG中的一个consumer。如果需要实现广播,只要每个consumer有一个独立的CG就可以了。要实现单播只要所有的consumer在同一个CG
Broker:一台kafka服务器就是一个broker。一个集群由多个broker组成。一个broker可以容纳多个topic;
Partition:为了实现扩展性,一个非常大的topic可以分布到多个broker(即服务器)上,一个topic可以分为多个partition,每个partition是一个有序的队列
Offset:偏移量。
0.9版本之前存储在zk
0.9版本后存储在本地

写入方式

采用推(push)模式将消息发布到broker,每条消息都被追加(append)到分区(patition)中,属于顺序写磁盘(顺序写磁盘效率比随机写速度快,保障Kafka吞吐率)。

kafka工作原理?

producer(生产者)向broker发送事件,consumer(消费者)从broker消费事件。
事件由topic区分开,每个consumer(消费者)都会属于一个group。
相同group中的consumer(消费者)不能重复消费事件,而同一事件将会发送给每个不同group的consumer(消费者)。

Kafka的机器数量?

Kafka机器数量=2*(峰值生产速度*副本数/100)+1

Kafka的日志保存时间

默认7天;生产环境一般3天

Kafka丢不丢数据

producerkafka生产者发送数据给kafka可能会丢数据?
通过ACK机制确保数据不丢失。

kafka接收到数据之后,消息存储在kafka中kafka可能会丢数据?
kafka通过副本机制保证数据不丢失(leaderfollower)

消费者消费数据的时候可能会丢数据
kafkaconsumer

Ack=0,相当于异步发送,消息发送完毕即offset增加,继续生产。(最快,可靠最差,生产不用)

Ack=1,leader收到leaderreplica对一个消息的接受ack才增加offset,然后继续生产。(较快,可靠可以,大多选择)

Ack=-1,leader收到所有replica对一个消息的接受ack才增加offset,然后继续生产。(慢,可靠,安全选择)

Kafka的ISR副本同步队列

ISR(InSyncReplicas),副本同步队列。
ISR中包括Leader和Follower。
如果Leader进程挂掉,会在ISR队列中选择一个服务作为新的Leader。有replica.lag.max.messages(延迟条数)和replica.lag.time.max.ms(延迟时间)两个参数决定一台服务是否可以加入ISR副本队列,在0.10版本移除了replica.lag.max.messages参数,防止服务频繁的进去队列。
任意一个维度超过阈值都会把Follower剔除出ISR,存入OSR(OutofSyncReplicas)列表,新加入的Follower也会先存放在OSR中。

isr leader挂了谁当老大??
在isr队列里面都有机会。
怎么进入:
旧版本:延迟时间,延迟条数
新版本:只有延迟时间

Kafka分区分配策略

在Kafka内部存在两种默认的分区分配策略:Range和RoundRobin。
Range是默认策略。Range是对每个Topic而言的(即一个Topic一个Topic分),首先对同一个Topic里面的分区按照序号进行排序,并对消费者按照字母顺序进行排序。然后用Partitions分区的个数除以消费者线程的总数来决定每个消费者线程消费几个分区。如果除不尽,那么前面几个消费者线程将会多消费一个分区。

RoundRobin:所有分区采用hash随机打散,轮询方式;

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

1)如果是Kafka消费能力不足,则可以考虑增加Topic的分区数,并且同时提升消费组的消费者数量,消费者数=分区数。(两者缺一不可)

2)如果是下游的数据处理不及时:提高每批次拉取的数量。批次拉取数据过少(拉取数据/处理时间<生产速度),使处理的数据小于生产的数据,也会造成数据积压。

加分区、加消费者条数

Kafka数据重复

幂等性+ack1+事务

Kafka数据重复,可以再下一级:SparkStreaming、redis或者hive中dwd(细节层)层去重,去重的手段:分组、按照id开窗只取第一个值;

幂等性:单分区,在一个会话内 ,效率高
事务:整个Kafka内部,全局维护id,效率低

Kafka支持传输?

对于消费体大小默认单条最大值是1m,但是常常遇到一条大于1m,如果不对Kafka进行配置,会照成生产者推送消息,消费也无法消费数据。
设置参数

Kafka过期数据清理

直接删除,启动删除策略(推荐,前面日志服务器有)
log.cleanup.policy=delete

压缩策略
log.cleanup.policy=compact

kafka保证数据有序?

分区内有序,分区间无序,业务逻辑可以无序,就不处理。
业务逻辑必须有序,如果数据小,搞一个单分区的主题,大的话,生产者记录位置信息,消费者根据位置信息指定分区进行读取数据

单分区有序,多分区间无序

怎么保证kafaka业务的不丢失?

重新分区,增加消费者

优化政策

针对Partitions的最佳实践

了解分区的数据速率,“平均消息大小”乘以“每秒消息数”得出 能标识单个consumer不延时所需要的支持的最低性能值。
除非有其他架构上的需要,否则在写topic时请使用随机分区

针对Consumers的最佳实践

consumer比0.10底的要升级版本,0.8.x使用zookeeper协调consumergroup会出现bug,长期处于再均衡状态,或者导致再均衡算法失败(再均衡风暴),因此再均衡期间一个多个分区会被分配同一组的每个consumer,再均衡风暴中会在各个cs之间流转。
调优consumer的套接字缓存区(socketbuffers),应对数据高速流入。

针对Producers的最佳实践

配置producer,以等待各种确认。

针对Brokers的最佳实践

在各个brokers上,请压缩topics所需的内存和CPU资源 通过网络吞吐量来监控brokers。

Mysql

DB:数据库,储存数据的容器
DBMS:数据库管理系统,用于创建管理DB
SQL:结构化查询语言

四层逻辑
连接层-服务层-引擎层-储存层

事务的并发问题

更新丢失:两同时修改同一文件,每个独立修改其副本,然后保存,最后一个保存的覆盖前一个做的更改。
解决:在第一个完成提交前,另一个不能访问同一文件。

脏读:事务A读取了事务B已修改但尚未提交的,那么A读取到的数据是脏数据

不可重复读:事务A多次读取同一数据,事务B在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果不一致
事务A读取到了事务B已经提交的修改数据,不符合隔离性。

幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。
事务A读取了事务B的新增

注:不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表

MySQL 事务隔离级别

默认可重复读的隔离级别

在这里插入图片描述

SQL索引优化(数据结构:B+Tree)

1、在表中建立索引,优先考虑where、groupby使用到的字段。

2、尽量避免使用select**,返回无用的字段会降低查询效率。如下: SELECTFROMt
优化方式:使用具体的字段代替
,只返回使用到的字段。

3、使用表或列的别名 如果表或列的名称太长了,使用一些简短的别名也能稍微提高一些SQL的性能。毕竟要扫描的字符长度就变少了

4、SQL写大写 我们在编写SQL的时候,官方推荐的是使用大写来写关键字,因为Oracle服务器总是先将小写字母转成大写后,才执行

5、用>=替代> 低效: SELECTFROMEMPWHEREDEPTNO>3
首先定位到DEPTNO=3的记录并且扫描到第一个DEPT大于3的记录 高效: SELECT
FROMEMPWHEREDEPTNO>=4
直接跳到第一个DEPT等于4的记录

6、尽量避免使用in和notin,会导致数据库引擎放弃索引进行全表扫描。如下:(B>Ain,B<aexists)
SELECTFROMtWHEREidIN(2,3)
SELECT
FROMt1WHEREusernameIN(SELECTusernameFROMt2)
优化方式:如果是连续数值,可以用between代替。如下: SELECTFROMtWHEREidBETWEEN2AND3
如果是子查询,可以用exists代替。如下:
SELECT
FROMt1WHEREEXISTS(SELECT*FROMt2WHEREt1.username=t2.username)

7、尽量避免使用or,会导致数据库引擎放弃索引进行全表扫描。如下: SELECTFROMtWHEREid=1ORid=3
优化方式:可以用union代替or。如下: SELECT
FROMtWHEREid=1 UNION
SELECT*FROMtWHEREid=3
(PS:如果or两边的字段是同一个,如例子中这样。貌似两种方式效率差不多,即使union扫描的是索引,or扫描的是全表)

8、尽量避免在字段开头模糊查询,会导致数据库引擎放弃索引进行全表扫描。如下:
SELECTFROMtWHEREusernameLIKE’%li%’ 优化方式:尽量在字段后面使用模糊查询。如下:
SELECT
FROMtWHEREusernameLIKE’li%’

9、尽量避免进行null值的判断,会导致数据库引擎放弃索引进行全表扫描。如下: SELECTFROMtWHEREscoreISNULL
优化方式:可以给字段添加默认值0,对0值进行判断。如下: SELECT
FROMtWHEREscore=0

10、尽量避免在where条件中等号的左侧进行表达式、函数操作,会导致数据库引擎放弃索引进行全表扫描。如下:
SELECTFROMt2WHEREscore/10=9
SELECT
FROMt2WHERESUBSTR(username,1,2)=‘li’
优化方式:可以将表达式、函数操作移动到等号右侧。如下: SELECTFROMt2WHEREscore=109
SELECT*FROMt2WHEREusernameLIKE’li%’

11、当数据量大时,避免使用where1=1的条件。通常为了方便拼装查询条件,我们会默认使用该条件,数据库引擎会放弃索引进行全表扫描。如下:
SELECT*FROMtWHERE1=1 优化方式:用代码拼装sql时进行判断,没where加where,有where加and。

12、服务器硬件优化 花钱

分析计算类

结构化数据:

类似数据库,行数据,由二维表结构

半结构化数据:

通过键可以获取相应值,且数据格式不相同,如json,文本型或者字典型或者列表

非结构化数据:

音乐,图片,视频等

Spark(2010发布)

基于内存计算的大数据并行计算框架,惰性计算模式,scala语言编写,也可以java,java麻烦

在这里插入图片描述

driver(驱动器)+executor(执行器)

webui界面

spark的UI界面:http://00.0.000.00:18080/

Spark与Hadoop区别??

核心区别:内存和磁盘的区别;job中途失败重新计算的区别。
某一部分丢失或者出错,可以通过整个数据集的计算流程的血缘关系来实现重建;
mapreduce的话容错可能只能重新计算了,成本较高。

MRShuffle和SparkShuffle差别总结如下:

1、Hadoop的有一个Map完成,Reduce便可以去fetch(取)数据了,不必等到所有Map任务完成,而Spark的必须等到父stage(阶段)完成,也就是父stage的map操作全部完成才能去fetch(取)数据。
2、Hadoop的Shuffle是sortbase的,那么不管是Map的输出,还是Reduce的输出,都是partion内有序的,而spark不要求这一点。
3、Hadoop的Reduce要等到fetch(取)完全部数据,才将数据传入reduce函数进行聚合,而spark是一边fetch(取)一边聚合。

shuffle是【划分DAG中stage的标识】,同时影响Spark执行速度的关键步骤

有明显阶段吗?没有明显阶段。
遇到【宽依赖的时候,会有数据的shuffle,遇到宽依赖的时候才划分stage。】
从【上一个stage到下一个stage就是一个shuffle的过程】。
shuffle指的就是数据的重新分配的一个过程,也就是说如果RDD的分区数据有交叉变化(遇到宽依赖,父RDD的分区和子RDD的分区是多对多),那么这个变化过程中就存在着shuffle过程。只要是宽依赖,就一定存在shuffle过程,两个stage之间一定存在shuffle过程。
Spark中的shuffle操作由【shufflemanager负责,默认使用sort机制】

spark几种部署模式

Local:本地模式,用于本地开发测试
Standlone:集群模式,Spark自带的资源调度框架,存在master单点故障,可由zookeeper实现HA,学习用
Yarn:集群模式,运行yarn之上,由yarn负责资源管理,spark负责任务调度和计算,生产用
有yarnclient和yarncluster

(两种模式,主要区别在于:Driver程序的运行节点。
Yarncluster适用于生产环境,而YarnCluster更适用于交互,调试模式)

Spark中job,stage,task等等

job:提交给spark的任务
stage:job处理过程中需要分为的几个阶段
task:task是每个job处理分几次任务的最小单位,运行在executor中
job>一个或多个stage>一个或多个task

简述Spark的架构与作业提交流程

1.首先spark在yarn下的作业提交分两种,一种是yarncluster模式,一种是yarnclient模式。yarnclient模式主要是用于测试,
yarncluster模式主要是用于生产。
在这里插入图片描述

在这里插入图片描述

2.当我们用sparksubmit提交任务的时候,会请求ResourceManager分配一个executor,用于启动ApplicationMaster,接着启动driver(yarnclient模式driver在提交作业的终端启动,yarncluster模式driver在AM处启动)。
接着AM找RM要资源,RM给分配相应数量的executor。
开始执行任务,拆分stage,提交stage的task,进行task的调度,分配到各个executor上面去执行。
执行完成后,driver会通知RM回收资源。

transformation算子,并简述功能

1)map(func):返回一个新的RDD,该RDD由每一个输入元素经过func函数转换后组成.
2)filter(func):返回一个新的RDD,该RDD由经过func函数计算后返回值为true的输入元素组成,(过滤)
3)flatMap(func):类似于map,但是每一个输入元素可以被映射为0或多个输出元素(所以func应该返回一个序列,而不是单一元素)
4)mapPartitions(func):类似于map,但独立地在RDD的每一个分片上运行,因此在类型为T的RDD上运行时,func的函数类型必须是Iterator[T]=>Iterator[U]。假设有N个元素,有M个分区,那么map的函数的将被调用N次,而mapPartitions被调用M次,一个函数一次处理所有分区。(一个函数一次处理所有分区)
5)mapPartitionsWithIndex(func):类似于mapPartitions,但func带有一个整数参数表示分片的索引值,因此在类型为T的RDD上运行时,func的函数类型必须是(Int,Interator[T])=>Iterator[U](描述分区信息)
6)union(otherDataset):对源RDD和参数RDD求并集后返回一个新的RDD
7)reduceByKey(func,[numTasks]):在一个(K,V)的RDD上调用,返回一个(K,V)的RDD,使用指定的reduce函数,将相同key的值聚合到一起,reduce任务的个数可以通过第二个可选的参数来设置。(相同key聚合)
8)groupByKey([numTasks]):在一个(K,V)的RDD上调用,返回一个(K,Iterator[V])的RDD,将相同key的value放到Iterator中。
groupByKey也是对每个key进行操作分组,但只生成一个sequence(序列)。
9)sortByKey([ascending],[numTasks]):在一个(K,V)的RDD上调用,K必须实现Ordered接口,返回一个按照key进行排序的(K,V)的RDD
(按照key排序)

action算子,并简述功能

1)reduce:通过func函数聚集RDD中的所有元素,这个功能必须是可交换且可并联的(计算)

2)collect:在驱动程序中,以数组的形式返回数据集的所有元素(收集)

3)first:返回RDD的第一个元素(类似于take(1))(选择)

4)take:返回一个由数据集的前n个元素组成的数组(选择)

5)count():返回RDD的元素个数(计数)

6)countByKey:针对(K,V)类型的RDD,返回一个(K,Int)的map,表示每一个key对应的元素个数。(对key计数)

7)foreach:在数据集的每一个元素上,运行函数func进行更新(遍历)

8)saveAsTextFile:将数据集的元素以textfile的形式保存到HDFS文件系统或者其他支持的文件系统,对于每个元素,Spark将会调用toString方法,将它装换为文件中的文本
(保存)

9)aggregate:给一个初始值,每个分区和初值聚合

会引起Shuffle过程的Spark算子,并简述功能。

reduceBykey:在一个(K,V)的RDD上调用,返回一个(K,V)的RDD,使用指定的reduce函数,将相同key的值聚合到一起,reduce任务的个数可以通过第二个可选的参数来设置。(相同key聚合,有map端聚合,高于groupbykey)

reduceByKey有map端的聚合操作,使得网络传输的数据量减小,效率要高于groupByKey
groupByKey不会进行map端的聚合,而是讲map端的数据shuffle到reduce端,在reduce端进行数据的聚合操作

groupByKey:groupByKey也是对每个key进行操作分组,但只生成一个sequence(序列),reduce端聚合
sortByKey([ascending],[numTasks]):在一个(K,V)的RDD上调用,K必须实现Ordered接口,返回一个按照key进行排序的(K,V)的RDD
(按key进行排序)
countByKey():计算个key的元素个数
…ByKey:

核心Shuffle(HashShuffle与SortShuffle)的工作流程(包括未优化的HashShuffle、优化的HashShuffle、普通的SortShuffle与bypass(分流)的SortShuffle)

spark1.6版本之前,一直使用HashShuffle,在spark1.6版本之后使用SortBaseShuffle,因为HashShuffle存在的不足所以就替换了HashShuffle.

未优化的hashshuffle:根据task划分文件,小文件太多。
优化后:根据core划分,但是core多也会有很多小文件。
SortBaseShuffle:加入排序,内存不够溢写磁盘,合成索引文件和数据文件。
bypass:有时是不需要排序的,这里参数小于200使用它,功能除了没排序都一样。

Spark reduceByKey与groupByKey的区别,哪一种更具优势?

reduceByKey:按照key进行聚合,在shuffle之前有combine(预聚合)操作,返回结果是RDD[k,v]。

groupByKey:按照key进行分组,直接进行shuffle。
建议使用reducebykey,但是注意是否会影响业务逻辑

Repartition(重新分区)和Coalesce(合并)关系与区别

1)关系:都是改变RDD的partition数量,reparation底层调用coalesce方法:
coalesce(numPartitions,shuffle=true)

2)区别:repartition一定shuffle,coalesce根据传入参数来判断是否发生shuffle
一般增大rdd的partition使用reparation,减少partition使用coalesce

12种缓存级别

在这里插入图片描述

none:不缓存
disk_only 缓存磁盘一份
disk_only_2缓存磁盘二份
memory_only缓存内存一份
memory_only_2缓存内存二分
memory_only_ser缓存内存,存放序列化后的数据
memory_only_ser_2缓存内存,存放序列化后的数据2
memory_and_disk缓存内存,放不下放磁盘
memory_and_disk_2缓存内存,放不下放磁盘2
memory_and_disk_ser缓存内存,放不下放磁盘,内存存放序列化后的数据
memory_and_disk_ser_2缓存内存,放不下放磁盘,内存存放序列化后的数据2份

简述Spark中共享变量(广播变量和累加器)的基本原理与用途。

累加器(accumulator):对事件计数
广播变量(broadcast):分发较大的对象。

SparkShuffle默认并行度

参数spark.sql.shuffle.partitions决定默认并行度200

SparkStreaming精准一次消费

1.手动维护偏移量

2.处理完业务数据后,再进行提交偏移量操作
极端情况下,如在提交偏移量时断网或停电会造成spark程序第二次启动时重复消费问题,所以在涉及到金额或精确性非常高的场景会使用事务保证精准一次消费

解决数据倾斜

原因:key分布不均匀,建表不周,业务数据激增

数据预处理、异常值的过滤、调参并行度、定位数据倾斜代码,一般在shuffle过程中、两阶段聚合(局部聚合+全局聚合)、reducejoin转为mapjoin(广播分发)、多种组合使用。

在这里插入图片描述

spark的优化怎么做?

常规调优:

避免重复加载RDD,重复的RDD需要缓存

(1)计算量大,形成的lineage(血脉关系)过大应该给已经缓存了的rdd添加checkpoint(检查点),以减少容错带来的开销。
(2)小分区合并,过小的分区造成过多的切换任务开销,使用repartition(分区)。

警惕shuffle操作性能问题:
reduceByKe优于groupByKey

广播变量:一个Executor中的所有task共享一个副本。

序列化:
在DataFrames和DataSet当中自动实现了kryo序列化。kryo序列化比java序列化更快更紧凑

使用DataSet对数据操作更简单,类型检查更安全。

通过sparkenv文件、程序中sparkconf和setproperty设置。
参数调优等:
并行度200默认,调优800

算子调优
mapPartitions:

一个task处理一个RDD的partition,那么一个task只会执行一次function,function一次接收所有的partition数据,效率比较高;但是如果使用mapPartitions算子,但数据量非常大时,function一次处理一个分区的数据,如果一旦内存不足,此时无法回收内存,就可能会OOM,即内存溢出。

foreachPartition优化数据库操作

在生产环境中,通常使用foreachPartition算子来完成数据库的写入,通过foreachPartition算子的特性,可以优化写数据库的性能

filter与coalesce的配合使用

我们可以在filter操作之后,使用coalesce算子针对每个partition的数据量各不相同的情况,压缩partition的数量,而且让每个partition的数据量尽量均匀紧凑,以便于后面的task进行计算操作,在某种程度上能够在一定程度上提升性能

repartition解决SparkSQL低并行度问题

对于Spark SQL查询出来的RDD,立即使用repartition算子,去重新进行分区,这样可以重新分区为多个partition,从repartition之后的RDD操作,由于不再设计Spark SQL,因此stage的并行度就会等于你手动设置的值

reduceByKey预聚合

map端会先对本地的数据进行combine操作,然后将数据写入给下个stage的每个task创建的文件中

shuffle调优
调节map端缓冲区大小

通过调节map端缓冲的大小,可以避免频繁的磁盘IO操作,进而提升Spark任务的整体性能

val conf = new SparkConf()
  .set("spark.shuffle.file.buffer", "64")

   
  
  
  • 1
  • 2
调节reduce端拉取数据缓冲区大小

如果内存资源较为充足,适当增加拉取数据缓冲区的大小,可以减少拉取数据的次数,也就可以减少网络传输的次数,进而提升性能

val conf = new SparkConf()
  .set("spark.reducer.maxSizeInFlight", "96")

   
  
  
  • 1
  • 2
调节reduce端拉取数据重试次数

对于那些包含了特别耗时的shuffle操作的作业,建议增加重试最大次数(比如60次),以避免由于JVM的full gc或者网络不稳定等因素导致的数据拉取失败

val conf = new SparkConf()
  .set("spark.shuffle.io.maxRetries", "6")

   
  
  
  • 1
  • 2
调节reduce端拉取数据等待间隔

Spark Shuffle过程中,reduce task拉取属于自己的数据时,如果因为网络异常等原因导致失败会自动进行重试,在一次失败后,会等待一定的时间间隔再进行重试,可以通过加大间隔时长(比如60s),以增加shuffle操作的稳定性

val conf = new SparkConf()
  .set("spark.shuffle.io.retryWait", "60s")

   
  
  
  • 1
  • 2
调节SortShuffle排序操作阈值

如果shuffle reduce task的数量小于某一阈值则shuffle write过程中不会进行排序操作,而是直接按照未经优化的HashShuffleManager的方式去写数据,但是最后会将每个task产生的所有临时磁盘文件都合并成一个文件,并会创建单独的索引文件

val conf = new SparkConf()
  .set("spark.shuffle.sort.bypassMergeThreshold", "400")

   
  
  
  • 1
  • 2
JVM调优

对于JVM调优,首先应该明确,full gc/minor gc,都会导致JVM的工作线程停止工作,即stop the world

降低cache操作的内存占比

如果发现gc太频繁,时间太长,就可以考虑调节Storage的内存占比,让task执行算子函数式,有更多的内存可以使用

val conf = new SparkConf()
  .set("spark.storage.memoryFraction", "0.4")

   
  
  
  • 1
  • 2
调节Executor堆外内存

Executor的堆外内存主要用于程序的共享库、Perm Space、 线程Stack和一些Memory mapping等, 或者类C方式allocate object。

--conf spark.yarn.executor.memoryOverhead=2048

   
  
  
  • 1
调节连接等待时长

垃圾回收会导致工作现场全部停止,也就是说,垃圾回收一旦执行,Spark的Executor进程就会停止工作,无法提供相应,此时,由于没有响应,无法建立网络连接,会导致网络连接超时

--conf spark.core.connection.ack.wait.timeout=300

   
  
  
  • 1

RDD分区

分为hash分区和range分区和自定义分区
默认hash分区

range保证数据量的均匀

自定义分区:
继承 org.apache.spark.Partitioner 类实现三个方法
numpartition:int 返回创建出来的分区数
getpartition(key:any):int 返回给定键的分区编号(0到numpartition-1)
equals():java判断相等性的标准方法。

Fink(15年发行)

Flink 在运行时主要包含:Jobmanager、Taskmanager 和 Slot

流式计算性能更高、可靠性更高

集群架构

在这里插入图片描述

client客户端提交任务给JobManager hadoop fs -mkdir -p /test/input
JobManager负责Flink集群计算资源管理,并分发任务给TaskManager执行
TaskManager定期向JobManager汇报状态

有界流和无界流

Flink将批处理(即处理有限的静态数据)视作一种特殊的流处理

Flink+Kafka如何实现exactly-once语义

内部–利用checkpoint机制,把状态存盘,保证内部的状态一致性。
source–Kafka consumer作为source,将偏移量保存下来,出现故障恢复可以有连接器重置偏移量,重新消费数据,保证一致性。
sink–Kafka producer 作为sink,采用两阶段提交sink,需要实现一个TwoPhaseCommitSinkFunction。

Flink相比传统的SparkStreaming区别?

Flink是标准的实时处理引擎,基于事件驱动。而SparkStreaming是微批(MicroBatch)的模型。(最大区别)

Flink的基础编程模型了解吗?

基本构建是数据输入来自一个source,代表输入端。
经过transformation转换,在一个或者多个sink接收器结束。
数据流(stream)就是一组永远不会停止的数据记录流,而转换(transformation)试将一个或者多个流作为输入,生成一或多个输出流的操作。
执行时,flink程序映射到streamingdataflow,就流(streams)和转换操作(transformationoperators)组成

说说Flink中的窗口?

划分窗口的方式,time和count
滚动窗口(TumblingEventTimeWindows)
滑动窗口(SlidingEventTimeWindows)
会话窗口(EventTimeSessionWindows)

窗口函数分两种:增量和全量
增量:reduce和eggregate(每个窗口先计算)
全量:process(先缓存该窗口所有元素,触发再算)

Flink中水印是什么概念,起到什么作用?

Watermark是ApacheFlink为了【处理EventTime窗口计算提出的一种机制】,本质上是一种【时间戳】。一般来讲Watermark经常和Window一起被用来【处理乱序事件。】

事件时间-摄入时间-处理时间

Flink是如何保证Exactlyonce语义的?

两阶段提交和状态保存来实现端到端的一致性语义

开始事务,【创建一个临时文件】,把数据写入文件夹。
【预提交将内存缓存的数据写入文件并关闭】。
【正式提交将之前写完的临时放到目标目录下】,最终会有些延迟。
【丢弃临时文件】。
若发生在预提交成功后,正式提交前。可以根据状态来提交预提交的数据,也可以删除预提交数据。

开始事务(beginTransaction)创建一个临时文件夹,来写把数据写入到这个文件夹里面
预提交(preCommit)将内存中缓存的数据写入文件并关闭
正式提交(commit)将之前写完的临时文件放入目标目录下。这代表着最终的数据会有一些延迟
丢弃(abort)丢弃临时文件
若失败发生在预提交成功后,正式提交前。可以根据状态来提交预提交的数据,也可删除预提交的数据

Flink中的Window出现了数据倾斜,你有什么解决办法?

window产生数据倾斜指的是数据在不同的窗口内堆积的数据量相差过多。本质上产生这种情况的原因是数据源头发送的数据量速度不同导致的。出现这种情况一般通过两种方式来解决:
在数据进入【窗口前做预聚合】。
【重新设计窗口聚合的key】

Flink中在使用聚合函数GroupBy、Distinct、KeyBy等函数时出现数据热点该如何解决?

在业务上规避这类问题
(把热点单独处理)

key设计
(把key拆分聚合)

参数设置【1.9.0SQL(BlinkPlanner),升级了微批模型MiniBatch】(缓存一定数据后再处理,减少state访问,提升吞吐和减少数据的输出量)

FlinkJob的提交流程(三层图)

【用户提交】的FlinkJob会被【转化成一个DAG任务运行】,分别是:【StreamGraph、JobGraph、ExecutionGraph】,Flink中【JobManager与TaskManager】,【JobManager与Client的交互是基于Akka(实时事务处理)工具包的,是通过消息驱动】。整个FlinkJob的提交还【包含着ActorSystem(调度)的创建,JobManager的启动,TaskManager的启动和注册】

三层图:StreamGraph->JobGraph->ExecutionGraph

查询应用类(扩展)

superset可视化

Python编写的web应用
能够对接常用的大数据分析工具,如hive,kylin,Druid等,数仓的可视化工具

ElasticSearch搜索

ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式、支持多用户的全文搜索引擎,基于RESTful Web接口。ElasticSearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索、稳定、可靠、快速、安装使用方便。

与mysql区别?

在这里插入图片描述

即席查询

presto (基于内存)

开源分布式sql查询引擎,数据量支持GB到PB字节,主要来处理秒级查询的场景,可以跨数据源查询

注:虽然可以解析sql,但它不是标准的数据库,不是mysql和oracle的替代品,也不能用来处理在线事务(OLTP)
一个数据源是catalog(目录)

impala也可以做

和presto类似架构,但优于它,但是数据源比impala数据源多

Druid(预计算)

快速的列式分布式的支持实时分析的数据储存系统,在处理PB级数据,毫秒级查询,数据实时处理方面,比传统OLAP显著的改进。

需要清洗的数据,和只读分析的。
实时比较高,数据质量不高的场景

DataSource(表)+segment(时间分块)

Kylin(预计算)

Kylin是一个开源的分布式分析引擎,提供了基于Hadoop的超大型数据集(TB/PB级别)的SQL接口以及多维度的OLAP分布式联机分析。最初由eBay开发并贡献至开源社区。它能在亚秒内查询巨大的Hive表。默认计算引擎hadoop,也可以spark,sql查询接口。

核心是cube(立方体),储存使用hbase

支持类型:prosto->sparksql->kylin->druid
查询效率:druid->kylin->prosto->sparksql

数据管理类(扩展)

这些都蛮简单,网上自行搜索

1、Azkaban(任务调度)

Azkaban是由linked开源的一个批量工作流任务调度器,它是由三个部分组成:Azkaban Web Server(管理服务器)、Azkaban Executor Server(执行管理器)和MySQL(关系数据库),可用于在一个工作流内以一个特定的顺序运行一组工作和流程,可以利用Azkaban来完成大数据的任务调度,大数据开发需掌握Azkaban的相关配置及语法规则。

2、EasyScheduler(任务调度)

在这里插入图片描述

3、AirFlow(任务调度)

airflow是一款开源的,分布式任务调度框架,它将一个具有上下级依赖关系的工作流,组装成一个有向无环图。
特点:
分布式任务调度:允许一个工作流的task在多台worker上同时执行
可构建任务依赖:以有向无环图的方式构建任务依赖关系
task原子性:工作流上每个task都是原子可重试的,一个工作流某个环节的task失败可自动或手动进行重试,不必从头开始任务
工作流示意图
在这里插入图片描述

4、数据治理

Atlas(元数据管理)

0.84最新

元数据打通了数据源、数据仓库、数据应用,记录了数据从产生到消费的全过程。因此,数据治理的核心就是元数据管理。

Atlas是一个可伸缩和可扩展的核心基础治理服务集合,使企业能够有效地和高效地满足Hadoop中的合规性要求,并允许与整个企业数据生态系统的集成。

ApacheAtlas为组织提供开放式元数据管理和治理功能,用以构建其数据资产目录,对这些资产进行分类和管理,并为数据科学家,数据分析师和数据治理团队提供围绕这些数据资产的协作功能。

元数据在hive里面用Kafka去读,读完直接到内核储存到hbase里面,然后用solr查询对应的元数据,然后支持二次开发的功能,最后图形化展示。

数据质量监控(Griffin)

0.4/0.5版本 对网络要求高,需要重新编译,用自己写脚本

分为batch(批)streaming(流),实时数据检测未有界面配置,可以通过api的方式提交。
Apache可视化监控工具,一步一步走,最终呈现监控画面

为什么要做数据质量监控(2019 年下半年)

1)数据不一致
2)数据不完整
3)数据不合规
4)数据不可控
5)数据冗余

建设方法

在这里插入图片描述

质量监管平台建设,主要包含如下 8 大流程步骤:

质量需求:发现数据问题;信息提报、收集需求;检核规则的需求等;

提炼规则:梳理规则指标、确定有效指标、检核指标准确度和衡量标准;

规则库构建:检核对象配置、调度配置、规则配置、检核范围确认、检核标准确定
等;

执行检核:调度配置、调度执行、检核代码;

问题检核:检核问题展示、分类、质量分析、质量严重等级分类等;

分析报告:数据质量报告、质量问题趋势分析,影响度分析,解决方案达成共识;

落实处理:方案落实执行、跟踪管理、解决方案 Review 及标准化提炼;

知识库体系形成:知识经验总结、标准方案沉淀、知识库体系建设。

权限管理

ranger ,sertry,人物认证

5、数据中台

https://mp.weixin.qq.com/s/nXI0nSSOneteIClA7dming
将相同模块提取,共同的

6、数据湖

数据湖(Data Lake)是一个存储企业的各种各样原始数据的大型仓库,其中的数据可供存取、处理、分析及传输。

数据湖是一个概念,而 Hadoop 是用于实现这个概念的技术。

7、OLAP(联机分析处理)

On line Analytical Processing
是一种软件技术,它使分析人员能够迅速、一致、交互地从【各个方面观察信息】,以达到深入理解数据的目的。【多维度分析】
维度2的n次方-1 种

OLAP类型:
ROLAP:基于关系型数据库,不需要预计算
MOLAP:基于多维数据集,需要预计算

它具有FASMI(Fast Analysis of Shared Multidimensional Information),即共享多维信息的快速分析的特征。
其中F是快速性(Fast),指系统能在数秒内对用户的多数分析要求做出反应;
A是可分析性(Analysis),指用户无需编程就可以定义新的专门计算,将其作为分析的一部 分,并以用户所希望的方式给出报告;
M是多维性(Multi—dimensional),指提供对数据分析的多维视图和分析;
I是信息性(Information),指能及时获得信息,并且管理大容量信息。

OLAP展现在用户面前的是一幅幅多维视图

OLTP:像mysql 专门处理后台业务的数据,GB
OLAP:擅长分析的,hive,spark,TB到PB

运维(扩展)

Zabbix监控集群(运维)

监控某些进程出现问题,进行通知

官方网站:https://www.zabbix.com/
Zabbix是一个基于WEB界面的提供分布式系统监控以及网络监控功能的企业级开源运维平台,也是目前国内互联网用户中使用最广的监控软件,云智慧遇到的85%以上用户在使用Zabbix做监控解决方案。
用户群:90%以上中小型的泛互联网企业
在这里插入图片描述

Ganglia

官方网站:http://ganglia.info/
Ganglia是加州大学伯克利分校发起的一个开源集群监控项目,设计之初是用于监控数以千计的网络节点。Ganglia是一个跨平台可扩展的,高性能计算系统下的分布式监控系统。它已被广泛移植到各种操作系统和处理器架构上。
用户群:适用于大型服务器集群用户。

版本控制(要会)

不懂的兄弟们,网上搜索,大概花个三个小时,就差不多了,常用性就不说了,可从gitee码云上手,毕竟中文。

Git版本控制

开源的分布式版本控制系统,也是个内容管理系统(CMS),工作管理系统等。

Git与SVN区别

Git是分布式的,SVN不是:
这是Git和其它非分布式的版本控制系统,例如SVN,CVS等,最核心的区别。

Git把内容按元数据方式存储,而SVN是按文件:
所有的资源控制系统都是把文件的元信息隐藏在一个类似.svn、.cvs等的文件夹里。

Git分支和SVN的分支不同:
分支在SVN中一点都不特别,其实它就是版本库中的另外一个目录。

Git没有一个全局的版本号,而SVN有:
目前为止这是跟SVN相比Git缺少的最大的一个特征。
Git的内容完整性要优于SVN:
Git的内容存储使用的是SHA1哈希算法。这能确保代码内容的完整性,确保在遇到磁盘故障和网络问题时降低对版本库的破坏。

在这里插入图片描述

呼!!暂时就到这吧,后续如有或小伙伴在工作面试遇到的可以留言这里,给大家再补充。刚好参加了这个活动,大家记得关注点赞收藏三连支持下哈,整理不易,感谢兄弟们!

单是说不行,要紧的是做。——鲁迅

猜你喜欢

转载自blog.csdn.net/qq_63369191/article/details/124601774