共计 72211 个字符,预计需要花费 181 分钟才能阅读完成。
此套面试题来自于各大厂的实在面试题及常问的知识点,如果能了解吃透这些问题,你的大数据能力将会大大晋升,进入大厂不可企及
获取本文《2023 最新大数据面试宝典》完整版带目录的 PDF 文档 ,请搜寻公众号【五分钟学大数据】,在对话框发送 2023 面试,即可获取。
参考链接:
2023 版最新最弱小数据面试宝典,附答案解析
温习大数据面试题,看这一套就够了!
本文目录:
一、Hadoop
\
二、Hive
\
三、Spark
\
四、Kafka
\
五、HBase
\
六、Flink
\
七、Clickhouse
\
八、Doris
\
九、数据仓库
\
十、数据湖
\
十一、必备 SQL 题
\
十二、必备算法
\
十三、大数据算法设计题
前言
此版本面试题相较于之前减少了很少数仓以及算法相干的题,同时新增了数据湖,必备 SQL 题,Clickhouse,Doris 等面试题。
版本更新如下:
版本 | 工夫 | 形容 |
---|---|---|
V1.0 | 2020-12-18 | 创立 |
V1.2 | 2021-01-17 | 新增:spark 面试题 |
V1.3 | 2021-01-18 | 新增:kafka 面试题 |
V1.4 | 2021-01-20 | 新增:hbase 面试题 |
V1.5 | 2021-01-30 | 新增:flink 面试题 |
V3.0 | 2022-01-10 | 新增:数据仓库,算法等面试题 修复:局部答案不残缺或有误 |
V4.0(此版本) | 2023-02-12 | 更新:数据仓库及算法; 新增:数据湖,必备 SQL 题,Clickhouse,Doris,大数据算法设计题 |
获取本文《2023 最新大数据面试宝典》完整版带目录的 PDF 文档,请搜寻公众号【五分钟学大数据】,在对话框发送 2023 面试,即可获取。完整版链接:
2023 版最新最弱小数据面试宝典,附答案解析
Hadoop
Hadoop 中常问的就三块,第一:分布式存储(HDFS);第二:分布式计算框架(MapReduce);第三:资源调度框架(YARN)。
1. 请说下 HDFS 读写流程
这个问题尽管见过无数次,面试官问过无数次,还是有不少面试者不能残缺的说进去,所以请务必记住。并且很多问题都是从 HDFS 读写流程中引申进去的。
HDFS 写流程:
- Client 客户端发送上传申请,通过 RPC 与 NameNode 建设通信,NameNode 查看该用户是否有上传权限,以及上传的文件是否在 HDFS 对应的目录下重名,如果这两者有任意一个不满足,则间接报错,如果两者都满足,则返回给客户端一个能够上传的信息;
- Client 依据文件的大小进行切分,默认 128M 一块,切分实现之后给 NameNode 发送申请第一个 block 块上传到哪些服务器上;
-
NameNode 收到申请之后,依据网络拓扑和机架感知以及正本机制进行文件调配,返回可用的 DataNode 的地址;
注:Hadoop 在设计时思考到数据的平安与高效, 数据文件默认在 HDFS 上寄存三份, 存储策略为本地一份,同机架内其它某一节点上一份, 不同机架的某一节点上一份。
- 客户端收到地址之后与服务器地址列表中的一个节点如 A 进行通信,实质上就是 RPC 调用,建设 pipeline,A 收到申请后会持续调用 B,B 在调用 C,将整个 pipeline 建设实现,逐级返回 Client;
- Client 开始向 A 上发送第一个 block(先从磁盘读取数据而后放到本地内存缓存 ), 以 packet(数据包,64kb)为单位,A 收到一个 packet 就会发送给 B,而后 B 发送给 C,A 每传完一个 packet 就会放入一个应答队列期待应答;
- 数据被宰割成一个个的 packet 数据包在 pipeline 上顺次传输,在 pipeline 反向传输中,一一发送 ack(命令正确应答),最终由 pipeline 中第一个 DataNode 节点 A 将 pipelineack 发送给 Client;
- 当一个 block 传输实现之后, Client 再次申请 NameNode 上传第二个 block,NameNode 从新抉择三台 DataNode 给 Client。
HDFS 读流程:
- Client 向 NameNode 发送 RPC 申请。申请文件 block 的地位;
- NameNode 收到申请之后会检查用户权限以及是否有这个文件,如果都合乎,则会视状况返回局部或全副的 block 列表,对于每个 block,NameNode 都会返回含有该 block 正本的 DataNode 地址;这些返回的 DataNode 地址,会依照集群拓扑构造得出 DataNode 与客户端的间隔,而后进行排序,排序两个规定:网络拓扑构造中距离 Client 近的排靠前;心跳机制中超时汇报的 DataNode 状态为 STALE,这样的排靠后;
- Client 选取排序靠前的 DataNode 来读取 block,如果客户端自身就是 DataNode, 那么将从本地间接获取数据 ( 短路读取个性);
- 底层上实质是建设 Socket Stream(FSDataInputStream),反复的调用父类 DataInputStream 的 read 办法,直到这个块上的数据读取结束;
- 当读完列表的 block 后,若文件读取还没有完结,客户端会持续向 NameNode 获取下一批的 block 列表;
- 读取完一个 block 都会进行 checksum 验证,如果读取 DataNode 时呈现谬误,客户端会告诉 NameNode,而后再从下一个领有该 block 正本的 DataNode 持续读;
- read 办法是并行的读取 block 信息,不是一块一块的读取 ;NameNode 只是返回 Client 申请蕴含块的 DataNode 地址, 并不是返回申请块的数据;
- 最终读取来所有的 block 会合并成一个残缺的最终文件;
2. HDFS 在读取文件的时候,如果其中一个块忽然损坏了怎么办
客户端读取完 DataNode 上的块之后会进行 checksum 验证,也就是把客户端读取到本地的块与 HDFS 上的原始块进行校验,如果发现校验后果不统一,客户端会告诉 NameNode,而后再 从下一个领有该 block 正本的 DataNode 持续读。
3. HDFS 在上传文件的时候,如果其中一个 DataNode 忽然挂掉了怎么办
客户端上传文件时与 DataNode 建设 pipeline 管道,管道的正方向是客户端向 DataNode 发送的数据包,管道反向是 DataNode 向客户端发送 ack 确认,也就是正确接管到数据包之后发送一个已确认接管到的应答。
当 DataNode 忽然挂掉了,客户端接管不到这个 DataNode 发送的 ack 确认,客户端会告诉 NameNode,NameNode 查看该块的正本与规定的不符,NameNode 会告诉 DataNode 去复制正本,并将挂掉的 DataNode 作下线解决,不再让它参加文件上传与下载。
4. NameNode 在启动的时候会做哪些操作
NameNode 数据存储在内存和本地磁盘,本地磁盘数据存储在fsimage 镜像文件和 edits 编辑日志文件。
首次启动 NameNode:
- 格式化文件系统,为了生成 fsimage 镜像文件;
-
启动 NameNode:
- 读取 fsimage 文件,将文件内容加载进内存
- 期待 DataNade 注册与发送 block report
-
启动 DataNode:
- 向 NameNode 注册
- 发送 block report
- 查看 fsimage 中记录的块的数量和 block report 中的块的总数是否雷同
-
对文件系统进行操作(创立目录,上传文件,删除文件等):
- 此时内存中曾经有文件系统扭转的信息,然而磁盘中没有文件系统扭转的信息,此时会将这些扭转信息写入 edits 文件中,edits 文件中存储的是文件系统元数据扭转的信息。
第二次启动 NameNode:
- 读取 fsimage 和 edits 文件;
- 将 fsimage 和 edits 文件合并成新的 fsimage 文件;
- 创立新的 edits 文件,内容开始为空;
- 启动 DataNode。
5. Secondary NameNode 理解吗,它的工作机制是怎么的
Secondary NameNode 是合并 NameNode 的 edit logs 到 fsimage 文件中;
它的具体工作机制:
- Secondary NameNode 询问 NameNode 是否须要 checkpoint。间接带回 NameNode 是否查看后果;
- Secondary NameNode 申请执行 checkpoint;
- NameNode 滚动正在写的 edits 日志;
- 将滚动前的编辑日志和镜像文件拷贝到 Secondary NameNode;
- Secondary NameNode 加载编辑日志和镜像文件到内存,并合并;
- 生成新的镜像文件 fsimage.chkpoint;
- 拷贝 fsimage.chkpoint 到 NameNode;
- NameNode 将 fsimage.chkpoint 重新命名成 fsimage;
所以如果 NameNode 中的元数据失落,是能够从 Secondary NameNode 复原一部分元数据信息的,但不是全副,因为 NameNode 正在写的 edits 日志还没有拷贝到 Secondary NameNode,这部分复原不了。
6. Secondary NameNode 不能复原 NameNode 的全副数据,那如何保障 NameNode 数据存储平安
这个问题就要说 NameNode 的高可用了,即 NameNode HA。
一个 NameNode 有单点故障的问题,那就配置双 NameNode,配置有两个关键点,一是必须要保障这两个 NameNode 的元数据信息必须要同步的,二是一个 NameNode 挂掉之后另一个要立马补上。
- 元数据信息同步在 HA 计划中采纳的是“共享存储”。每次写文件时,须要将日志同步写入共享存储,这个步骤胜利能力认定写文件胜利。而后备份节点定期从共享存储同步日志,以便进行主备切换。
- 监控 NameNode 状态采纳 zookeeper,两个 NameNode 节点的状态寄存在 zookeeper 中,另外两个 NameNode 节点别离有一个过程监控程序,施行读取 zookeeper 中有 NameNode 的状态,来判断以后的 NameNode 是不是曾经 down 机。如果 Standby 的 NameNode 节点的 ZKFC 发现主节点曾经挂掉,那么就会强制给本来的 Active NameNode 节点发送强制敞开申请,之后将备用的 NameNode 设置为 Active。
如果面试官再问 HA 中的 共享存储 是怎么实现的晓得吗?
能够进行解释下:NameNode 共享存储计划有很多,比方 Linux HA, VMware FT, QJM 等,目前社区曾经把由 Clouderea 公司实现的基于 QJM(Quorum Journal Manager)的计划合并到 HDFS 的 trunk 之中并且作为 默认的共享存储 实现。
基于 QJM 的共享存储系统 次要用于保留 EditLog,并不保留 FSImage 文件。FSImage 文件还是在 NameNode 的本地磁盘上。
QJM 共享存储的根本思维来自于 Paxos 算法,采纳多个称为 JournalNode 的节点组成的 JournalNode 集群来存储 EditLog。每个 JournalNode 保留同样的 EditLog 正本。每次 NameNode 写 EditLog 的时候,除了向本地磁盘写入 EditLog 之外,也会并行地向 JournalNode 集群之中的每一个 JournalNode 发送写申请,只有大多数的 JournalNode 节点返回胜利就认为向 JournalNode 集群写入 EditLog 胜利。如果有 2N+ 1 台 JournalNode,那么依据大多数的准则,最多能够容忍有 N 台 JournalNode 节点挂掉。
7. 在 NameNode HA 中,会呈现脑裂问题吗?怎么解决脑裂
假如 NameNode1 以后为 Active 状态,NameNode2 以后为 Standby 状态。如果某一时刻 NameNode1 对应的 ZKFailoverController 过程产生了“假死”景象,那么 Zookeeper 服务端会认为 NameNode1 挂掉了,依据后面的主备切换逻辑,NameNode2 会代替 NameNode1 进入 Active 状态。然而此时 NameNode1 可能依然处于 Active 状态失常运行,这样 NameNode1 和 NameNode2 都处于 Active 状态,都能够对外提供服务。这种状况称为脑裂。
脑裂对于 NameNode 这类对数据一致性要求十分高的零碎来说是灾难性的,数据会产生错乱且无奈复原。zookeeper 社区对这种问题的解决办法叫做 fencing,中文翻译为隔离,也就是想方法把旧的 Active NameNode 隔离起来,使它不能失常对外提供服务。
在进行 fencing 的时候,会执行以下的操作:
- 首先尝试调用这个旧 Active NameNode 的 HAServiceProtocol RPC 接口的 transitionToStandby 办法,看能不能把它转换为 Standby 状态。
-
如果 transitionToStandby 办法调用失败,那么就执行 Hadoop 配置文件之中预约义的隔离措施,Hadoop 目前次要提供两种隔离措施,通常会抉择 sshfence:
- sshfence:通过 SSH 登录到指标机器上,执行命令 fuser 将对应的过程杀死;
- shellfence:执行一个用户自定义的 shell 脚本来将对应的过程隔离。
8. 小文件过多会有什么危害,如何防止
Hadoop 上大量 HDFS 元数据信息存储在 NameNode 内存中, 因而过多的小文件必定会压垮 NameNode 的内存。
每个元数据对象约占 150byte,所以如果有 1 千万个小文件,每个文件占用一个 block,则 NameNode 大概须要 2G 空间。如果存储 1 亿个文件,则 NameNode 须要 20G 空间。
不言而喻的解决这个问题的办法就是合并小文件, 能够抉择在客户端上传时执行肯定的策略先合并, 或者是应用 Hadoop 的 CombineFileInputFormat\<K,V\>
实现小文件的合并。
9. 请说下 HDFS 的组织架构
-
Client:客户端
- 切分文件。文件上传 HDFS 的时候,Client 将文件切分成一个一个的 Block,而后进行存储
- 与 NameNode 交互,获取文件的地位信息
- 与 DataNode 交互,读取或者写入数据
- Client 提供一些命令来治理 HDFS,比方启动敞开 HDFS、拜访 HDFS 目录及内容等
-
NameNode:名称节点,也称主节点,存储数据的元数据信息,不存储具体的数据
- 治理 HDFS 的名称空间
- 治理数据块(Block)映射信息
- 配置正本策略
- 解决客户端读写申请
-
DataNode:数据节点,也称从节点。NameNode 下达命令,DataNode 执行理论的操作
- 存储理论的数据块
- 执行数据块的读 / 写操作
-
Secondary NameNode:并非 NameNode 的热备。当 NameNode 挂掉的时候,它并不能马上替换 NameNode 并提供服务
- 辅助 NameNode,分担其工作量
- 定期合并 Fsimage 和 Edits,并推送给 NameNode
- 在紧急情况下,可辅助复原 NameNode
10. 请说下 MR 中 Map Task 的工作机制
简略概述:
inputFile 通过 split 被切割为多个 split 文件,通过 Record 按行读取内容给 map(本人写的解决逻辑的办法)
,数据被 map 解决完之后交给 OutputCollect 收集器,对其后果 key 进行分区(默认应用的 hashPartitioner),而后写入 buffer,每个 map task 都有一个内存缓冲区(环形缓冲区),寄存着 map 的输入后果,当缓冲区快满的时候须要将缓冲区的数据以一个临时文件的形式溢写到磁盘,当整个 map task 完结后再对磁盘中这个 maptask 产生的所有临时文件做合并,生成最终的正式输入文件,而后期待 reduce task 的拉取。
具体步骤:
1) 读取数据组件 InputFormat (默认 TextInputFormat) 会通过 getSplits 办法对输出目录中的文件进行逻辑切片布局失去 block,有多少个 block 就对应启动多少个 MapTask。
2) 将输出文件切分为 block 之后,由 RecordReader 对象 (默认是 LineRecordReader) 进行读取,以 \n 作为分隔符, 读取一行数据, 返回 \<key,value\>,Key 示意每行首字符偏移值,Value 示意这一行文本内容。
3) 读取 block 返回 \<key,value\>, 进入用户本人继承的 Mapper 类中,执行用户重写的 map 函数,RecordReader 读取一行这里调用一次。
4) Mapper 逻辑完结之后,将 Mapper 的每条后果通过 context.write 进行 collect 数据收集。在 collect 中,会先对其进行分区解决,默认应用 HashPartitioner。
5) 接下来,会将数据写入内存,内存中这片区域叫做环形缓冲区(默认 100M),缓冲区的作用是 批量收集 Mapper 后果,缩小磁盘 IO 的影响。咱们的 Key/Value 对以及 Partition 的后果都会被写入缓冲区。当然,写入之前,Key 与 Value 值都会被序列化成字节数组。
6) 当环形缓冲区的数据达到溢写比列 (默认 0.8),也就是 80M 时,溢写线程启动, 须要对这 80MB 空间内的 Key 做排序 (Sort)。排序是 MapReduce 模型默认的行为,这里的排序也是对序列化的字节做的排序。
7) 合并溢写文件,每次溢写会在磁盘上生成一个临时文件 (写之前判断是否有 Combiner),如果 Mapper 的输入后果真的很大,有屡次这样的溢写产生,磁盘上相应的就会有多个临时文件存在。当整个数据处理完结之后开始对磁盘中的临时文件进行 Merge 合并,因为最终的文件只有一个写入磁盘,并且为这个文件提供了一个索引文件,以记录每个 reduce 对应数据的偏移量。
11. 请说下 MR 中 Reduce Task 的工作机制
简略形容:
Reduce 大抵分为 copy、sort、reduce 三个阶段,重点在前两个阶段。
copy 阶段蕴含一个 eventFetcher 来获取已实现的 map 列表,由 Fetcher 线程去 copy 数据,在此过程中会启动两个 merge 线程,别离为 inMemoryMerger 和 onDiskMerger,别离将内存中的数据 merge 到磁盘和将磁盘中的数据进行 merge。待数据 copy 实现之后,copy 阶段就实现了。
开始进行 sort 阶段,sort 阶段次要是执行 finalMerge 操作,纯正的 sort 阶段,实现之后就是 reduce 阶段,调用用户定义的 reduce 函数进行解决。
具体步骤:
1) Copy 阶段:简略地拉取数据。Reduce 过程启动一些数据 copy 线程(Fetcher),通过 HTTP 形式申请 maptask 获取属于本人的文件(map task 的分区会标识每个 map task 属于哪个 reduce task,默认 reduce task 的标识从 0 开始)。
2) Merge 阶段:在近程拷贝数据的同时,ReduceTask 启动了两个后盾线程对内存和磁盘上的文件进行合并,以避免内存应用过多或磁盘上文件过多。
merge 有三种模式:内存到内存;内存到磁盘;磁盘到磁盘。默认状况下第一种模式不启用。当内存中的数据量达到肯定阈值,就间接启动内存到磁盘的 merge。与 map 端相似,这也是溢写的过程,这个过程中如果你设置有 Combiner,也是会启用的,而后在磁盘中生成了泛滥的溢写文件。内存到磁盘的 merge 形式始终在运行,直到没有 map 端的数据时才完结,而后启动第三种磁盘到磁盘的 merge 形式生成最终的文件。
3) 合并排序:把扩散的数据合并成一个大的数据后,还会再对合并后的数据排序。
4) 对排序后的键值对调用 reduce 办法:键相等的键值对调用一次 reduce 办法,每次调用会产生零个或者多个键值对,最初把这些输入的键值对写入到 HDFS 文件中。
12. 请说下 MR 中 Shuffle 阶段
shuffle 阶段分为四个步骤:顺次为:分区,排序,规约,分组,其中前三个步骤在 map 阶段实现,最初一个步骤在 reduce 阶段实现。
shuffle 是 Mapreduce 的外围,它散布在 Mapreduce 的 map 阶段和 reduce 阶段。个别把从 Map 产生输入开始到 Reduce 获得数据作为输出之前的过程称作 shuffle。
- Collect 阶段:将 MapTask 的后果输入到默认大小为 100M 的环形缓冲区,保留的是 key/value,Partition 分区信息等。
- Spill 阶段:当内存中的数据量达到肯定的阀值的时候,就会将数据写入本地磁盘,在将数据写入磁盘之前须要对数据进行一次排序的操作,如果配置了 combiner,还会将有雷同分区号和 key 的数据进行排序。
- MapTask 阶段的 Merge:把所有溢出的临时文件进行一次合并操作,以确保一个 MapTask 最终只产生一个两头数据文件。
- Copy 阶段:ReduceTask 启动 Fetcher 线程到曾经实现 MapTask 的节点上复制一份属于本人的数据,这些数据默认会保留在内存的缓冲区中,当内存的缓冲区达到肯定的阀值的时候,就会将数据写到磁盘之上。
- ReduceTask 阶段的 Merge:在 ReduceTask 近程复制数据的同时,会在后盾开启两个线程对内存到本地的数据文件进行合并操作。
- Sort 阶段:在对数据进行合并的同时,会进行排序操作,因为 MapTask 阶段曾经对数据进行了部分的排序,ReduceTask 只需保障 Copy 的数据的最终整体有效性即可。
Shuffle 中的缓冲区大小会影响到 mapreduce 程序的执行效率,原则上说,缓冲区越大,磁盘 io 的次数越少,执行速度就越快。
缓冲区的大小能够通过参数调整, 参数:mapreduce.task.io.sort.mb
默认 100M
13. Shuffle 阶段的数据压缩机制理解吗
在 shuffle 阶段,能够看到数据通过大量的拷贝,从 map 阶段输入的数据,都要通过网络拷贝,发送到 reduce 阶段,这一过程中,波及到大量的网络 IO,如果数据可能进行压缩,那么数据的发送量就会少得多。
hadoop 当中反对的压缩算法:
gzip、bzip2、LZO、LZ4、Snappy,这几种压缩算法综合压缩和解压缩的速率,谷歌的 Snappy 是最优的,个别都抉择 Snappy 压缩。谷歌出品,必属精品。
14. 在写 MR 时,什么状况下能够应用规约
规约(combiner)是不可能影响工作的运行后果的部分汇总,实用于求和类,不适用于求平均值,如果 reduce 的输出参数类型和输入参数的类型是一样的,则规约的类能够应用 reduce 类,只须要在驱动类中指明规约的类即可。
15. YARN 集群的架构和工作原理晓得多少
YARN 的根本设计思维是将 MapReduce V1 中的 JobTracker 拆分为两个独立的服务:ResourceManager 和 ApplicationMaster。
ResourceManager 负责整个零碎的资源管理和调配,ApplicationMaster 负责单个应用程序的的治理。
1) ResourceManager:
RM 是一个全局的资源管理器,负责整个零碎的资源管理和调配,它次要由两个局部组成:调度器(Scheduler)和应用程序管理器(Application Manager)。
调度器依据容量、队列等限度条件,将零碎中的资源分配给正在运行的应用程序,在保障容量、公平性和服务等级的前提下,优化集群资源利用率,让所有的资源都被充分利用应用程序管理器负责管理整个零碎中的所有的应用程序,包含应用程序的提交、与调度器协商资源以启动 ApplicationMaster、监控 ApplicationMaster 运行状态并在失败时重启它。
2) ApplicationMaster:
用户提交的一个应用程序会对应于一个 ApplicationMaster,它的次要性能有:
- 与 RM 调度器协商以取得资源,资源以 Container 示意。- 将失去的工作进一步调配给外部的工作。- 与 NM 通信以启动 / 进行工作。- 监控所有的外部工作状态,并在工作运行失败的时候从新为工作申请资源以重启工作。
3) NodeManager:
NodeManager 是每个节点上的资源和工作管理器,一方面,它会定期地向 RM 汇报本节点上的资源应用状况和各个 Container 的运行状态;另一方面,他接管并解决来自 AM 的 Container 启动和进行申请。
4) Container:
Container 是 YARN 中的资源形象,封装了各种资源。一个应用程序会调配一个 Container,这个应用程序只能应用这个 Container 中形容的资源。不同于 MapReduceV1 中槽位 slot 的资源封装,Container 是一个动静资源的划分单位,更能充分利用资源。
16. YARN 的工作提交流程是怎么的
当 jobclient 向 YARN 提交一个应用程序后,YARN 将分两个阶段运行这个应用程序:一是启动 ApplicationMaster; 第二个阶段是由 ApplicationMaster 创立应用程序,为它申请资源,监控运行直到完结。
具体步骤如下:
1) 用户向 YARN 提交一个应用程序,并指定 ApplicationMaster 程序、启动 ApplicationMaster 的命令、用户程序。
2) RM 为这个应用程序调配第一个 Container,并与之对应的 NM 通信,要求它在这个 Container 中启动应用程序 ApplicationMaster。
3) ApplicationMaster 向 RM 注册,而后拆分为外部各个子工作,为各个外部工作申请资源,并监控这些工作的运行,直到完结。
4) AM 采纳轮询的形式向 RM 申请和支付资源。
5) RM 为 AM 分配资源,以 Container 模式返回。
6) AM 申请到资源后,便与之对应的 NM 通信,要求 NM 启动工作。
7) NodeManager 为工作设置好运行环境,将工作启动命令写到一个脚本中,并通过运行这个脚本启动工作。
8) 各个工作向 AM 汇报本人的状态和进度,以便当工作失败时能够重启工作。
9) 应用程序实现后,ApplicationMaster 向 ResourceManager 登记并敞开本人。
17. YARN 的资源调度三种模型理解吗
在 Yarn 中有三种调度器能够抉择:FIFO Scheduler,Capacity Scheduler,Fair Scheduler。
Apache 版本的 hadoop 默认应用的是 Capacity Scheduler 调度形式。CDH 版本的默认应用的是 Fair Scheduler 调度形式
FIFO Scheduler(先来先服务):
FIFO Scheduler 把利用按提交的程序排成一个队列,这是一个先进先出队列,在进行资源分配的时候,先给队列中最头上的利用进行分配资源,待最头上的利用需要满足后再给下一个调配,以此类推。
FIFO Scheduler 是最简略也是最容易了解的调度器,也不须要任何配置,但它并不适用于共享集群。大的利用可能会占用所有集群资源,这就导致其它利用被阻塞,比方有个大工作在执行,占用了全副的资源,再提交一个小工作,则此小工作会始终被阻塞。
Capacity Scheduler(能力调度器):
对于 Capacity 调度器,有一个专门的队列用来运行小工作,然而为小工作专门设置一个队列会事后占用肯定的集群资源,这就导致大工作的执行工夫会落后于应用 FIFO 调度器时的工夫。
Fair Scheduler(偏心调度器):
在 Fair 调度器中,咱们不须要事后占用肯定的系统资源,Fair 调度器会为所有运行的 job 动静的调整系统资源。
比方:当第一个大 job 提交时,只有这一个 job 在运行,此时它取得了所有集群资源;当第二个小工作提交后,Fair 调度器会调配一半资源给这个小工作,让这两个工作偏心的共享集群资源。
须要留神的是,在 Fair 调度器中,从第二个工作提交到取得资源会有肯定的提早,因为它须要期待第一个工作开释占用的 Container。小工作执行实现之后也会开释本人占用的资源,大工作又取得了全副的系统资源。最终的成果就是 Fair 调度器即失去了高的资源利用率又能保障小工作及时实现。
Hive
1. Hive 外部表和内部表的区别
未被 external 润饰的是外部表,被 external 润饰的为内部表。
区别:
1) 外部表数据由 Hive 本身治理,内部表数据由 HDFS 治理;
2) 外部表数据存储的地位是 hive.metastore.warehouse.dir
(默认:/user/hive/warehouse
),内部表数据的存储地位由本人制订(如果没有 LOCATION,Hive 将在 HDFS 上的/user/hive/warehouse
文件夹下以内部表的表名创立一个文件夹,并将属于这个表的数据寄存在这里);
3) 删除外部表会间接删除元数据(metadata)及存储数据;删除内部表仅仅会删除元数据,HDFS 上的文件并不会被删除。
2. Hive 有索引吗
Hive 反对索引(3.0 版本之前),然而 Hive 的索引与关系型数据库中的索引并不相同,比方,Hive 不反对主键或者外键。并且 Hive 索引提供的性能很无限,效率也并不高,因而 Hive 索引很少应用。
- 索引实用的场景:
实用于不更新的动态字段。免得总是重建索引数据。每次建设、更新数据后,都要重建索引以构建索引表。
- Hive 索引的机制如下:
hive 在指定列上建设索引,会产生一张索引表(Hive 的一张物理表),外面的字段包含:索引列的值、该值对应的 HDFS 文件门路、该值在文件中的偏移量。
Hive 0.8 版本后引入 bitmap 索引处理器,这个处理器实用于去重后,值较少的列(例如,某字段的取值只可能是几个枚举值)
因为索引是用空间换工夫,索引列的取值过多会导致建设 bitmap 索引表过大。
留神:Hive 中每次有数据时须要及时更新索引,相当于重建一个新表,否则会影响数据查问的效率和准确性,Hive 官网文档曾经明确示意 Hive 的索引不举荐被应用,在新版本的 Hive 中曾经被废除了。
扩大:Hive 是在 0.7 版本之后反对索引的,在 0.8 版本后引入 bitmap 索引处理器,在 3.0 版本开始移除索引的性能,取而代之的是 2.3 版本开始的物化视图,主动重写的物化视图代替了索引的性能。
3. 运维如何对 Hive 进行调度
- 将 hive 的 sql 定义在脚本当中;
- 应用 azkaban 或者 oozie 进行工作的调度;
- 监控任务调度页面。
4. ORC、Parquet 等列式存储的长处
ORC 和 Parquet 都是高性能的存储形式,这两种存储格局总会带来存储和性能上的晋升。
Parquet:
- Parquet 反对嵌套的数据模型,相似于 Protocol Buffers,每一个数据模型的 schema 蕴含多个字段,每一个字段有三个属性:反复次数、数据类型和字段名。
反复次数能够是以下三种:required(只呈现 1 次),repeated(呈现 0 次或屡次),optional(呈现 0 次或 1 次)。每一个字段的数据类型能够分成两种:
group(简单类型)和 primitive(根本类型)。 - Parquet 中没有 Map、Array 这样的简单数据结构,然而能够通过 repeated 和 group 组合来实现的。
- 因为 Parquet 反对的数据模型比拟涣散,可能一条记录中存在比拟深的嵌套关系,如果为每一条记录都保护一个相似的树状结可能会占用较大的存储空间,因而 Dremel 论文中提出了一种高效的对于嵌套数据格式的压缩算法:Striping/Assembly 算法。通过 Striping/Assembly 算法,parquet 能够应用较少的存储空间示意简单的嵌套格局,并且通常 Repetition level 和 Definition level 都是较小的整数值,能够通过 RLE 算法对其进行压缩,进一步升高存储空间。
- Parquet 文件是以二进制形式存储的,是不能够间接读取和批改的,Parquet 文件是自解析的,文件中包含该文件的数据和元数据。
ORC:
- ORC 文件是自描述的,它的元数据应用 Protocol Buffers 序列化,并且文件中的数据尽可能的压缩以升高存储空间的耗费。
- 和 Parquet 相似,ORC 文件也是以二进制形式存储的,所以是不能够间接读取,ORC 文件也是自解析的,它蕴含许多的元数据,这些元数据都是同构 ProtoBuffer 进行序列化的。
- ORC 会尽可能合并多个离散的区间尽可能的缩小 I / O 次数。
- ORC 中应用了更加准确的索引信息,使得在读取数据时能够指定从任意一行开始读取,更细粒度的统计信息使得读取 ORC 文件跳过整个 row group,ORC 默认会对任何一块数据和索引信息应用 ZLIB 压缩,因而 ORC 文件占用的存储空间也更小。
- 在新版本的 ORC 中也退出了对 Bloom Filter 的反对,它能够进一
步晋升谓词下推的效率,在 Hive 1.2.0 版本当前也退出了对此的支
持。
5. 数据建模用的哪些模型?
1. 星型模型
星形模式 (Star Schema) 是最罕用的维度建模形式。星型模式是以事实表为核心,所有的维度表间接连贯在事实表上,像星星一样。
星形模式的维度建模由一个事实表和一组维表成,且具备以下特点:
a. 维表只和事实表关联,维表之间没有关联;
b. 每个维表主键为单列,且该主键搁置在事实表中,作为两边连贯的外键;
c. 以事实表为外围,维表围绕外围呈星形散布。
2. 雪花模型
雪花模式 (Snowflake Schema) 是对星形模式的扩大。雪花模式的维度表能够领有其余维度表的,尽管这种模型相比星型更标准一些,然而因为这种模型不太容易了解,保护老本比拟高,而且性能方面须要关联多层维表,性能比星型模型要低。
3. 星座模型
星座模式是星型模式延长而来,星型模式是基于一张事实表的,而 星座模式是基于多张事实表的,而且共享维度信息。后面介绍的两种维度建模办法都是多维表对应单事实表,但在很多时候维度空间内的事实表不止一个,而一个维表也可能被多个事实表用到。在业务倒退前期,绝大部分维度建模都采纳的是星座模式。
数仓建模具体介绍可查看:通俗易懂数仓建模
6. 为什么要对数据仓库分层?
- 用空间换工夫,通过大量的预处理来晋升利用零碎的用户体验(效率),因而数据仓库会存在大量冗余的数据。
- 如果不分层的话,如果源业务零碎的业务规定发生变化将会影响整个数据荡涤过程,工作量微小。
- 通过数据分层治理能够简化数据荡涤的过程,因为把原来一步的工作分到了多个步骤去实现,相当于把一个简单的工作拆成了多个简略的工作,把一个大的黑盒变成了一个白盒,每一层的解决逻辑都绝对简略和容易了解,这样咱们比拟容易保障每一个步骤的正确性,当数据产生谬误的时候,往往咱们只须要部分调整某个步骤即可。
数据仓库具体介绍可查看:万字详解整个数据仓库建设体系
7. 应用过 Hive 解析 JSON 串吗
Hive 解决 json 数据总体来说有两个方向的路走:
- 将 json 以字符串的形式整个入 Hive 表,而后通过应用 UDF 函数解析曾经导入到 hive 中的数据,比方应用
LATERAL VIEW json_tuple
的办法,获取所须要的列名。 - 在导入之前将 json 拆成各个字段,导入 Hive 表的数据是曾经解析过的。这将须要应用第三方的
SerDe。
具体介绍可查看:Hive 解析 Json 数组超全解说
8. sort by 和 order by 的区别
order by 会对输出做全局排序,因而只有一个 reducer(多个 reducer 无奈保障全局有序)只有一个 reducer,会导致当输出规模较大时,须要较长的计算工夫。
sort by 不是全局排序,其在数据进入 reducer 前实现排序.
因而,如果用 sort by 进行排序,并且设置 mapred.reduce.tasks>1,则sort by 只保障每个 reducer 的输入有序,不保障全局有序。
9. 数据歪斜怎么解决
数据歪斜问题次要有以下几种:
- 空值引发的数据歪斜
- 不同数据类型引发的数据歪斜
- 不可拆分大文件引发的数据歪斜
- 数据收缩引发的数据歪斜
- 表连贯时引发的数据歪斜
- 的确无奈缩小数据量引发的数据歪斜
以上歪斜问题的具体解决方案可查看:Hive 千亿级数据歪斜解决方案
留神:对于 left join 或者 right join 来说,不会对关联的字段主动去除 null 值,对于 inner join 来说,会对关联的字段主动去除 null 值。
小伙伴们在浏览时留神下,在下面的文章(Hive 千亿级数据歪斜解决方案)中,有一处 sql 呈现了上述问题(举例的时候本来是想应用 left join 的,后果手误写成了 join)。此问题由公众号读者发现,感激这位读者斧正。
10. Hive 小文件过多怎么解决
1. 应用 hive 自带的 concatenate 命令,主动合并小文件
应用办法:
# 对于非分区表
alter table A concatenate;
#对于分区表
alter table B partition(day=20201224) concatenate;
留神:
1、concatenate 命令只反对 RCFILE 和 ORC 文件类型。
2、应用 concatenate 命令合并小文件时不能指定合并后的文件数量,但能够屡次执行该命令。
3、当屡次应用 concatenate 后文件数量不在变动,这个跟参数 mapreduce.input.fileinputformat.split.minsize=256mb 的设置无关,可设定每个文件的最小 size。
2. 调整参数缩小 Map 数量
设置 map 输出合并小文件的相干参数(执行 Map 前进行小文件合并):
在 mapper 中将多个文件合成一个 split 作为输出(CombineHiveInputFormat
底层是 Hadoop 的 CombineFileInputFormat
办法):
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat; -- 默认
每个 Map 最大输出大小(这个值决定了合并后文件的数量):
set mapred.max.split.size=256000000; -- 256M
一个节点上 split 的至多大小(这个值决定了多个 DataNode 上的文件是否须要合并):
set mapred.min.split.size.per.node=100000000; -- 100M
一个交换机下 split 的至多大小(这个值决定了多个交换机上的文件是否须要合并):
set mapred.min.split.size.per.rack=100000000; -- 100M
3. 缩小 Reduce 的数量
reduce 的个数决定了输入的文件的个数,所以能够调整 reduce 的个数管制 hive 表的文件数量。
hive 中的分区函数 distribute by 正好是管制 MR 中 partition 分区的,能够通过设置 reduce 的数量,联合分区函数让数据平衡的进入每个 reduce 即可:
# 设置 reduce 的数量有两种形式,第一种是间接设置 reduce 个数
set mapreduce.job.reduces=10;
#第二种是设置每个 reduce 的大小,Hive 会依据数据总大小猜想确定一个 reduce 个数
set hive.exec.reducers.bytes.per.reducer=5120000000; -- 默认是 1G,设置为 5G
#执行以下语句,将数据平衡的调配到 reduce 中
set mapreduce.job.reduces=10;
insert overwrite table A partition(dt)
select * from B
distribute by rand();
对于上述语句解释:如设置 reduce 数量为 10,应用 rand(),随机生成一个数 x % 10
,
这样数据就会随机进入 reduce 中,防止出现有的文件过大或过小。
4. 应用 hadoop 的 archive 将小文件归档
Hadoop Archive 简称 HAR,是一个高效地将小文件放入 HDFS 块中的文件存档工具,它可能将多个小文件打包成一个 HAR 文件,这样在缩小 namenode 内存应用的同时,依然容许对文件进行通明的拜访。
# 用来管制归档是否可用
set hive.archive.enabled=true;
#告诉 Hive 在创立归档时是否能够设置父目录
set hive.archive.har.parentdir.settable=true;
#管制须要归档文件的大小
set har.partfile.size=1099511627776;
应用以下命令进行归档:ALTER TABLE A ARCHIVE PARTITION(dt='2021-05-07', hr='12');
对已归档的分区复原为原文件:ALTER TABLE A UNARCHIVE PARTITION(dt='2021-05-07', hr='12');
留神:
归档的分区能够查看不能 insert overwrite,必须先 unarchive
Hive 小文件问题具体可查看:解决 hive 小文件过多问题
11. Hive 优化有哪些
1. 数据存储及压缩:
针对 hive 中表的存储格局通常有 orc 和 parquet,压缩格局个别应用 snappy。相比与 textfile 格局表,orc 占有更少的存储。因为 hive 底层应用 MR 计算架构,数据流是 hdfs 到磁盘再到 hdfs,而且会有很屡次,所以应用 orc 数据格式和 snappy 压缩策略能够升高 IO 读写,还能升高网络传输量,这样在肯定水平上能够节俭存储,还能晋升 hql 工作执行效率;
2. 通过调参优化:
并行执行,调节 parallel 参数;
调节 jvm 参数,重用 jvm;
设置 map、reduce 的参数;开启 strict mode 模式;
敞开揣测执行设置。
3. 无效地减小数据集将大表拆分成子表;联合应用内部表和分区表。
4. SQL 优化
- 大表对大表:尽量减少数据集,能够通过分区表,防止扫描全表或者全字段;
- 大表对小表:设置自动识别小表,将小表放入内存中去执行。
Hive 优化具体分析可查看:Hive 企业级性能优化
12. Tez 引擎长处?
Tez 能够将多个有依赖的作业转换为一个作业,这样只需写一次 HDFS,且两头节点较少,从而大大晋升作业的计算性能。
Mr/tez/spark 区别:
Mr 引擎:多 job 串联,基于磁盘,落盘的中央比拟多。尽管慢,但肯定能跑出后果。个别解决,周、月、年指标。
Spark 引擎:尽管在 Shuffle 过程中也落盘,然而并不是所有算子都须要 Shuffle,尤其是多算子过程,两头过程不落盘 DAG 有向无环图。兼顾了可靠性和效率。个别解决天指标。
Tez 引擎:齐全基于内存。留神:如果数据量特地大,谨慎应用。容易 OOM。个别用于疾速出后果,数据量比拟小的场景。
Spark
1. Spark 的运行流程?
具体运行流程如下:
- SparkContext 向资源管理器注册并向资源管理器申请运行 Executor
- 资源管理器调配 Executor,而后资源管理器启动 Executor
- Executor 发送心跳至资源管理器
- SparkContext 构建 DAG 有向无环图
- 将 DAG 分解成 Stage(TaskSet)
- 把 Stage 发送给 TaskScheduler
- Executor 向 SparkContext 申请 Task
- TaskScheduler 将 Task 发送给 Executor 运行
- 同时 SparkContext 将利用程序代码发放给 Executor
- Task 在 Executor 上运行,运行结束开释所有资源
2. Spark 有哪些组件?
- master:治理集群和节点,不参加计算。
- worker:计算节点,过程自身不参加计算,和 master 汇报。
- Driver:运行程序的 main 办法,创立 spark context 对象。
- spark context:管制整个 application 的生命周期,包含 dagsheduler 和 task scheduler 等组件。
- client:用户提交程序的入口。
3. Spark 中的 RDD 机制了解吗?
rdd 分布式弹性数据集,简略的了解成一种数据结构,是 spark 框架上的通用货币。所有算子都是基于 rdd 来执行的,不同的场景会有不同的 rdd 实现类,然而都能够进行相互转换。rdd 执行过程中会造成 dag 图,而后造成 lineage 保障容错性等。从物理的角度来看 rdd 存储的是 block 和 node 之间的映射。
RDD 是 spark 提供的外围形象,全称为弹性分布式数据集。
RDD 在逻辑上是一个 hdfs 文件,在形象上是一种元素汇合,蕴含了数据。它是被分区的,分为多个分区,每个分区散布在集群中的不同结点上,从而让 RDD 中的数据能够被并行操作(分布式数据集)
比方有个 RDD 有 90W 数据,3 个 partition,则每个分区上有 30W 数据。RDD 通常通过 Hadoop 上的文件,即 HDFS 或者 HIVE 表来创立,还能够通过应用程序中的汇合来创立;RDD 最重要的个性就是容错性,能够主动从节点失败中恢复过来。即如果某个结点上的 RDD partition 因为节点故障,导致数据失落,那么 RDD 能够通过本人的数据起源从新计算该 partition。这所有对使用者都是通明的。
RDD 的数据默认寄存在内存中,然而当内存资源有余时,spark 会主动将 RDD 数据写入磁盘。比方某结点内存只能解决 20W 数据,那么这 20W 数据就会放入内存中计算,剩下 10W 放到磁盘中。RDD 的弹性体当初于 RDD 上主动进行内存和磁盘之间衡量和切换的机制。
4. RDD 中 reduceBykey 与 groupByKey 哪个性能好,为什么?
reduceByKey:reduceByKey 会在后果发送至 reducer 之前会对每个 mapper 在本地进行 merge,有点相似于在 MapReduce 中的 combiner。这样做的益处在于,在 map 端进行一次 reduce 之后,数据量会大幅度减小,从而减小传输,保障 reduce 端可能更快的进行后果计算。
groupByKey:groupByKey 会对每一个 RDD 中的 value 值进行聚合造成一个序列(Iterator),此操作产生在 reduce 端,所以势必会将所有的数据通过网络进行传输,造成不必要的节约。同时如果数据量非常大,可能还会造成 OutOfMemoryError。
所以在进行大量数据的 reduce 操作时候倡议应用 reduceByKey。不仅能够进步速度,还能够避免应用 groupByKey 造成的内存溢出问题。
5. 介绍一下 cogroup rdd 实现原理,你在什么场景下用过这个 rdd?
cogroup:对多个(2~4)RDD 中的 KV 元素,每个 RDD 中雷同 key 中的元素别离聚合成一个汇合。
与 reduceByKey 不同的是 :reduceByKey 针对 一个 RDD中雷同的 key 进行合并。而 cogroup 针对 多个 RDD中雷同的 key 的元素进行合并。
cogroup 的函数实现:这个实现依据要进行合并的两个 RDD 操作,生成一个 CoGroupedRDD 的实例,这个 RDD 的返回后果是把雷同的 key 中两个 RDD 别离进行合并操作,最初返回的 RDD 的 value 是一个 Pair 的实例,这个实例蕴含两个 Iterable 的值,第一个值示意的是 RDD1 中雷同 KEY 的值,第二个值示意的是 RDD2 中雷同 key 的值。
因为做 cogroup 的操作,须要通过 partitioner 进行从新分区的操作,因而,执行这个流程时,须要执行一次 shuffle 的操作(如果要进行合并的两个 RDD 的都曾经是 shuffle 后的 rdd,同时他们对应的 partitioner 雷同时,就不须要执行 shuffle)。
场景:表关联查问或者解决反复的 key。
6. 如何辨别 RDD 的宽窄依赖?
窄依赖: 父 RDD 的一个分区只会被子 RDD 的一个分区依赖;
宽依赖: 父 RDD 的一个分区会被子 RDD 的多个分区依赖(波及到 shuffle)。
7. 为什么要设计宽窄依赖?
- _对于窄依赖_:
\
窄依赖的多个分区能够并行计算;
\
窄依赖的一个分区的数据如果失落只须要从新计算对应的分区的数据就能够了。 - _对于宽依赖_:
\
划分 Stage(阶段)的根据: 对于宽依赖, 必须等到上一阶段计算实现能力计算下一阶段。
8. DAG 是什么?
DAG(Directed Acyclic Graph 有向无环图)指的是数据转换执行的过程,有方向,无闭环 (其实就是 RDD 执行的流程);
\
原始的 RDD 通过一系列的转换操作就造成了 DAG 有向无环图,工作执行时,能够依照 DAG 的形容,执行真正的计算(数据被操作的一个过程)。
9. DAG 中为什么要划分 Stage?
并行计算。
一个简单的业务逻辑如果有 shuffle,那么就意味着后面阶段产生后果后,能力执行下一个阶段,即下一个阶段的计算要依赖上一个阶段的数据。那么咱们依照 shuffle 进行划分(也就是依照宽依赖就行划分),就能够将一个 DAG 划分成多个 Stage/ 阶段,在同一个 Stage 中,会有多个算子操作,能够造成一个 pipeline 流水线,流水线内的多个平行的分区能够并行执行。
10. 如何划分 DAG 的 stage?
对于窄依赖,partition 的转换解决在 stage 中实现计算,不划分(将窄依赖尽量放在在同一个 stage 中,能够实现流水线计算)。
对于宽依赖,因为有 shuffle 的存在,只能在父 RDD 解决实现后,能力开始接下来的计算,也就是说须要要划分 stage。
11. DAG 划分为 Stage 的算法理解吗?
外围算法:回溯算法
从后往前回溯 / 反向解析,遇到窄依赖退出本 Stage,遇见宽依赖进行 Stage 切分。
Spark 内核会从触发 Action 操作的那个 RDD 开始 从后往前推 ,首先会为最初一个 RDD 创立一个 Stage,而后持续倒推,如果发现对某个 RDD 是宽依赖,那么就会将宽依赖的那个 RDD 创立一个新的 Stage,那个 RDD 就是新的 Stage 的最初一个 RDD。
而后顺次类推,持续倒推,依据窄依赖或者宽依赖进行 Stage 的划分,直到所有的 RDD 全副遍历实现为止。
具体划分算法请参考:AMP 实验室发表的论文
\
《Resilient Distributed Datasets: A Fault-Tolerant Abstraction for In-Memory Cluster Computing》
\http://xueshu.baidu.com/usercenter/paper/show?paperid=b33564e60f0a7e7a1889a9da10963461&site=xueshu_se
12. 对于 Spark 中的数据歪斜问题你有什么好的计划?
- 前提是定位数据歪斜,是 OOM 了,还是工作执行迟缓,看日志,看 WebUI
- 解决办法,有多个方面:
- 防止不必要的 shuffle,如应用播送小表的形式,将 reduce-side-join 晋升为 map-side-join
- 分拆产生数据歪斜的记录,分成几个局部进行,而后合并 join 后的后果
- 扭转并行度,可能并行度太少了,导致个别 task 数据压力大
- 两阶段聚合,先部分聚合,再全局聚合
- 自定义 paritioner,扩散 key 的散布,使其更加平均
13. Spark 中的 OOM 问题?
- map 类型的算子执行中内存溢出如 flatMap,mapPatitions
- 起因:map 端过程产生大量对象导致内存溢出:这种溢出的起因是在单个 map 中产生了大量的对象导致的针对这种问题。
- 解决方案:
- 减少堆内内存。
- 在不减少内存的状况下,能够缩小每个 Task 解决数据量,使每个 Task 产生大量的对象时,Executor 的内存也可能装得下。具体做法能够在会产生大量对象的 map 操作之前调用 repartition 办法,分区成更小的块传入 map。
- shuffle 后内存溢出如 join,reduceByKey,repartition。
- shuffle 内存溢出的状况能够说都是 shuffle 后,单个文件过大导致的。在 shuffle 的应用,须要传入一个 partitioner,大部分 Spark 中的 shuffle 操作,默认的 partitioner 都是 HashPatitioner,默认值是父 RDD 中最大的分区数.这个参数 spark.default.parallelism 只对 HashPartitioner 无效.如果是别的 partitioner 导致的 shuffle 内存溢出就须要重写 partitioner 代码了.
- driver 内存溢出
- 用户在 Dirver 端口生成大对象,比方创立了一个大的汇合数据结构。解决方案:将大对象转换成 Executor 端加载,比方调用 sc.textfile 或者评估大对象占用的内存,减少 dirver 端的内存
- 从 Executor 端收集数据(collect)回 Dirver 端,倡议将 driver 端对 collect 回来的数据所作的操作,转换成 executor 端 rdd 操作。
14. Spark 中数据的地位是被谁治理的?
每个数据分片都对应具体物理地位,数据的地位是被 blockManager 治理,无论数据是在磁盘,内存还是 tacyan,都是由 blockManager 治理。
15. Spaek 程序执行,有时候默认为什么会产生很多 task,怎么批改默认 task 执行个数?
- 输出数据有很多 task,尤其是有很多小文件的时候,有多少个输出
block 就会有多少个 task 启动; - spark 中有 partition 的概念,每个 partition 都会对应一个 task,task 越多,在解决大规模数据的时候,就会越有效率。不过 task 并不是越多越好,如果平时测试,或者数据量没有那么大,则没有必要 task 数量太多。
- 参数能够通过 spark_home/conf/spark-default.conf 配置文件设置:
针对 spark sql 的 task 数量:spark.sql.shuffle.partitions=50
非 spark sql 程序设置失效:spark.default.parallelism=10
16. 介绍一下 join 操作优化教训?
这道题常考,这里只是给大家一个思路,简略说下!面试之前还需做更多筹备。
join 其实常见的就分为两类:map-side join 和 reduce-side join。
当大表和小表 join 时,用 map-side join 能显著提高效率。
将多份数据进行关联是数据处理过程中十分广泛的用法,不过在分布式计算零碎中,这个问题往往会变的十分麻烦,因为框架提供的 join 操作个别会将所有数据依据 key 发送到所有的 reduce 分区中去,也就是 shuffle 的过程。造成大量的网络以及磁盘 IO 耗费,运行效率极其低下,这个过程个别被称为 reduce-side-join。
如果其中有张表较小的话,咱们则能够本人实现在 map 端实现数据关联,跳过大量数据进行 shuffle 的过程,运行工夫失去大量缩短,依据不同数据可能会有几倍到数十倍的性能晋升。
在大数据量的状况下,join 是一中十分低廉的操作,须要在 join 之前应尽可能的先放大数据量。
对于放大数据量,有以下几条倡议:
- 若两个 RDD 都有反复的 key,join 操作会使得数据量会急剧的扩充。所有,最好先应用 distinct 或者 combineByKey 操作来缩小 key 空间或者用 cogroup 来解决反复的 key,而不是产生所有的穿插后果。在 combine 时,进行机智的分区,能够防止第二次 shuffle。
- 如果只在一个 RDD 呈现,那你将在无心中失落你的数据。所以应用外连贯会更加平安,这样你就能确保右边的 RDD 或者左边的 RDD 的数据完整性,在 join 之后再过滤数据。
- 如果咱们容易失去 RDD 的能够的有用的子集合,那么咱们能够先用 filter 或者 reduce,如何在再用 join。
17. Spark 与 MapReduce 的 Shuffle 的区别?
- 相同点:都是将 mapper(Spark 里是 ShuffleMapTask)的输入进行 partition,不同的 partition 送到不同的 reducer(Spark 里 reducer 可能是下一个 stage 里的 ShuffleMapTask,也可能是 ResultTask)
- 不同点:
- MapReduce 默认是排序的,spark 默认不排序,除非应用 sortByKey 算子。
- MapReduce 能够划分成 split,map()、spill、merge、shuffle、sort、reduce()等阶段,spark 没有显著的阶段划分,只有不同的 stage 和算子操作。
- MR 落盘,Spark 不落盘,spark 能够解决 mr 落盘导致效率低下的问题。
18. Spark SQL 执行的流程?
这个问题如果深挖还挺简单的,这里简略介绍下总体流程:
- parser:基于 antlr 框架对 sql 解析,生成形象语法树。
- 变量替换:通过正则表达式找出合乎规定的字符串,替换成零碎缓存环境的变量
SQLConf 中的
spark.sql.variable.substitute
,默认是可用的;参考SparkSqlParser
- parser:将 antlr 的 tree 转成 spark catalyst 的 LogicPlan,也就是 未解析的逻辑打算;具体参考
AstBuild
,ParseDriver
- analyzer:通过分析器,联合 catalog,把 logical plan 和理论的数据绑定起来,将 未解析的逻辑打算 生成 逻辑打算;具体参考
QureyExecution
- 缓存替换:通过 CacheManager,替换有雷同后果的 logical plan(逻辑打算)
- logical plan 优化,基于规定的优化;优化规定参考 Optimizer,优化执行器 RuleExecutor
- 生成 spark plan,也就是物理打算;参考
QueryPlanner
和SparkStrategies
- spark plan 筹备阶段
- 结构 RDD 执行,波及 spark 的 wholeStageCodegenExec 机制,基于 janino 框架生成 java 代码并编译
19. Spark SQL 是如何将数据写到 Hive 表的?
- 形式一:是利用 Spark RDD 的 API 将数据写入 hdfs 造成 hdfs 文件,之后再将 hdfs 文件和 hive 表做加载映射。
- 形式二:利用 Spark SQL 将获取的数据 RDD 转换成 DataFrame,再将 DataFrame 写成缓存表,最初利用 Spark SQL 直接插入 hive 表中。而对于利用 Spark SQL 写 hive 表官网有两种常见的 API,第一种是利用 JavaBean 做映射,第二种是利用 StructType 创立 Schema 做映射。
20. 通常来说,Spark 与 MapReduce 相比,Spark 运行效率更高。请阐明效率更高来源于 Spark 内置的哪些机制?
- 基于内存计算,缩小低效的磁盘交互;
- 高效的调度算法,基于 DAG;
- 容错机制 Linage。
重点局部就是 DAG 和 Lingae
21. Hadoop 和 Spark 的相同点和不同点?
Hadoop 底层应用 MapReduce 计算架构,只有 map 和 reduce 两种操作,表达能力比拟欠缺,而且在 MR 过程中会反复的读写 hdfs,造成大量的磁盘 io 读写操作,所以适宜高时延环境下批处理计算的利用;
Spark 是基于内存的分布式计算架构,提供更加丰盛的数据集操作类型,次要分成转化操作和口头操作,包含 map、reduce、filter、flatmap、groupbykey、reducebykey、union 和 join 等,数据分析更加疾速,所以适宜低时延环境下计算的利用;
spark 与 hadoop 最大的区别在于迭代式计算模型。基于 mapreduce 框架的 Hadoop 次要分为 map 和 reduce 两个阶段,两个阶段完了就完结了,所以在一个 job 外面能做的解决很无限;spark 计算模型是基于内存的迭代式计算模型,能够分为 n 个阶段,依据用户编写的 RDD 算子和程序,在解决完一个阶段后能够持续往下解决很多个阶段,而不只是两个阶段。所以 spark 相较于 mapreduce,计算模型更加灵便,能够提供更弱小的性能。
然而 spark 也有劣势,因为 spark 基于内存进行计算,尽管开发容易,然而真正面对大数据的时候,在没有进行调优的状况下,可能会呈现各种各样的问题,比方 OOM 内存溢出等状况,导致 spark 程序可能无奈运行起来,而 mapreduce 尽管运行迟缓,然而至多能够缓缓运行完。
22. Hadoop 和 Spark 应用场景?
Hadoop/MapReduce 和 Spark 最适宜的都是做离线型的数据分析,但 Hadoop 特地适宜是单次剖析的数据量“很大”的情景,而 Spark 则实用于数据量不是很大的情景。
- 个别状况下,对于中小互联网和企业级的大数据利用而言,单次剖析的数量都不会“很大”,因而能够优先思考应用 Spark。
- 业务通常认为 Spark 更实用于机器学习之类的“迭代式”利用,80GB 的压缩数据(解压后超过 200GB),10 个节点的集群规模,跑相似“sum+group-by”的利用,MapReduce 花了 5 分钟,而 spark 只须要 2 分钟。
23. Spark 如何保障宕机迅速复原?
- 适当减少 spark standby master
- 编写 shell 脚本,定期检测 master 状态,呈现宕机后对 master 进行重启操作
24. RDD 长久化原理?
spark 十分重要的一个性能个性就是能够将 RDD 长久化在内存中。
调用 cache()和 persist()办法即可。cache()和 persist()的区别在于,cache()是 persist()的一种简化形式,cache()的底层就是调用 persist()的无参版本 persist(MEMORY_ONLY),将数据长久化到内存中。
如果须要从内存中革除缓存,能够应用 unpersist()办法。RDD 长久化是能够手动抉择不同的策略的。在调用 persist()时传入对应的 StorageLevel 即可。
25. Checkpoint 检查点机制?
利用场景:当 spark 应用程序特地简单,从初始的 RDD 开始到最初整个应用程序实现有很多的步骤,而且整个利用运行工夫特地长,这种状况下就比拟适宜应用 checkpoint 性能。
起因:对于特地简单的 Spark 利用,会呈现某个重复应用的 RDD,即便之前长久化过但因为节点的故障导致数据失落了,没有容错机制,所以须要从新计算一次数据。
Checkpoint 首先会调用 SparkContext 的 setCheckPointDIR()办法,设置一个容错的文件系统的目录,比如说 HDFS;而后对 RDD 调用 checkpoint()办法。之后在 RDD 所处的 job 运行完结之后,会启动一个独自的 job,来将 checkpoint 过的 RDD 数据写入之前设置的文件系统,进行高可用、容错的类长久化操作。
检查点机制是咱们在 spark streaming 中用来保障容错性的次要机制,它能够使 spark streaming 阶段性的把利用数据存储到诸如 HDFS 等牢靠存储系统中,以供复原时应用。具体来说基于以下两个目标服务:
- 管制产生失败时须要重算的状态数。Spark streaming 能够通过转化图的谱系图来重算状态,检查点机制则能够管制须要在转化图中回溯多远。
- 提供驱动器程序容错。如果流计算利用中的驱动器程序解体了,你能够重启驱动器程序并让驱动器程序从检查点复原,这样 spark streaming 就能够读取之前运行的程序处理数据的进度,并从那里持续。
26. Checkpoint 和长久化机制的区别?
最次要的区别在于长久化只是将数据保留在 BlockManager 中,然而 RDD 的 lineage(血缘关系,依赖关系)是不变的。然而 checkpoint 执行完之后,rdd 曾经没有之前所谓的依赖 rdd 了,而只有一个强行为其设置的 checkpointRDD,checkpoint 之后 rdd 的 lineage 就扭转了。
长久化的数据失落的可能性更大,因为节点的故障会导致磁盘、内存的数据失落。然而 checkpoint 的数据通常是保留在高可用的文件系统中,比方 HDFS 中,所以数据失落可能性比拟低
27. Spark Streaming 以及根本工作原理?
Spark streaming 是 spark core API 的一种扩大,能够用于进行大规模、高吞吐量、容错的实时数据流的解决。
它反对从多种数据源读取数据,比方 Kafka、Flume、Twitter 和 TCP Socket,并且可能应用算子比方 map、reduce、join 和 window 等来解决数据,解决后的数据能够保留到文件系统、数据库等存储中。
Spark streaming 外部的根本工作原理是:承受实时输出数据流,而后将数据拆分成 batch,比方每收集一秒的数据封装成一个 batch,而后将每个 batch 交给 spark 的计算引擎进行解决,最初会生产处一个后果数据流,其中的数据也是一个一个的 batch 组成的。
28. DStream 以及根本工作原理?
DStream 是 spark streaming 提供的一种高级形象,代表了一个继续一直的数据流。
DStream 能够通过输出数据源来创立,比方 Kafka、flume 等,也能够通过其余 DStream 的高阶函数来创立,比方 map、reduce、join 和 window 等。
DStream 外部其实一直产生 RDD,每个 RDD 蕴含了一个时间段的数据。
Spark streaming 肯定是有一个输出的 DStream 接收数据,依照工夫划分成一个一个的 batch,并转化为一个 RDD,RDD 的数据是扩散在各个子节点的 partition 中。
29. Spark Streaming 整合 Kafka 的两种模式?
- receiver 形式 :将数据拉取到 executor 中做操作,若数据量大,内存存储不下,能够通过 WAL,设置了本地存储,保证数据不失落,而后应用 Kafka 高级 API 通过 zk 来保护偏移量,保障生产数据。receiver 生产的数据偏移量是在 zk 获取的, 此形式效率低,容易呈现数据失落。
- receiver 形式的容错性:在默认的配置下,这种形式可能会因为底层的失败而失落数据。如果要启用高牢靠机制,让数据零失落,就必须启用 Spark Streaming 的预写日志机制(Write Ahead Log,WAL)。该机制会同步地将接管到的 Kafka 数据写入分布式文件系统(比方 HDFS)上的预写日志中。所以,即便底层节点呈现了失败,也能够应用预写日志中的数据进行复原。
- Kafka 中的 topic 的 partition,与 Spark 中的 RDD 的 partition 是没有关系的。在 1、KafkaUtils.createStream()中,进步 partition 的数量,只会减少 Receiver 形式中读取 partition 的线程的数量。不会减少 Spark 解决数据的并行度。能够创立多个 Kafka 输出 DStream,应用不同的 consumer group 和 topic,来通过多个 receiver 并行接收数据。
- 基于 Direct 形式 : 应用 Kafka 底层 Api,其消费者间接连贯 kafka 的分区上,因为 createDirectStream 创立的 DirectKafkaInputDStream 每个 batch 所对应的 RDD 的分区与 kafka 分区一一对应,然而须要本人保护偏移量,即用即取,不会给内存造成太大的压力,效率高。
- 长处:简化并行读取:如果要读取多个 partition,不须要创立多个输出 DStream 而后对它们进行 union 操作。Spark 会创立跟 Kafka partition 一样多的 RDD partition,并且会并行从 Kafka 中读取数据。所以在 Kafka partition 和 RDD partition 之间,有一个一对一的映射关系。
- 高性能:如果要保障零数据失落,在基于 receiver 的形式中,须要开启 WAL 机制。这种形式其实效率低下,因为数据实际上被复制了两份,Kafka 本人自身就有高牢靠的机制,会对数据复制一份,而这里又会复制一份到 WAL 中。而基于 direct 的形式,不依赖 Receiver,不须要开启 WAL 机制,只有 Kafka 中作了数据的复制,那么就能够通过 Kafka 的正本进行复原。
- receiver 与和 direct 的比拟:
- 基于 receiver 的形式,是应用 Kafka 的高阶 API 来在 ZooKeeper 中保留生产过的 offset 的。这是生产 Kafka 数据的传统形式。这种形式配合着 WAL 机制能够保证数据零失落的高可靠性,然而却无奈保证数据被解决一次且仅一次,可能会解决两次。因为 Spark 和 ZooKeeper 之间可能是不同步的。
- 基于 direct 的形式,应用 Kafka 的低阶 API,Spark Streaming 本人就负责追踪生产的 offset,并保留在 checkpoint 中。Spark 本人肯定是同步的,因而能够保证数据是生产一次且仅生产一次。
- Receiver 形式是通过 zookeeper 来连贯 kafka 队列,Direct 形式是间接连贯到 kafka 的节点上获取数据。
30. Spark 主备切换机制原理晓得吗?
Master 实际上能够配置两个,Spark 原生的 standalone 模式是反对 Master 主备切换的。当 Active Master 节点挂掉当前,咱们能够将 Standby Master 切换为 Active Master。
Spark Master 主备切换能够基于两种机制,一种是基于文件系统的,一种是基于 ZooKeeper 的。
基于文件系统的主备切换机制,须要在 Active Master 挂掉之后手动切换到 Standby Master 上;
而基于 Zookeeper 的主备切换机制,能够实现主动切换 Master。
31. Spark 解决了 Hadoop 的哪些问题?
-
MR:抽象层次低,须要应用手工代码来实现程序编写,应用上难以上手;
Spark:Spark 采纳 RDD 计算模型,简略容易上手。
-
MR:只提供 map 和 reduce 两个操作,表达能力欠缺;
Spark:Spark 采纳更加丰盛的算子模型,包含 map、flatmap、groupbykey、reducebykey 等;
-
MR:一个 job 只能蕴含 map 和 reduce 两个阶段,简单的工作须要蕴含很多个 job,这些 job 之间的治理以来须要开发者本人进行治理;
Spark:Spark 中一个 job 能够蕴含多个转换操作,在调度时能够生成多个 stage,而且如果多个 map 操作的分区不变,是能够放在同一个 task 外面去执行;
-
MR:两头后果寄存在 hdfs 中;
Spark:Spark 的两头后果个别存在内存中,只有当内存不够了,才会存入本地磁盘,而不是 hdfs;
-
MR:只有等到所有的 map task 执行结束后能力执行 reduce task;
Spark:Spark 中分区雷同的转换形成流水线在一个 task 中执行,分区不同的须要进行 shuffle 操作,被划分成不同的 stage 须要期待后面的 stage 执行完能力执行。
-
MR:只适宜 batch 批处理,时延高,对于交互式解决和实时处理反对不够;
Spark:Spark streaming 能够将流拆成工夫距离的 batch 进行解决,实时计算。
32. 数据歪斜的产生和解决办法?
数据歪斜认为着某一个或者某几个 partition 的数据特地大,导致这几个 partition 上的计算须要消耗相当长的工夫。
在 spark 中同一个应用程序划分成多个 stage,这些 stage 之间是串行执行的,而一个 stage 外面的多个 task 是能够并行执行,task 数目由 partition 数目决定,如果一个 partition 的数目特地大,那么导致这个 task 执行工夫很长,导致接下来的 stage 无奈执行,从而导致整个 job 执行变慢。
防止数据歪斜,个别是要选用适合的 key,或者本人定义相干的 partitioner,通过加盐或者哈希值来拆分这些 key,从而将这些数据扩散到不同的 partition 去执行。
如下算子会导致 shuffle 操作,是导致数据歪斜可能产生的关键点所在:groupByKey;reduceByKey;aggregaByKey;join;cogroup;
33. 你用 Spark Sql 解决的时候,处理过程中用的 DataFrame 还是间接写的 Sql?为什么?
这个问题的主旨是问你 spark sql 中 dataframe 和 sql 的区别,从执行原理、操作不便水平和自定义水平来剖析
这个问题。
34. Spark Master HA 主从切换过程不会影响到集群已有作业的运行,为什么?
不会的。
因为程序在运行之前,曾经申请过资源了,driver 和 Executors 通信,不须要和 master 进行通信的。
35. Spark Master 应用 Zookeeper 进行 HA,有哪些源数据保留到 Zookeeper 外面?
spark 通过这个参数 spark.deploy.zookeeper.dir 指定 master 元数据在 zookeeper 中保留的地位,包含 Worker,Driver 和 Application 以及 Executors。standby 节点要从 zk 中,取得元数据信息,复原集群运行状态,能力对外持续提供服务,作业提交资源申请等,在复原前是不能承受申请的。
注:Master 切换须要留神 2 点:
1、在 Master 切换的过程中,所有的曾经在运行的程序皆失常运行!
因为 Spark Application 在运行前就曾经通过 Cluster Manager 取得了计算资源,所以在运行时 Job 自身的
调度和解决和 Master 是没有任何关系。
2、在 Master 的切换过程中惟一的影响是不能提交新的 Job:一方面不可能提交新的应用程序给集群,
因为只有 Active Master 能力承受新的程序的提交申请;另外一方面,曾经运行的程序中也不可能因
Action 操作触发新的 Job 的提交申请。
36. 如何实现 Spark Streaming 读取 Flume 中的数据?
能够这样说:
- 后期通过技术调研,查看官网相干材料,发现 sparkStreaming 整合 flume 有 2 种模式,一种是拉模式,一种是推模式,而后在简略的聊聊这 2 种模式的特点,以及如何部署实现,须要做哪些事件,最初比照两种模式的特点,抉择那种模式更好。
- 推模式:Flume 将数据 Push 推给 Spark Streaming
- 拉模式:Spark Streaming 从 flume 中 Poll 拉取数据
37. 在理论开发的时候是如何保证数据不失落的?
能够这样说:
- flume 那边采纳的 channel 是将数据落地到磁盘中,保障数据源端安全性(能够在补充一下,flume 在这里的 channel 能够设置为 memory 内存中,进步数据接管解决的效率,然而因为数据在内存中,平安机制保障不了,故抉择 channel 为磁盘存储。整个流程运行有一点的提早性)
- sparkStreaming 通过拉模式整合的时候,应用了 FlumeUtils 这样一个类,该类是须要依赖一个额定的 jar 包(spark-streaming-flume_2.10)
-
要想保证数据不失落,数据的准确性,能够在构建 StreamingConext 的时候,利用 StreamingContext.getOrCreate(checkpoint, creatingFunc: () => StreamingContext)来创立一个 StreamingContext, 应用 StreamingContext.getOrCreate 来创立 StreamingContext 对象,传入的第一个参数是 checkpoint 的寄存目录,第二参数是生成 StreamingContext 对象的用户自定义函数。如果 checkpoint 的寄存目录存在,则从这个目录中生成 StreamingContext 对象;如果不存在,才会调用第二个函数来生成新的 StreamingContext 对象。在 creatingFunc 函数中,除了生成一个新的 StreamingContext 操作,还须要实现各种操作,而后调用 ssc.checkpoint(checkpointDirectory)来初始化 checkpoint 性能,最初再返回 StreamingContext 对象。
这样,在 StreamingContext.getOrCreate 之后,就能够间接调用 start()函数来启动(或者是从中断点持续运行)流式利用了。如果有其余在启动或持续运行都要做的工作,能够在 start()调用前执行。
38. RDD 有哪些缺点?
- 不反对细粒度的写和更新操作,Spark 写数据是粗粒度的,所谓粗粒度,就是批量写入数据,目标是为了提高效率。然而 Spark 读数据是细粒度的,也就是说能够一条条的读。
- 不反对增量迭代计算,如果对 Flink 相熟,能够说下 Flink 反对增量迭代计算。
Kafka
1. 为什么要应用 kafka?
- 缓冲和削峰:上游数据时有突发流量,上游可能扛不住,或者上游没有足够多的机器来保障冗余,kafka 在两头能够起到一个缓冲的作用,把音讯暂存在 kafka 中,上游服务就能够依照本人的节奏进行缓缓解决。
- 解耦和扩展性:我的项目开始的时候,并不能确定具体需要。音讯队列能够作为一个接口层,解耦重要的业务流程。只须要恪守约定,针对数据编程即可获取扩大能力。
- 冗余:能够采纳一对多的形式,一个生产者公布音讯,能够被多个订阅 topic 的服务生产到,供多个毫无关联的业务应用。
- 健壮性:音讯队列能够沉积申请,所以生产端业务即便短时间死掉,也不会影响次要业务的失常进行。
- 异步通信:很多时候,用户不想也不须要立刻解决音讯。音讯队列提供了异步解决机制,容许用户把一个音讯放入队列,但并不立刻解决它。想向队列中放入多少音讯就放多少,而后在须要的时候再去解决它们。
2. Kafka 生产过的音讯如何再生产?
kafka 生产音讯的 offset 是定义在 zookeeper 中的,如果想反复生产 kafka 的音讯,能够在 redis 中本人记录 offset 的 checkpoint 点(n 个),当想反复生产音讯时,通过读取 redis 中的 checkpoint 点进行 zookeeper 的 offset 重设,这样就能够达到反复生产音讯的目标了
3. kafka 的数据是放在磁盘上还是内存上,为什么速度会快?
kafka 应用的是磁盘存储。
速度快是因为:
- 程序写入:因为硬盘是机械构造,每次读写都会寻址 -> 写入,其中寻址是一个“机械动作”,它是耗时的。所以硬盘“厌恶”随机 I /O,喜爱程序 I /O。为了进步读写硬盘的速度,Kafka 就是应用程序 I /O。
- Memory Mapped Files(内存映射文件):64 位操作系统中个别能够示意 20G 的数据文件,它的工作原理是间接利用操作系统的 Page 来实现文件到物理内存的间接映射。实现映射之后你对物理内存的操作会被同步到硬盘上。
- Kafka 高效文件存储设计:Kafka 把 topic 中一个 parition 大文件分成多个小文件段,通过多个小文件段,就容易定期革除或删除曾经生产完文件,缩小磁盘占用。通过索引信息能够疾速定位
message 和确定 response 的 大 小。通过 index 元数据全副映射到 memory(内存映射文件),
能够防止 segment file 的 IO 磁盘操作。通过索引文件稠密存储,能够大幅升高 index 文件元数据占用空间大小。
注:
- Kafka 解决查问效率的伎俩之一是将数据文件分段,比方有 100 条 Message,它们的 offset 是从 0 到 99。假如将数据文件分成 5 段,第一段为 0 -19,第二段为 20-39,以此类推,每段放在一个独自的数据文件外面,数据文件以该段中 小的 offset 命名。这样在查找指定 offset 的
Message 的时候,用二分查找就能够定位到该 Message 在哪个段中。 - 为数据文件建 索引数据文件分段 使得能够在一个较小的数据文件中查找对应 offset 的 Message 了,然而这仍然须要程序扫描能力找到对应 offset 的 Message。
为了进一步提高查找的效率,Kafka 为每个分段后的数据文件建设了索引文件,文件名与数据文件的名字是一样的,只是文件扩大名为.index。
4. Kafka 数据怎么保障不失落?
分三个点说,一个是生产者端,一个消费者端,一个 broker 端。
- 生产者数据的不失落
kafka 的 ack 机制:在 kafka 发送数据的时候,每次发送音讯都会有一个确认反馈机制,确保音讯失常的可能被收到,其中状态有 0,1,-1。
如果是同步模式:
ack 设置为 0,危险很大,个别不倡议设置为 0。即便设置为 1,也会随着 leader 宕机失落数据。所以如果要严格保障生产端数据不失落,可设置为 -1。
如果是异步模式:
也会思考 ack 的状态,除此之外,异步模式下的有个 buffer,通过 buffer 来进行控制数据的发送,有两个值来进行管制,工夫阈值与音讯的数量阈值,如果 buffer 满了数据还没有发送进来,有个选项是配置是否立刻清空 buffer。能够设置为 -1,永恒阻塞,也就数据不再生产。异步模式下,即便设置为 -1。也可能因为程序员的不迷信操作,操作数据失落,比方 kill -9,但这是特地的例外情况。
注:
ack=0:producer 不期待 broker 同步实现的确认,持续发送下一条 (批) 信息。
ack=1(默认):producer 要期待 leader 胜利收到数据并失去确认,才发送下一条 message。
ack=-1:producer 失去 follwer 确认,才发送下一条数据。
- 消费者数据的不失落
通过 offset commit 来保证数据的不失落,kafka 本人记录了每次生产的 offset 数值,下次持续生产的时候,会接着上次的 offset 进行生产。
而 offset 的信息在 kafka0.8 版本之前保留在 zookeeper 中,在 0.8 版本之后保留到 topic 中,即便消费者在运行过程中挂掉了,再次启动的时候会找到 offset 的值,找到之前生产音讯的地位,接着生产,因为 offset 的信息写入的时候并不是每条音讯生产实现后都写入的,所以这种状况有可能会造成反复生产,然而不会失落音讯。
惟一例外的状况是,咱们在程序中给本来做不同性能的两个 consumer 组设置
KafkaSpoutConfig.bulider.setGroupid 的时候设置成了一样的 groupid,这种状况会导致这两个组共享同一份数据,就会产生组 A 生产 partition1,partition2 中的音讯,组 B 生产 partition3 的音讯,这样每个组生产的音讯都会失落,都是不残缺的。为了保障每个组都独享一份音讯数据,groupid 肯定不要反复才行。
- kafka 集群中的 broker 的数据不失落
每个 broker 中的 partition 咱们个别都会设置有 replication(正本)的个数,生产者写入的时候首先依据散发策略(有 partition 按 partition,有 key 按 key,都没有轮询)写入到 leader 中,follower(正本)再跟 leader 同步数据,这样有了备份,也能够保障音讯数据的不失落。
5. 采集数据为什么抉择 kafka?
采集层 次要能够应用 Flume, Kafka 等技术。
Flume:Flume 是管道流形式,提供了很多的默认实现,让用户通过参数部署,及扩大 API.
Kafka:Kafka 是一个可长久化的分布式的音讯队列。Kafka 是一个十分通用的零碎。你能够有许多生产者和很多的消费者共享多个主题 Topics。
相比之下,Flume 是一个专用工具被设计为旨在往 HDFS,HBase 发送数据。它对 HDFS 有非凡的优化,并且集成了 Hadoop 的平安个性。
所以,Cloudera 倡议如果数据被多个零碎生产的话,应用 kafka;如果数据被设计给 Hadoop 应用,应用 Flume。
6. kafka 重启是否会导致数据失落?
- kafka 是将数据写到磁盘的,个别数据不会失落。
- 然而在重启 kafka 过程中,如果有消费者生产音讯,那么 kafka 如果来不及提交 offset,可能会造成数据的不精确(失落或者反复生产)。
7. kafka 宕机了如何解决?
- 先思考业务是否受到影响
kafka 宕机了,首先咱们思考的问题应该是所提供的服务是否因为宕机的机器而受到影响,如果服务提供没问题,如果实现做好了集群的容灾机制,那么这块就不必放心了。
- 节点排错与复原
想要复原集群的节点,次要的步骤就是通过日志剖析来查看节点宕机的起因,从而解决,从新复原节点。
8. 为什么 Kafka 不反对读写拆散?
在 Kafka 中,生产者写入音讯、消费者读取音讯的操作都是与 leader 正本进行交互的,从 而实现的是一种 主写主读 的生产生产模型。
Kafka 并不反对 主写从读,因为主写从读有 2 个很显著的毛病:
- 数据一致性问题:数据从主节点转到从节点必然会有一个延时的工夫窗口,这个工夫 窗口会导致主从节点之间的数据不统一。某一时刻,在主节点和从节点中 A 数据的值都为 X,之后将主节点中 A 的值批改为 Y,那么在这个变更告诉到从节点之前,利用读取从节点中的 A 数据的值并不为最新的 Y,由此便产生了数据不统一的问题。
- 延时问题:相似 Redis 这种组件,数据从写入主节点到同步至从节点中的过程须要经验 网络→主节点内存→网络→从节点内存 这几个阶段,整个过程会消耗肯定的工夫。而在 Kafka 中,主从同步会比 Redis 更加耗时,它须要经验 网络→主节点内存→主节点磁盘→网络→从节 点内存→从节点磁盘 这几个阶段。对延时敏感的利用而言,主写从读的性能并不太实用。
而 kafka 的 主写主读 的长处就很多了:
- 能够简化代码的实现逻辑,缩小出错的可能;
- 将负载粒度细化均摊,与主写从读相比,不仅负载效力更好,而且对用户可控;
- 没有延时的影响;
- 在正本稳固的状况下,不会呈现数据不统一的状况。
9. kafka 数据分区和消费者的关系?
每个分区只能由同一个生产组内的一个消费者 (consumer) 来生产,能够由不同的生产组的消费者来生产,同组的消费者则起到并发的成果。
10. kafka 的数据 offset 读取流程
- 连贯 ZK 集群,从 ZK 中拿到对应 topic 的 partition 信息和 partition 的 Leader 的相干信息
- 连贯到对应 Leader 对应的 broker
- consumer 将⾃自⼰己保留的 offset 发送给 Leader
- Leader 依据 offset 等信息定位到 segment(索引⽂文件和⽇日志⽂文件)
- 依据索引⽂文件中的内容,定位到⽇日志⽂文件中该偏移量量对应的开始地位读取相应⻓长度的数据并返回给 consumer
11. kafka 外部如何保障程序,联合内部组件如何保障消费者的程序?
kafka 只能保障 partition 内是有序的,然而 partition 间的有序是没方法的。爱奇艺的搜寻架构,是从业务上把须要有序的打到同⼀个 partition。
12. Kafka 音讯数据积压,Kafka 生产能力有余怎么解决?
- 如果是 Kafka 生产能力有余,则能够思考减少 Topic 的分区数,并且同时晋升生产组的消费者数量,消费者数 = 分区数。(两者缺一不可)
- 如果是上游的数据处理不及时:进步每批次拉取的数量。批次拉取数据过少(拉取数据 / 解决工夫 < 生产速度),使解决的数据小于生产的数据,也会造成数据积压。
13. Kafka 单条日志传输大小
kafka 对于音讯体的大小默认为单条最大值是 1M 然而在咱们利用场景中, 经常会呈现一条音讯大于 1M,如果不对 kafka 进行配置。则会呈现生产者无奈将音讯推送到 kafka 或消费者无奈去生产 kafka 外面的数据, 这时咱们就要对 kafka 进行以下配置:server.properties
replica.fetch.max.bytes: 1048576 broker 可复制的音讯的最大字节数, 默认为 1M
message.max.bytes: 1000012 kafka 会接管单个音讯 size 的最大限度,默认为 1M 左右
留神:message.max.bytes 必须小于等于 replica.fetch.max.bytes,否则就会导致 replica 之间数据同步失败。
Hbase
1. Hbase 是怎么写数据的?
Client 写入 -> 存入 MemStore,始终到 MemStore 满 -> Flush 成一个 StoreFile,直至增长到肯定阈值 -> 触发 Compact 合并操作 -> 多个 StoreFile 合并成一个 StoreFile,同时进行版本合并和数据删除 -> 当 StoreFiles Compact 后,逐步形成越来越大的 StoreFile -> 单个 StoreFile 大小超过肯定阈值后(默认 10G),触发 Split 操作,把以后 Region Split 成 2 个 Region,Region 会下线,新 Split 出的 2 个孩子 Region 会被 HMaster 调配到相应的 HRegionServer 上,使得原先 1 个 Region 的压力得以分流到 2 个 Region 上
由此过程可知,HBase 只是减少数据,没有更新和删除操作,用户的更新和删除都是逻辑层面的,在物理层面,更新只是追加操作,删除只是标记操作。
用户写操作只须要进入到内存即可立刻返回,从而保障 I / O 高性能。
2. HDFS 和 HBase 各自应用场景
首先一点须要明确:Hbase 是基于 HDFS 来存储的。
HDFS:
- 一次性写入,屡次读取。
- 保证数据的一致性。
- 次要是能够部署在许多便宜机器中,通过多正本进步可靠性,提供了容错和复原机制。
HBase:
- 霎时写入量很大,数据库不好撑持或须要很高老本撑持的场景。
- 数据须要短暂保留,且量会长久增长到比拟大的场景。
- HBase 不实用与有 join,多级索引,表关系简单的数据模型。
- 大数据量(100s TB 级数据)且有疾速随机拜访的需要。如:淘宝的交易历史记录。数据量微小无容置疑,面向普通用户的申请必然要即时响应。
- 业务场景简略,不须要关系数据库中很多个性(例如穿插列、穿插表,事务,连贯等等)。
3. Hbase 的存储构造
Hbase 中的每张表都通过行键 (rowkey) 依照肯定的范畴被宰割成多个子表(HRegion),默认一个 HRegion 超过 256M 就要被宰割成两个,由 HRegionServer 治理,治理哪些 HRegion 由 Hmaster 调配。HRegion 存取一个子表时,会创立一个 HRegion 对象,而后对表的每个列族(Column Family)创立一个 store 实例,每个 store 都会有 0 个或多个 StoreFile 与之对应,每个 StoreFile 都会对应一个 HFile,HFile 就是理论的存储文件,一个 HRegion 还领有一个 MemStore 实例。
4. 热点景象(数据歪斜)怎么产生的,以及解决办法有哪些
热点景象:
某个小的时段内,对 HBase 的读写申请集中到极少数的 Region 上,导致这些 region 所在的 RegionServer 解决申请量骤增,负载量显著偏大,而其余的 RgionServer 显著闲暇。
热点景象呈现的起因:
HBase 中的行是依照 rowkey 的字典程序排序的,这种设计优化了 scan 操作,能够将相干的行以及会被一起读取的行存取在邻近地位,便于 scan。然而蹩脚的 rowkey 设计是热点的源头。
热点产生在大量的 client 间接拜访集群的一个或极少数个节点(拜访可能是读,写或者其余操作)。大量拜访会使热点 region 所在的单个机器超出本身承受能力,引起性能降落甚至 region 不可用,这也会影响同一个 RegionServer 上的其余 region,因为主机无奈服务其余 region 的申请。
热点景象解决办法:
为了防止写热点,设计 rowkey 使得不同行在同一个 region,然而在更多数据状况下,数据应该被写入集群的多个 region,而不是一个。常见的办法有以下这些:
- 加盐:在 rowkey 的后面减少随机数,使得它和之前的 rowkey 的结尾不同。调配的前缀品种数量应该和你想应用数据扩散到不同的 region 的数量统一。加盐之后的 rowkey 就会依据随机生成的前缀扩散到各个 region 上,以防止热点。
- 哈希:哈希能够使负载扩散到整个集群,然而读却是能够预测的。应用确定的哈希能够让客户端重构残缺的 rowkey,能够应用 get 操作精确获取某一个行数据
- 反转:第三种避免热点的办法时反转固定长度或者数字格局的 rowkey。这样能够使得 rowkey 中常常扭转的局部(最没有意义的局部)放在后面。这样能够无效的随机 rowkey,然而就义了 rowkey 的有序性。反转 rowkey 的例子以手机号为 rowkey,能够将手机号反转后的字符串作为 rowkey,这样的就防止了以手机号那样比拟固定结尾导致热点问题
-
工夫戳反转 :一个常见的数据处理问题是疾速获取数据的最近版本,应用反转的工夫戳作为 rowkey 的一部分对这个问题非常有用,能够用 Long.Max_Value – timestamp 追加到 key 的开端,例如 key,[key] 的最新值能够通过 scan [key]取得 [key] 的第一条记录,因为 HBase 中 rowkey 是有序的,第一条记录是最初录入的数据。
- 比方须要保留一个用户的操作记录,依照操作工夫倒序排序,在设计 rowkey 的时候,能够这样设计[userId 反转]
[Long.Max_Value – timestamp],在查问用户的所有操作记录数据的时候,间接指定反转后的 userId,startRow 是 userId 反转,stopRow 是 userId 反转 - 如果须要查问某段时间的操作记录,startRow 是 user 反转,stopRow 是 userId 反转
- 比方须要保留一个用户的操作记录,依照操作工夫倒序排序,在设计 rowkey 的时候,能够这样设计[userId 反转]
- HBase 建表预分区:创立 HBase 表时,就事后依据可能的 RowKey 划分出多个 region 而不是默认的一个,从而能够将后续的读写操作负载平衡到不同的 region 上,防止热点景象。
5. HBase 的 rowkey 设计准则
长度准则:100 字节以内,8 的倍数最好,可能的状况下越短越好。因为 HFile 是依照 keyvalue 存储的,过长的 rowkey 会影响存储效率;其次,过长的 rowkey 在 memstore 中较大,影响缓冲成果,升高检索效率。最初,操作系统大多为 64 位,8 的倍数,充分利用操作系统的最佳性能。
散列准则:高位散列,低位工夫字段。防止热点问题。
惟一准则:分利用这个排序的特点,将常常读取的数据存储到一块,将最近可能会被拜访 的数据放到一块。
6. HBase 的列簇设计
准则:在正当范畴内能尽量少的缩小列簇就尽量减少列簇,因为列簇是共享 region 的,每个列簇数据相差太大导致查问效率低下。
最优:将所有相关性很强的 key-value 都放在同一个列簇下,这样既能做到查问效率最高,也能放弃尽可能少的拜访不同的磁盘文件。以用户信息为例,能够将必须的根本信息寄存在一个列族,而一些附加的额定信息能够放在另一列族。
7. HBase 中 compact 用处是什么,什么时候触发,分为哪两种,有什么区别
在 hbase 中每当有 memstore 数据 flush 到磁盘之后,就造成一个 storefile,当 storeFile 的数量达到肯定水平后,就须要将 storefile 文件来进行 compaction 操作。
Compact 的作用:
- 合并文件
- 革除过期,多余版本的数据
- 进步读写数据的效率
4
HBase 中实现了两种 compaction 的形式:minor and major. 这两种 compaction 形式的
区别是: - Minor 操作只用来做局部文件的合并操作以及包含 minVersion=0 并且设置 ttl 的过
期版本清理,不做任何删除数据、多版本数据的清理工作。 - Major 操作是对 Region 下的 HStore 下的所有 StoreFile 执行合并操作,最终的后果
是整顿合并出一个文件。
Flink
1. 简略介绍一下 Flink
Flink 是一个面向 流解决 和批处理 的分布式数据计算引擎,可能基于同一个 Flink 运行,能够提供流解决和批处理两种类型的性能。在 Flink 的世界观中,一切都是由流组成的,离线数据是有界的流;实时数据是一个没有界线的流:这就是所谓的有界流和无界流。
2. Flink 的运行必须依赖 Hadoop 组件吗
Flink 能够齐全独立于 Hadoop,在不依赖 Hadoop 组件下运行。然而做为大数据的基础设施,Hadoop 体系是任何大数据框架都绕不过来的。Flink 能够集成泛滥 Hadooop 组件,例如 Yarn、Hbase、HDFS 等等。例如,Flink 能够和 Yarn 集成做资源调度,也能够读写 HDFS,或者利用 HDFS 做检查点。
3. Flink 集群运行时角色
Flink 运行时由两种类型的过程组成:一个 JobManager 和一个或者多个 TaskManager。
Client 不是运行时和程序执行的一部分,而是用于筹备数据流并将其发送给 JobManager。之后,客户端能够断开连接(拆散模式),或放弃连贯来接管过程报告(附加模式)。客户端能够作为触发执行 Java/Scala 程序的一部分运行,也能够在命令行过程 ./bin/flink run ...
中运行。
能够通过多种形式启动 JobManager 和 TaskManager:间接在机器上作为 standalone 集群启动、在容器中启动、或者通过 YARN 等资源框架治理并启动。TaskManager 连贯到 JobManagers,发表本人可用,并被调配工作。
JobManager:
JobManager 具备许多与协调 Flink 应用程序的分布式执行无关的职责:它决定何时调度下一个 task(或一组 task)、对实现的 task 或执行失败做出反馈、协调 checkpoint、并且协调从失败中复原等等。这个过程由三个不同的组件组成:
- ResourceManager
ResourceManager 负责 Flink 集群中的资源提供、回收、调配,治理 task slots。
- Dispatcher
Dispatcher 提供了一个 REST 接口,用来提交 Flink 应用程序执行,并为每个提交的作业启动一个新的 JobMaster。它还运行 Flink WebUI 用来提供作业执行信息。
- JobMaster
JobMaster 负责管理单个 JobGraph 的执行。Flink 集群中能够同时运行多个作业,每个作业都有本人的 JobMaster。
TaskManagers:
TaskManager(也称为 worker)执行作业流的 task,并且缓存和替换数据流。
必须始终至多有一个 TaskManager。在 TaskManager 中资源调度的最小单位是 task slot。TaskManager 中 task slot 的数量示意并发解决 task 的数量。请留神一个 task slot 中能够执行多个算子。
4. Flink 相比 Spark Streaming 有什么区别
1. 架构模型
Spark Streaming 在运行时的次要角色包含:Master、Worker、Driver、Executor,Flink 在运行时次要蕴含:Jobmanager、Taskmanager 和 Slot。
2. 任务调度
Spark Streaming 连续不断的生成渺小的数据批次,构建有向无环图 DAG,Spark Streaming 会顺次创立 DStreamGraph、JobGenerator、JobScheduler。
Flink 依据用户提交的代码生成 StreamGraph,通过优化生成 JobGraph,而后提交给 JobManager 进行解决,JobManager 会依据 JobGraph 生成 ExecutionGraph,ExecutionGraph 是 Flink 调度最外围的数据结构,JobManager 依据 ExecutionGraph 对 Job 进行调度。
3. 工夫机制
Spark Streaming 反对的工夫机制无限,只反对解决工夫。Flink 反对了流处理程序在工夫上的三个定义:解决工夫、事件工夫、注入工夫。同时也反对 watermark 机制来解决滞后数据。
4. 容错机制
对于 Spark Streaming 工作,咱们能够设置 checkpoint,而后如果产生故障并重启,咱们能够从上次 checkpoint 之处复原,然而这个行为只能使得数据不失落,可能会反复解决,不能做到恰一次解决语义。
Flink 则应用两阶段提交协定来解决这个问题。
5. 介绍下 Flink 的容错机制(checkpoint)
Checkpoint 机制是 Flink 可靠性的基石,能够保障 Flink 集群在某个算子因为某些起因 (如 异样退出) 呈现故障时,可能将整个利用流图的状态复原到故障之前的某一状态,保障利用流图状态的一致性。Flink 的 Checkpoint 机制原理来自“Chandy-Lamport algorithm”算法。
每个须要 Checkpoint 的利用在启动时,Flink 的 JobManager 为其创立一个 CheckpointCoordinator(检查点协调器),CheckpointCoordinator 全权负责本利用的快照制作。
CheckpointCoordinator(检查点协调器),CheckpointCoordinator 全权负责本利用的快照制作。
1) CheckpointCoordinator(检查点协调器) 周期性的向该流利用的所有 source 算子发送 barrier(屏障)。
2) 当某个 source 算子收到一个 barrier 时,便暂停数据处理过程,而后将本人的以后状态制作成快照,并保留到指定的长久化存储中,最初向 CheckpointCoordinator 报告本人快照制作状况,同时向本身所有上游算子播送该 barrier,复原数据处理
3) 上游算子收到 barrier 之后,会暂停本人的数据处理过程,而后将本身的相干状态制作成快照,并保留到指定的长久化存储中,最初向 CheckpointCoordinator 报告本身快照状况,同时向本身所有上游算子播送该 barrier,复原数据处理。
4) 每个算子依照步骤 3 一直制作快照并向上游播送,直到最初 barrier 传递到 sink 算子,快照制作实现。
5) 当 CheckpointCoordinator 收到所有算子的报告之后,认为该周期的快照制作胜利; 否则,如果在规定的工夫内没有收到所有算子的报告,则认为本周期快照制作失败。
文章举荐:
Flink 可靠性的基石 -checkpoint 机制具体解析
6. Flink checkpoint 与 Spark Streaming 的有什么区别或劣势吗
spark streaming 的 checkpoint 仅仅是针对 driver 的故障复原做了数据和元数据的 checkpoint。而 flink 的 checkpoint 机制 要简单了很多,它采纳的是轻量级的分布式快照,实现了每个算子的快照,及流动中的数据的快照。
7. Flink 是如何保障 Exactly-once 语义的
Flink 通过实现 两阶段提交 和状态保留来实现端到端的一致性语义。分为以下几个步骤:
开始事务(beginTransaction)创立一个长期文件夹,来写把数据写入到这个文件夹外面
预提交(preCommit)将内存中缓存的数据写入文件并敞开
正式提交(commit)将之前写完的临时文件放入目标目录下。这代表着最终的数据会有一些提早
抛弃(abort)抛弃临时文件
若失败产生在预提交胜利后,正式提交前。能够依据状态来提交预提交的数据,也可删除预提交的数据。
两阶段提交协定详解:八张图搞懂 Flink 的 Exactly-once
8. 如果上级存储不反对事务,Flink 怎么保障 exactly-once
端到端的 exactly-once 对 sink 要求比拟高,具体实现次要有幂等写入和事务性写入两种形式。
幂等写入的场景依赖于业务逻辑,更常见的是用事务性写入。而事务性写入又有预写日志(WAL)和两阶段提交(2PC)两种形式。
如果内部零碎不反对事务,那么能够用预写日志的形式,把后果数据先当成状态保留,而后在收到 checkpoint 实现的告诉时,一次性写入 sink 零碎。
9. Flink 罕用的算子有哪些
分两局部:
- 数据读取,这是 Flink 流计算利用的终点,罕用算子有:
- 从内存读:fromElements
- 从文件读:readTextFile
- Socket 接入:socketTextStream
- 自定义读取:createInput
- 解决数据的算子,罕用的算子包含:Map(单输出单输入)、FlatMap(单输出、多输入)、Filter(过滤)、KeyBy(分组)、Reduce(聚合)、Window(窗口)、Connect(连贯)、Split(宰割)等。
举荐浏览:一文学完 Flink 流计算罕用算子(Flink 算子大全)
10. Flink 工作延时高,如何动手
在 Flink 的后台任务治理中,咱们能够看到 Flink 的哪个算子和 task 呈现了反压。最次要的伎俩是资源调优和算子调优。资源调优即是对作业中的 Operator 的并发数(parallelism)、CPU(core)、堆内存(heap_memory)等参数进行调优。作业参数调优包含:并行度的设置,State 的设置,checkpoint 的设置。
11. Flink 是如何解决反压的
Flink 外部是基于 producer-consumer 模型来进行消息传递的,Flink 的反压设计也是基于这个模型。Flink 应用了高效有界的分布式阻塞队列,就像 Java 通用的阻塞队列(BlockingQueue)一样。上游消费者生产变慢,上游就会受到阻塞。
12. 如何排查生产环境中的反压问题
1. 反压呈现的场景
反压经常出现在促销、热门流动等场景。短时间内流量陡增造成数据的沉积或者生产速度变慢。
它们有一个独特的特点:数据的生产速度小于数据的生产速度。
2. 反压监控办法
通过 Flink Web UI 发现反压问题。
Flink 的 TaskManager 会每隔 50 ms 触发一次反压状态监测,共监测 100 次,并将计算结果反馈给 JobManager,最初由 JobManager 进行计算反压的比例,而后进行展现。
这个比例展现逻辑如下:
OK: 0 <= Ratio <= 0.10,示意状态良好正;
LOW: 0.10 < Ratio <= 0.5,示意有待察看;
HIGH: 0.5 < Ratio <= 1,示意要解决了(减少并行度 /subTask/ 查看是否有数据歪斜 / 减少内存)。
0.01,代表 100 次中有一次阻塞在外部调用。
3. flink 反压的实现形式
Flink 工作的组成由根本的“流”和“算子”形成,“流”中的数据在“算子”间进行计算和转换时,会被放入分布式的阻塞队列中。当消费者的阻塞队列满时,则会升高生产者的数据生产速度
4. 反压问题定位和解决
Flink 会因为数据沉积和处理速度变慢导致 checkpoint 超时,而 checkpoint 是 Flink 保证数据一致性的关键所在,最终会导致数据的不统一产生。
数据歪斜:能够在 Flink 的后盾治理页面看到每个 Task 解决数据的大小。当数据歪斜呈现时,通常是简略地应用相似 KeyBy 等分组聚合函数导致的,须要用户将热点 Key 进行预处理,升高或者打消热点 Key 的影。
GC:不合理的设置 TaskManager 的垃圾回收参数会导致重大的 GC 问题,咱们能够通过 -XX:+PrintGCDetails
参数查看 GC 的日志。
代码自身:开发者谬误地应用 Flink 算子,没有深刻理解算子的实现机制导致性能问题。咱们能够通过查看运行机器节点的 CPU 和内存状况定位问题。
13. Flink 中的状态存储
Flink 在做计算的过程中常常须要存储中间状态,来防止数据失落和状态复原。抉择的状态存储策略不同,会影响状态长久化如何和 checkpoint 交互。Flink 提供了三种状态存储形式:MemoryStateBackend、FsStateBackend、RocksDBStateBackend。
14. Operator Chains(算子链)这个概念你理解吗
为了更高效地分布式执行,Flink 会尽可能地将 operator 的 subtask 链接(chain)在一起造成 task。每个 task 在一个线程中执行。将 operators 链接成 task 是十分无效的优化:它能缩小线程之间的切换,缩小音讯的序列化 / 反序列化,缩小数据在缓冲区的替换,缩小了提早的同时进步整体的吞吐量。这就是咱们所说的算子链。
15. Flink 的内存治理是如何做的
Flink 并不是将大量对象存在堆上,而是将对象都序列化到一个预调配的内存块上。此外,Flink 大量的应用了堆外内存。如果须要解决的数据超出了内存限度,则会将局部数据存储到硬盘上。Flink 为了间接操作二进制数据实现了本人的序列化框架。
16. 如何解决生产环境中的数据歪斜问题
1. flink 数据歪斜的体现:
工作节点频繁呈现反压,减少并行度也不能解决问题;
局部节点呈现 OOM 异样,是因为大量的数据集中在某个节点上,导致该节点内存被爆,工作失败重启。
2. 数据歪斜产生的起因:
业务上有重大的数据热点,比方滴滴打车的订单数据中北京、上海等几个城市的订单量远远超过其余地区;
技术上大量应用了 KeyBy、GroupBy 等操作,谬误的应用了分组 Key,人为产生数据热点。
3. 解决问题的思路:
业务上要尽量避免热点 key 的设计,例如咱们能够把北京、上海等热点城市分成不同的区域,并进行独自解决;
技术上呈现热点时,要调整计划打散原来的 key,防止间接聚合;此外 Flink 还提供了大量的性能能够防止数据歪斜。
17. Flink 中的 Time 有哪几种
Flink 中的工夫有三种类型,如下图所示:
- Event Time:是事件创立的工夫。它通常由事件中的工夫戳形容,例如采集的日志数据中,每一条日志都会记录本人的生成工夫,Flink 通过工夫戳分配器拜访事件工夫戳。
- Ingestion Time:是数据进入 Flink 的工夫。
- Processing Time:是每一个执行基于工夫操作的算子的本地零碎工夫,与机器相干,默认的工夫属性就是 Processing Time。
例如,一条日志进入 Flink 的工夫为2021-01-22 10:00:00.123
,达到 Window 的零碎工夫为2021-01-22 10:00:01.234
,日志的内容如下:2021-01-06 18:37:15.624 INFO Fail over to rm2
对于业务来说,要统计 1min 内的故障日志个数,哪个工夫是最有意义的?—— eventTime,因为咱们要依据日志的生成工夫进行统计。
18. Flink 对于早退数据是怎么解决的
Flink 中 WaterMark 和 Window 机制解决了流式数据的乱序问题,对于因为提早而程序有误的数据,能够依据 eventTime 进行业务解决,对于提早的数据 Flink 也有本人的解决办法,次要的方法是给定一个容许提早的工夫,在该工夫范畴内仍能够承受解决提早数据
设置容许提早的工夫是通过 allowedLateness(lateness: Time)设置
保留提早数据则是通过 sideOutputLateData(outputTag: OutputTag[T])保留
获取提早数据是通过 DataStream.getSideOutput(tag: OutputTag[X])获取
文章举荐:
Flink 中极其重要的 Time 与 Window 具体解析
19. Flink 中 window 呈现数据歪斜怎么解决
window 产生数据歪斜指的是数据在不同的窗口内沉积的数据量相差过多。实质上产生这种状况的起因是数据源头发送的数据量速度不同导致的。呈现这种状况个别通过两种形式来解决:
- 在数据进入窗口前做预聚合
- 从新设计窗口聚合的 key
20. Flink CEP 编程中当状态没有达到的时候会将数据保留在哪里
在流式解决中,CEP 当然是要反对 EventTime 的,那么绝对应的也要反对数据的早退景象,也就是 watermark 的解决逻辑。CEP 对未匹配胜利的事件序列的解决,和早退数据是相似的。在 Flink CEP 的解决逻辑中,状态没有满足的和早退的数据,都会存储在一个 Map 数据结构中,也就是说,如果咱们限定判断事件序列的时长为 5 分钟,那么内存中就会存储 5 分钟的数据,这在我看来,也是对内存的极大伤害之一。
举荐浏览:一文学会 Flink CEP
21. Flink 设置并行度的形式
们在理论生产环境中能够从四个不同层面设置并行度:
-
操作算子层面(Operator Level)
.map(new RollingAdditionMapper()).setParallelism(10) // 将操作算子设置并行度
-
执行环境层面(Execution Environment Level)
$FLINK_HOME/bin/flink 的 - p 参数批改并行度
-
客户端层面(Client Level)
env.setParallelism(10)
- 零碎层面(System Level)
全局配置在 flink-conf.yaml 文件中,parallelism.default,默认是 1:能够设置默认值大一点
须要留神的优先级:算子层面 > 环境层面 > 客户端层面 > 零碎层面。
22. Flink 中 Task 如何做到数据交换
在一个 Flink Job 中,数据须要在不同的 task 中进行替换,整个数据交换是有 TaskManager 负责的,TaskManager 的网络组件首先从缓冲 buffer 中收集 records,而后再发送。Records 并不是一个一个被发送的,是积攒一个批次再发送,batch 技术能够更加高效的利用网络资源。
23. Flink 的内存治理是如何做的
Flink 并不是将大量对象存在堆上,而是将对象都序列化到一个预调配的内存块上。此外,Flink 大量的应用了堆外内存。如果须要解决的数据超出了内存限度,则会将局部数据存储到硬盘上。Flink 为了间接操作二进制数据实现了本人的序列化框架。
24. 介绍下 Flink 的序列化
Flink 摒弃了 Java 原生的序列化办法,以独特的形式解决数据类型和序列化,蕴含本人的类型描述符,泛型类型提取和类型序列化框架。
TypeInformation 是所有类型描述符的基类。它揭示了该类型的一些根本属性,并且能够生成序列化器。
TypeInformation 反对以下几种类型:
- BasicTypeInfo: 任意 Java 根本类型或 String 类型
- BasicArrayTypeInfo: 任意 Java 根本类型数组或 String 数组
- WritableTypeInfo: 任意 Hadoop Writable 接口的实现类
- TupleTypeInfo: 任意的 Flink Tuple 类型(反对 Tuple1 to Tuple25)。Flink tuples 是固定长度固定类型的 Java Tuple 实现
- CaseClassTypeInfo: 任意的 Scala CaseClass(包含 Scala tuples)
- PojoTypeInfo: 任意的 POJO (Java or Scala),例如,Java 对象的所有成员变量,要么是 public 修饰符定义,要么有 getter/setter 办法
- GenericTypeInfo: 任意无奈匹配之前几种类型的类
25. Flink 海量数据高效去重
- 基于状态后端。
- 基于 HyperLogLog:不是精准的去重。
- 基于布隆过滤器(BloomFilter);疾速判断一个 key 是否存在于某容器,不存在就间接返回。
- 基于 BitMap;用一个 bit 位来标记某个元素对应的 Value,而 Key 即是该元素。因为采纳了 Bit 为单位来存储数据,因而能够大大节俭存储空间。
- 基于内部数据库;抉择应用 Redis 或者 HBase 存储数据,咱们只须要设计好存储的 Key 即可,不须要关怀 Flink 工作重启造成的状态失落问题。
26. Flink SQL 的是如何实现的
构建形象语法树的事件交给了 Calcite 去做。SQL query 会通过 Calcite 解析器转变成 SQL 节点树,通过验证后构建成 Calcite 的形象语法树(也就是图中的 Logical Plan)。另一边,Table API 上的调用会构建成 Table API 的形象语法树,并通过 Calcite 提供的 RelBuilder 转变成 Calcite 的形象语法树。而后顺次被转换成逻辑执行打算和物理执行打算。
在提交工作后会散发到各个 TaskManager 中运行,在运行时会应用 Janino 编译器编译代码后运行。
ClickHouse
1. ClickHouse 的应⽤场景有哪些?
- 绝⼤少数申请都是⽤于读拜访的;
- 数据须要以⼤批次(⼤于 1000 ⾏)进⾏更新,⽽不是单⾏更新;
- 数据只是增加到数据库,没有必要批改;
- 读取数据时,会从数据库中提取出⼤量的⾏,但只⽤到⼀⼩局部列;
- 表很“宽”,即表中蕴含⼤量的列;
- 查问频率绝对较低(通常每台服务器每秒查问数百次或更少);
- 对于简略查问,容许⼤约 50 毫秒的提早;
- 列的值是⽐较⼩的数值和短字符串(例如,每个 URL 只有 60 个字节);
- 在解决单个查问时须要⾼吞吐量(每台服务器每秒⾼达数⼗亿⾏);
- 不须要事务;
- 数据⼀致性要求较低;
- 每次查问中只会查问⼀个⼤表。除了⼀个⼤表,其余都是⼩表;
- 查问后果显著⼩于数据源。即数据有过滤或聚合。返回后果不超过单个服务器内存。
2. ClickHouse 的优缺点
长处:
- 为了高效的应用 CPU,数据不仅仅按列存储,同时还按向量进行解决;
- 数据压缩空间大,缩小 IO;解决单查问高吞吐量每台服务器每秒最多数十亿行;
- 索引非 B 树结构,不须要满足最左准则;只有过滤条件在索引列中蕴含即可;即便在应用的数据不在索引中,因为各种并行处理机制 ClickHouse 全表扫描的速度也很快;
- 写入速度十分快,50-200M/s,对于大量的数据更新十分实用。
毛病:
- 不反对事务,不反对真正的删除 / 更新;
- 不反对高并发,官网倡议 qps 为 100,能够通过批改配置文件减少连接数,然而在服务器足够好的状况下;
- SQL 满足日常应用 80% 以上的语法,join 写法比拟非凡;最新版已反对相似 SQL 的 join,但性能不好;
- 尽量做 1000 条以上批量的写入,防止逐行 insert 或小批量的 insert,update,delete 操作,因为 ClickHouse 底层会一直的做异步的数据合并,会影响查问性能,这个在做实时数据写入的时候要尽量避开;
- Clickhouse 快是因为采纳了并行处理机制,即便一个查问,也会用服务器一半的 CPU 去执行,所以 ClickHouse 不能反对高并发的应用场景,默认单查问应用 CPU 核数为服务器核数的一半,装置时会自动识别服务器核数,能够通过配置文件批改该参数。
3. ClickHouse 的核⼼个性?
- 列存储:列存储是指仅从存储系统中读取必要的列数据,⽆⽤列不读取,速度⾮常快。ClickHouse 采⽤列存储,这对于剖析型申请⾮常⾼效。⼀个典型且实在的状况是,如果咱们须要剖析的数据有 50 列,⽽每次剖析仅读取其中的 5 列,那么通过列存储,咱们仅需读取必要的列数据,相⽐于一般⾏存,可缩小 10 倍左右的读取、解压、解决等开销,对性能会有质的影响。
- 向量化执⾏:在⽀持列存的根底上,ClickHouse 实现了⼀套⾯向 向量化解决 的计算引擎,⼤量的解决操作都是向量化执⾏的。相⽐于传统⽕⼭模型中的逐⾏解决模式,向量化执⾏引擎采⽤批量解决模式,能够⼤幅缩小函数调⽤开销,升高指令、数据的 Cache Miss,晋升 CPU 利⽤效率。并且 ClickHouse 可利⽤ SIMD 指令进⼀步减速执⾏效率。这部分是 ClickHouse 优于⼤量同类 OLAP 产品的重要因素。
- 编码压缩:因为 ClickHouse 采⽤列存储,雷同列的数据间断存储,且底层数据在存储时是通过排序的,这样数据的部分规律性⾮常强,有利于取得更⾼的数据压缩⽐。此外,ClickHouse 除了⽀持 LZ4、ZSTD 等通⽤压缩算法外,还⽀持 Delta、DoubleDelta、Gorilla 等专⽤编码算法,⽤于进⼀步提⾼数据压缩⽐。
- 多索引:列存⽤于裁剪不必要的字段读取,⽽索引则⽤于裁剪不必要的记录读取。ClickHouse ⽀持丰盛的索引,从⽽在查问时尽可能的裁剪不必要的记录读取,提⾼查问性能。
4. 使⽤ ClickHouse 时有哪些留神点?
分区和索引
分区粒度依据业务特点决定,不宜过粗或过细。⼀般抉择按天分区,也可指定为 tuple();以单表 1 亿数据为例,分区⼤⼩管制在 10-30 个为最佳。
必须指定索引列,clickhouse 中的索引列即排序列,通过 order by 指定,⼀般在查问条件中常常被⽤来充当筛选条件的属性被纳⼊进来;能够是单⼀维度,也能够是组合维度的索引;通常须要满⾜⾼级列在前、查问频率⼤的在前准则;还有基数特地⼤的不适宜做索引列,如⽤户表的 userid 字段;通常筛选后的数据满⾜在百万以内为最佳。
数据采样策略
通过采⽤运算可极⼤晋升数据分析的性能。
数据量太⼤时应防止使⽤ select * 操作,查问的性能会与查问的字段⼤⼩和数量成线性变换;字段越少,耗费的 IO 资源就越少,性能就会越⾼。
千万以上数据集⽤ order by 查问时须要搭配 where 条件和 limit 语句⼀起使⽤。
如⾮必须不要在后果集上构建虚构列,虚构列⾮常耗费资源节约性能,能够思考在前端进⾏解决,或者在表中结构理论字段进⾏额定存储。
不倡议在⾼基列上执⾏ distinct 去重查问,改为近似去重 uniqCombined。
多表 Join 时要满⾜⼩表在右的准则,右表关联时被加载到内存中与左表进⾏⽐较。
存储
ClickHouse 不⽀持设置多数据⽬录,为了晋升数据 io 性能,能够挂载虚构券组,⼀个券组绑定多块物理磁盘晋升读写性能;少数查问场景 SSD 盘会⽐一般机械硬盘快 2 - 3 倍。
5. ClickHouse 的引擎有哪些?
ClickHouse 提供了⼤量的数据引擎,分为数据库引擎、表引擎,依据数据特点及使⽤场景抉择适合的引擎⾄关重
要。
ClickHouse引擎分类:
在以下⼏种状况下,ClickHouse 使⽤⾃⼰的数据库引擎:
- MergeTree 系列引擎
- Log 系列引擎
- 与其余存储 / 解决系统集成的引擎
- 特定性能的引擎
- 决定表存储在哪⾥以及以何种⽅式存储;
- ⽀持哪些查问以及如何⽀持;
- 并发数据拜访;
- 索引的使⽤;
- 是否能够执⾏多线程申请;
- 数据复制参数。
在所有的表引擎中,最为核⼼的当属 MergeTree 系列表引擎,这些表引擎领有最为强⼤的性能和最⼴泛的使⽤场合。对于⾮ MergeTree 系列的其余引擎⽽⾔,次要⽤于非凡⽤途,场景绝对无限。⽽ MergeTree 系列表引擎是官⽅主推的存储引擎,⽀持⼏乎所有 ClickHouse 核⼼性能。
MergeTree 作为家族系列最根底的表引擎,次要有以下特点:
- 存储的数据依照主键排序:容许创立稠密索引,从⽽放慢数据查问速度;
- ⽀持分区,能够通过 PRIMARY KEY 语句指定分区字段;
- ⽀持数据正本;
- ⽀持数据采样。
6. 建表引擎参数有哪些?
- ENGINE:
ENGINE = MergeTree()
,MergeTree 引擎没有参数。 - ORDER BY:order by 设定了分区内的数据依照哪些字段程序进⾏有序保留。
order by 是 MergeTree 中唯⼀⼀个必填项,甚⾄⽐ primary key 还重要,因为当⽤户不设置主键的状况,很多解决会按照 order by 的字段进⾏解决。
要求:主键必须是 order by 字段的前缀字段。
如果 ORDER BY 与 PRIMARY KEY 不同,PRIMARY KEY 必须是 ORDER BY 的前缀(为了保障分区内数据和主键的有序性)。
ORDER BY 决定了每个分区中数据的排序规定;
PRIMARY KEY 决定了⼀级索引(primary.idx);
ORDER BY 能够指代 PRIMARY KEY, 通常只⽤申明 ORDER BY 即可。
- PARTITION BY:分区字段,可选。如果不填:只会使⽤⼀个分区。
分区⽬录:MergeTree 是以列⽂件 + 索引⽂件 + 表定义⽂件组成的,然而如果设定了分区那么这些⽂件就会保留到不同的分区⽬录中。
- PRIMARY KEY:指定主键,如果排序字段与主键不⼀致,能够独自指定主键字段。否则默认主键是排序字段。可选。
- SAMPLE BY:采样字段,如果指定了该字段,那么主键中也必须蕴含该字段。⽐如 SAMPLE BY intHash32(UserID) ORDER BY (CounterID, EventDate, intHash32(UserID))。可选。
- TTL:数据的存活工夫。在 MergeTree 中,能够为某个列字段或整张表设置 TTL。当工夫达到时,如果是列字段级别的 TTL,则会删除这⼀列的数据;如果是表级别的 TTL,则会删除整张表的数据。可选。
- SETTINGS:额定的参数配置。可选。
Doris
1. Doris 的利用场景有哪些?
首先 Doris 是一个有着 MPP 架构的剖析型数据库产品。对于 PB 数量级、结构化数据能够做到亚秒级查问响应。应用上兼容 MySQL 协定,语法是规范的 SQL。Doris 自身不依赖任何其余零碎,相比 Hadoop 生态产品更易于运维。
利用场景包含:固定历史报表剖析、实时数据分析、交互式数据分析等。
个别状况下,用户的原始数据,比方日志或者在事务型数据库中的数据,通过流式零碎或离线解决后,导入到 Doris 中以供下层的报表工具或者数据分析师查问应用。
2. Doris 的架构介绍下
Doris 的架构很简洁,只设 FE(Frontend)、BE(Backend)两种角色、两个过程。
- 以数据存储的角度观看,FE 存储、保护集群元数据;BE 存储物理数据,数据的可靠性由 BE 保障,BE 会对整个数据存储多正本。
- 以查询处理的角度观看,FE 节点接管、解析查问申请,布局查问打算,调度查问执行,返回查问后果;BE 节点根据 FE 生成的物理打算,分布式地执行查问。
FE 次要有有三个角色,一个是 Leader,一个是 Follower,还有一个 Observer。Leader 跟 Follower,次要是用来达到元数据的高可用,保障单节点宕机的状况下,元数据可能实时地在线复原,而不影响整个服务。Observer 只是用来扩大查问节点,就是说如果在发现集群压力十分大的状况下,须要去扩大整个查问的能力,那么能够加 Observer 的节点。Observer 不参加任何的写入,只参加读取。
在应用接口方面,Doris 采纳 MySQL 协定,高度兼容 MySQL 语法,反对规范 SQL,用户能够通过各类客户端工具来拜访 Doris,并反对与 BI 工具的无缝对接。
3. Doris 的数据模型
Doris 的数据模型次要分为 3 类:
- Aggregate 聚合模型
- Uniq 惟一主键模型
- Duplicate 模型
Aggregate 聚合模型:
聚合模型须要用户在建表时显式的将列分为 Key 列和 Value 列。该模型会主动的对 Key 雷同的行,在 Value 列上进行聚合操作。
当咱们导入数据时,对于 Key 列雷同的行汇聚合成一行,而 Value 列会依照设置的 AggregationType 进行聚合。AggregationType 目前有以下四种聚合形式:
- SUM:求和,多行的 Value 进行累加。
- REPLACE:代替,下一批数据中的 Value 会替换之前导入过的行中的 Value。
- MAX:保留最大值。
- MIN:保留最小值。
例如:
CREATE TABLE IF NOT EXISTS example_db.expamle_tbl
(
`user_id` LARGEINT NOT NULL COMMENT "用户 id",
`date` DATE NOT NULL COMMENT "数据灌入日期工夫",
`city` VARCHAR(20) COMMENT "用户所在城市",
`age` SMALLINT COMMENT "用户年龄",
`sex` TINYINT COMMENT "用户性别",
`last_visit_date` DATETIME REPLACE DEFAULT "1970-01-01 00:00:00" COMMENT "用户最初一次拜访工夫",
`cost` BIGINT SUM DEFAULT "0" COMMENT "用户总生产",
`max_dwell_time` INT MAX DEFAULT "0" COMMENT "用户最大停留时间",
`min_dwell_time` INT MIN DEFAULT "99999" COMMENT "用户最小停留时间"
)
AGGREGATE KEY(`user_id`, `date`, `city`, `age`, `sex`)
... /* 省略 Partition 和 Distribution 信息 */
;
Unique 惟一主键模型:
在某些多维分析场景下,用户更关注的是如何保障 Key 的唯一性,即如何取得 Primary Key 唯一性束缚。因而,咱们引入了 Unique 的数据模型。该模型实质上是聚合模型的一个特例,也是一种简化的表构造示意形式。咱们举例说明。
这是一个典型的用户根底信息表。这类数据没有聚合需要,只需保障主键唯一性。(这里的主键为 user_id + username)。那么咱们的建表语句如下:
CREATE TABLE IF NOT EXISTS example_db.expamle_tbl
(
`user_id` LARGEINT NOT NULL COMMENT "用户 id",
`username` VARCHAR(50) NOT NULL COMMENT "用户昵称",
`city` VARCHAR(20) COMMENT "用户所在城市",
`age` SMALLINT COMMENT "用户年龄",
`sex` TINYINT COMMENT "用户性别",
`phone` LARGEINT COMMENT "用户电话",
`address` VARCHAR(500) COMMENT "用户地址",
`register_time` DATETIME COMMENT "用户注册工夫"
)
UNIQUE KEY(`user_id`, `user_name`)
... /* 省略 Partition 和 Distribution 信息 */
;
而这个表构造,齐全同等于以下应用聚合模型形容的表构造:
CREATE TABLE IF NOT EXISTS example_db.expamle_tbl
(
`user_id` LARGEINT NOT NULL COMMENT "用户 id",
`username` VARCHAR(50) NOT NULL COMMENT "用户昵称",
`city` VARCHAR(20) REPLACE COMMENT "用户所在城市",
`age` SMALLINT REPLACE COMMENT "用户年龄",
`sex` TINYINT REPLACE COMMENT "用户性别",
`phone` LARGEINT REPLACE COMMENT "用户电话",
`address` VARCHAR(500) REPLACE COMMENT "用户地址",
`register_time` DATETIME REPLACE COMMENT "用户注册工夫"
)
AGGREGATE KEY(`user_id`, `user_name`)
... /* 省略 Partition 和 Distribution 信息 */;
即 Unique 模型齐全能够用聚合模型中的 REPLACE 形式代替。其外部的实现形式和数据存储形式也齐全一样。这里不再持续举例说明。
Duplicate 模型:
在某些多维分析场景下,数据既没有主键,也没有聚合需要。因而,咱们引入 Duplicate 数据模型来满足这类需要。
例如:
CREATE TABLE IF NOT EXISTS example_db.expamle_tbl
(
`timestamp` DATETIME NOT NULL COMMENT "日志工夫",
`type` INT NOT NULL COMMENT "日志类型",
`error_code` INT COMMENT "错误码",
`error_msg` VARCHAR(1024) COMMENT "谬误详细信息",
`op_id` BIGINT COMMENT "负责人 id",
`op_time` DATETIME COMMENT "解决工夫"
)
DUPLICATE KEY(`timestamp`, `type`)
... /* 省略 Partition 和 Distribution 信息 */;
这种数据模型区别于 Aggregate 和 Uniq 模型。数据齐全依照导入文件中的数据进行存储,不会有任何聚合。即便两行数据完全相同,也都会保留。而在建表语句中指定的 DUPLICATE KEY,只是用来指明底层数据依照那些列进行排序。
4. 介绍下 Doris 的 ROLLUP
ROLLUP
ROLLUP 在多维分析中是“上卷”的意思,行将数据按 某种指定的粒度进行进一步聚合。
在 Doris 中,咱们将用户通过建表语句创立进去的表称为 Base 表(Base Table)。在 Base 表之上,咱们能够创立任意多个 ROLLUP 表。这些 ROLLUP 的数据是基于 Base 表产生的,并且在物理上是 独立存储 的。
ROLLUP 表的根本作用,在于在 Base 表的根底上,取得更粗粒度的聚合数据。
Duplicate 模型中的 ROLLUP
因为 Duplicate 模型没有 聚合的语意。所以该模型中的 ROLLUP,曾经失去了“上卷”这一层含意。而仅仅是作为调整列程序,以命中前缀索引的作用。
5. Doris 的前缀索引理解吗?
不同于传统的数据库设计,Doris 不反对在任意列上创立索引。Doris 这类 MPP 架构的 OLAP 数据库,通常都是通过进步并发,来解决大量数据的。
实质上,Doris 的数据存储在相似 SSTable(Sorted String Table)的数据结构中。该构造是一种有序的数据结构,能够依照指定的列进行排序存储。在这种数据结构上,以排序列作为条件进行查找,会十分的高效。
在 Aggregate、Uniq 和 Duplicate 三种数据模型中。底层的数据存储,是依照各自建表语句中,AGGREGATE KEY、UNIQ KEY 和 DUPLICATE KEY 中指定的列进行排序存储的。
而前缀索引,即在排序的根底上,实现的一种依据给定前缀列,疾速查问数据的索引形式。
在建表时,正确的抉择列程序,可能极大地提高查问效率。
ROLLUP 调整前缀索引
因为建表时曾经指定了列程序,所以一个表只有一种前缀索引。这对于应用其余不能命中前缀索引的列作为条件进行的查问来说,效率上可能无奈满足需要。因而,咱们能够通过创立 ROLLUP 来人为的调整列程序,以取得更好的查问效率。
6. 讲下 Doris 的物化视图
物化视图是将事后计算(依据定义好的 SELECT 语句)好的数据集,存储在 Doris 中的一个非凡的表。
物化视图的呈现次要是为了满足用户,既能对原始明细数据的任意维度剖析,也能疾速的对固定维度进行剖析查问。
应用场景(物化视图次要针对 Duplicate 明细模型做聚合操作)
- 剖析需要笼罩明细数据查问以及固定维度查问两方面。
- 查问仅波及表中的很小一部分列或行。
- 查问蕴含一些耗时解决操作,比方:工夫很久的聚合操作等。
- 查问须要匹配不同前缀索引。
劣势
- 对于那些常常反复的应用雷同的子查问后果的查问性能大幅晋升。
- Doris 主动保护物化视图的数据,无论是新的导入,还是删除操作都能保障 base 表和物化视图表的数据一致性。无需任何额定的人工保护老本。
- 查问时,会主动匹配到最优物化视图,并间接从物化视图中读取数据。
7. 物化视图和 Rollup 的区别是什么
在没有物化视图性能之前,用户个别都是应用 Rollup 性能通过预聚合形式晋升查问效率的。然而 Rollup 具备肯定的局限性,他不能基于明细模型做预聚合。
物化视图则在笼罩了 Rollup 的性能的同时,还能反对更丰盛的聚合函数。所以物化视图其实是 Rollup 的一个超集。
物化视图的局限性
- 物化视图的聚合函数的参数不反对表达式仅反对单列,比方:sum(a+b)不反对。
- 如果删除语句的条件列,在物化视图中不存在,则不能进行删除操作。如果肯定要删除数据,则须要先将物化视图删除,而后方可删除数据。
- 单表上过多的物化视图会影响导入的效率:导入数据时,物化视图和 base 表数据是同步更新的,如果一张表的物化视图表超过 10 张,则有可能导致导入速度很慢。这就像单次导入须要同时导入 10 张表数据是一样的。
- 雷同列,不同聚合函数,不能同时呈现在一张物化视图中,比方:select sum(a), min(a) from table 不反对。
- 物化视图针对 Unique Key 数据模型,只能扭转列程序,不能起到聚合的作用,所以在 Unique Key 模型上不能通过创立物化视图的形式对数据进行粗粒度聚合操作
数据仓库
举荐数仓建设好文,倡议读一读:万字详解整个数据仓库建设体系
1. ODS 层采纳什么压缩形式和存储格局?
压缩采纳Snappy,存储采纳orc,压缩比是 100g 数据压缩完 10g 左右。
2. DWD 层做了哪些事?
1) 数据荡涤
- 空值去除
- 过滤外围字段无意义的数据,比方订单表中订单 id 为 null,领取表中领取 id 为空
- 对手机号、身份证号等敏感数据脱敏
- 对业务数据传过来的表进行维度进化和降维。
- 将用户行为宽表和业务表进行数据一致性解决
2) 荡涤的伎俩
- Sql、mr、rdd、kettle、Python(我的项目中采纳 sql 进行革除)
3. DWS 层做了哪些事?
1) DWS 层有 3 - 5 张宽表(解决 100-200 个指标 70% 以上的需要)
具体宽表名称:用户行为宽表,用户购买商品明细行为宽表,商品宽表,购物车宽表,物流宽表、登录注册、售后等。
2) 哪个宽表最宽?大略有多少个字段?
最宽的是用户行为宽表。大略有 60-100 个字段
4. 事实表的类型?
事实表有:事务事实表、周期快照事实表、累积快照事实表、⾮事实事实表。
1)事务事实表
事务事实表记录的是事务层⾯的事实,保留的是最原⼦的数据,也称“原⼦事实表”。事务事实表中的数据在事务事件发⽣后产⽣,数据的粒度通常是每个事务记录⼀条记录。
2)周期快照事实表
以具备规律性的、可预⻅的工夫距离来记录事实。它统计的是距离周期内的度量统计,每个时间段⼀条记录,是在事务事实表之上建⽴的汇集表。
3)累积快照事实表
累积快照表记录的不确定的周期的数据。代表的是齐全笼罩⼀个事务或产品的⽣命周期的时间跨度,通常具备多个⽇期字段,⽤来记录整个⽣命周期中的要害工夫点。
4)⾮事实型事实表
这个与上⾯三个有所不同。事实表中通常要保留度量事实和多个维度外键,度量事实是事实表的关键所在。
⾮事实表中没有这些度量事实,只有多个维度外键。⾮事实型事实表通常⽤来跟踪⼀些事件或阐明某些流动的范畴。
第⼀类⾮事实型事实表是⽤来跟踪事件的事实表。例如:学⽣注册事件
第⼆类⾮事实型事实表是⽤来阐明某些流动范畴的事实表。例如:促销范畴事实表。
5. 星型模型和雪花模型的区别
1) 星型模式
星形模式 (Star Schema) 是最罕用的维度建模形式。星型模式是以事实表为核心,所有的维度表间接连贯在事实表上,像星星一样。星形模式的维度建模由一个事实表和一组维表成,且具备以下特点:a. 维表只和事实表关联,维表之间没有关联;b. 每个维表主键为单列,且该主键搁置在事实表中,作为两边连贯的外键;c. 以事实表为外围,维表围绕外围呈星形散布;
- 雪花模式
雪花模式 (Snowflake Schema) 是对星形模式的扩大。雪花模式的维度表能够领有其余维度表的,尽管这种模型相比星型更标准一些,然而因为这种模型不太容易了解,保护老本比拟高,而且性能方面须要关联多层维表,性能也比星型模型要低。所以个别不是很罕用
3.星座模式
星座模式是星型模式延长而来,星型模式是基于一张事实表的,而 星座模式是基于多张事实表的,而且共享维度信息。后面介绍的两种维度建模办法都是多维表对应单事实表,但在很多时候维度空间内的事实表不止一个,而一个维表也可能被多个事实表用到。在业务倒退前期,绝大部分维度建模都采纳的是星座模式。
6. 数据漂移如何解决?
1) 什么是数据漂移?
通常是指 ods 表的同⼀个业务⽇期数据中蕴含了前⼀天或后⼀天凌晨左近的数据或者失落当天变更的数据,这种景象就叫做漂移,且在⼤局部公司中都会遇到的场景。
2) 如何解决数据漂移问题?
通常有两种解决⽅案:
- 多获取后⼀天的数据,保障数据只多不少
- 通过多个工夫戳字段来限度工夫获取绝对精确的数据
第⼀种⽅案⽐较暴⼒,这⾥不做过多解释,次要来解说⼀下第⼆种解决⽅案。(这种解决⽅案在⼤数据之路这本书有体现)。
第⼀种⽅案⾥,工夫戳字段分为四类:
- 数据库表中⽤来标识数据记录更新工夫的工夫戳字段(假如这类字段叫 modified time)。
- 数据库⽇志中⽤来标识数据记录更新工夫的工夫戳字段·(假如这类宇段叫 log_time)。
- 数据库表中⽤来记录具体业务过程发⽣工夫的工夫戳字段(假如这类字段叫 proc_time)。
- 标识数据记录被抽取到工夫的工夫戳字段(假如这类字段 extract time)。
实践上这⼏个工夫应该是⼀致的,但往往会呈现差别,造成的起因可能为:
- 数据抽取须要⼀定的工夫,extract_time 往往晚于前三个工夫。
- 业务零碎⼿动改变数据并未更新 modfied_time。
- ⽹络或零碎压⼒问题,log_time 或 modified_time 晚于 proc_time。
通常都是依据以上的某⼏个字段来切分 ODS 表,这就产⽣了数据漂移。具体场景如下:
- 依据 extract_time 进⾏同步。
- 依据 modified_time 进⾏限度同步,在理论⽣产中这种状况最常⻅,然而往往会发⽣不更新 modified time ⽽导致的数据脱漏,或者凌晨工夫产⽣的数据记录漂移到先天。因为⽹络或者零碎压⼒问题,log_time 会晚 proc_time,从⽽导致凌晨工夫产⽣的数据记录漂移到后⼀天。
- 依据 proc_time 来限度,会违反 ods 和业务库放弃⼀致的准则,因为仅仅依据 proc_time 来限度,会脱漏很多其余过程的变动。
第⼆种解决⽅案:
- ⾸先通过 log_time 多同步前⼀天最初 15 分钟和后⼀天凌晨开始 15 分钟的数据,而后⽤ modified_time 过滤⾮当天的数据,这样确保数据不会因为零碎问题被脱漏。
- 而后依据 log_time 获取后⼀天 15 分钟的数据,基于这部分数据,依照主键依据 log_time 做升序排序,那么第⼀条数据也就是最靠近当天记录变动的。
- 最初将前两步的数据做全外连贯,通过限度业务工夫 proc_time 来获取想要的数据。
7. 维度建模和范式建模的区别
通常数据建模有以下⼏个流程:
- 概念建模:即通常先将业务划分多个主题。
- 逻辑建模:即定义各种实体、属性和关系。
- 物理建模:设计数据对象的物理实现,⽐如表字段类型、命名等。
那么范式建模,即 3NF 模型具备以下特点:
- 原⼦性,即 数据不可分割。
- 基于第⼀个条件,实体属性齐全依赖于主键,不能存在仅依赖主关键字⼀局部属性。即 不能存在局部依赖。
- 基于第⼆个条件,任何⾮主属性不依赖于其余⾮主属性。即 打消传递依赖。
基于以上三个特点,3NF 的最终⽬的就是为了升高数据冗余,保障数据⼀致性;同时也有了数据关联逻辑简单的毛病。
⽽维度建模是⾯向剖析场景的,次要关注点在于疾速、灵便,可能提供⼤规模的数据响应。
常⽤的维度模型类型次要有:
- 星型模型:即由⼀个事实表和⼀组维度表组成,每个维表都有⼀个维度作为主键。事实表居中,多个维表呈辐射状散布在周围,并与事实表关联,造成⼀个星型构造。
- 雪花模型:在星型模型的根底上,基于范式实践进⼀步层次化,将某些维表扩大成事实表,最终造成雪花状构造。
- 星系模型:基于多个事实表,共享⼀些维度表。
8. 谈谈元数据的了解?
广义来讲就是⽤来形容数据的数据。
⼴义来看,除了业务逻辑间接读写解决的业务数据,所有其余⽤来保护整个零碎运行所须要的数据,都能够较为元数据。
定义:元数据 metadata 是对于数据的数据。在数仓零碎中,元数据能够帮忙数据仓库管理员和数据仓库开发⼈员⽅便的找到他们所关⼼的数据;元数据是形容数据仓库外部数据的构造和建⽴⽅法的数据。依照⽤途可分为:技术元数据、业务元数据。
技术元数据
存储对于数据仓库技术细节的数据,⽤于开发和治理数据仓库使⽤的数据。
- 数据仓库构造的形容,包含数据模式、视图、维、层次结构和导出数据的定义,以及数据集市的地位和内容。
- 业务零碎、数据仓库和数据集市的体系结构和模式。
- 由操作环境到数据仓库环境的映射,包含元数据和他们的内容、数据提取、转换规则和数据刷新规定、权限等。
业务元数据
从业务⻆度形容了数据仓库中的数据,他提供了介于使⽤者和理论零碎之间的语义层,使不懂计算机技术的业务⼈员也能读懂数仓中的数据。
- 企业概念模型:示意企业数据模型的⾼层信息。整个企业业务概念和互相关系。以这个企业模型为根底,不懂 sql 的⼈也能做到⼼中无数
- 多维数据模型。通知业务剖析⼈员在数据集市中有哪些维、维的类别、数据⽴⽅体以及数据集市中的聚合规定。
- 业务概念模型和物理数据之间的依赖。业务视图和理论数仓的表、字段、维的对应关系也应该在元数据知识库中有所体现。
9. 数仓如何确定主题域?
主题
主题是在较⾼档次上将数据进⾏综合、归类和剖析利⽤的⼀个抽象概念,每⼀个主题根本对应⼀个宏观的剖析畛域。在逻辑意义上,它是对企业中某⼀宏观剖析畛域所波及的剖析对象。
⾯向主题的数据组织⽅式,就是在较⾼档次上对剖析对象数据的⼀个残缺并且⼀致的形容,能刻画各个剖析对象所波及的企业各项数据,以及数据之间的分割。
主题是依据剖析的要求来确定的。
主题域
- 从数据⻆度看(集合论)
主题语通常是分割较为严密的数据主题的汇合。能够依据业务的关注点,将这些数据主题划分到不同的主题域。主题域的确定由最终⽤户和数仓设计⼈员共同完成。
- 从须要建设的数仓主题看(边界论)
主题域是对某个主题进⾏剖析后确定的主题的边界。
数仓建设过程中,须要对主题进⾏剖析,确定主题所波及到的表、字段、维度等界线。
- 确定主题内容
数仓主题定义好当前,数仓中的逻辑模型也就根本成形了,须要在主题的逻辑关系中列出属性和零碎相干⾏为。此阶段须要定义好数据仓库的存储构造,向主题模型中增加所须要的信息和能充沛代表主题的属性组。
10. 在解决大数据过程中,如何保障失去期望值
- 保障在数据采集的时候不失落数据,这个尤为重要,如果在数据采集的时候就曾经不精确,前面很难达到期望值
- 在数据处理的时候不失落数据,例如 sparkstreaming 解决 kafka 数据的时候,要保证数据不失落,这个尤为重要
- 前两步中,如果无奈保证数据的完整性,那么就要通过离线计算进行数据的校对,这样能力保障咱们可能失去期望值
11. 你感觉数仓建设中最重要的是什么
数仓建设中,最重要的是数据准确性,数据的真正价值在于数据驱动决策,通过数据领导经营,在一个不精确的数据驱动下,失去的肯定是谬误的数据分析,影响的是公司的业务倒退决策,最终导致公司的策略调控失败。
12. 数据仓库建模怎么做的
数仓建设中最罕用模型 –Kimball 维度建模详解
13. 数据品质怎么监控
单表数据量监控
一张表的记录数在一个已知的范畴内,或者高低浮动不会超过某个阈值
- SQL 后果:var 数据量 = select count(*)from 表 where 工夫等过滤条件
- 报警触发条件设置:如果数据量不在[数值上限, 数值下限],则触发报警
- 同比增加:如果 ((本周的数据量 - 上周的数据量)/ 上周的数据量 *100) 不在 [比例下线,比例下限],则触发报警
- 环比减少:如果 ((明天的数据量 – 昨天的数据量)/ 昨天的数据量 *100) 不在 [比例下线,比例下限],则触发报警
- 报警触发条件设置肯定要有。如果没有配置的阈值,不能做监控
日活、周活、月活、留存(日周月)、转化率(日、周、月)GMV(日、周、月)
复购率(日周月)
单表空值检测
某个字段为空的记录数在一个范畴内,或者占总量的百分比在某个阈值范畴内
- 指标字段:抉择要监控的字段,不能选“无”
- SQL 后果:var 异样数据量 = select count(*) from 表 where 指标字段 is null
- 单次检测:如果 (异样数据量) 不在[数值上限, 数值下限],则触发报警
单表反复值检测
一个或多个字段是否满足某些规定
- 指标字段:第一步先失常统计条数;select count(*) form 表;
- 第二步,去重统计;select count(*) from 表 group by 某个字段
- 第一步的值和第二步的值做减法,看是否在高低线阀值之内
- 单次检测:如果 (异样数据量) 不在[数值上限, 数值下限],则触发报警
跨表数据量比照
次要针对同步流程,监控两张表的数据量是否统一
- SQL 后果:count(本表) – count(关联表)
- 阈值配置与“空值检测”雷同
14. 数据分析方法论理解过哪些?
数据商业剖析的指标是利用大数据为所有职场人员做出迅捷,高质,高效的决策提供可规模化的解决方案。商业剖析是发明价值的数据迷信。
数据商业剖析中会存在很多判断:
- 察看数据以后产生了什么?
比方想晓得线上渠道 A、B 各自带来了多少流量,新上线的产品有多少用户喜爱,新注册流中注册的人数有多少。这些都须要通过数据来展现后果。
- 了解为什么产生?
咱们须要晓得渠道 A 为什么比渠道 B 好,这些是要通过数据去发现的。兴许某个关键字带来的流量转化率比其余都要低,这时能够通过信息、常识、数据积淀出产生的起因是什么。
- 预测将来会产生什么?
在对渠道 A、B 有了判断之后,依据以往的常识预测将来会产生什么。在投放渠道 C、D 的时候,猜想渠道 C 比渠道 D 好,当上线新的注册流、新的优化,能够晓得哪一个节点比拟容易出问题,这些都是通过数据进行预测的过程。
- 商业决策
所有工作中最有意义的还是商业决策,通过数据来判断应该做什么。这是商业剖析最终的目标。
数据湖
数据湖常识理解举荐浏览:万字详解数据仓库、数据湖、数据中台和湖仓一体
1. 什么是数据湖
本文首发于公众号【五分钟学大数据】,点击获取:数仓建设保姆级教程
数据湖是一种一直演进中、可扩大的大数据存储、解决、剖析的基础设施;以数据为导向,实现任意起源、任意速度、任意规模、任意类型数据的全量获取、全量存储、多模式解决与全生命周期治理;并通过与各类内部异构数据源的交互集成,反对各类企业级利用。
用架构图能很快说明确,用阿里的数据架构图来说:
- ODS(operational data store, staging area)存储来自各业务零碎(生产零碎)的原始数据,即为数据湖。
- CDM 为通过整合、荡涤的数据。其中的 DWS 汇总层,为面向主题的数据仓库(广义),用于 BI 报表出数。
简略来说,数据湖的定义就是原始数据保留区. 尽管这个概念国内谈的少,但绝大部分互联网公司都曾经有了。国内个别把整个 HDFS 叫做数仓(狭义),即寄存所有数据的中央。
2. 数据湖的倒退
数据湖最早是 2011 年由 Pentaho 的首席技术官 James Dixon 提出的一个概念,他认为诸如数据集市,数据仓库因为其有序性的特点,势必会带来数据孤岛效应,而数据湖能够因为其开放性的特点能够解决数据孤岛问题。
为什么不是数据河?
因为,数据要能存,而不是一江春水向东流。
为什么不是数据池?
因为,要足够大,大数据太大,一池存不下。
为什么不是数据海?
因为,企业的数据要有边界,能够流通和替换,但更重视隐衷和平安,“海到无际天作岸”,那可不行。
所以数据要能“存”,数据要够“存”,数据要有边界地“存”。企业级的数据是须要长期积淀的,因而是“数据湖”。
同时湖水人造会进行分层,满足不同的生态系统要求,这与企业建设对立数据中心,寄存治理数据的需要是统一的。热数据在下层不便流通利用,温数据、冷数据位于数据中心的不同存储介质之中,达到数据存储容量与老本的均衡。
但随着数据湖在各类企业的利用,大家都感觉:嗯,这个数据有用,我要放进去;那个数据也有用,我也要放进去;于是把所有的数据不假思索地扔进基于数据湖的相干技术或工具中,没有规定不成方圆,当咱们认为所有数据都有用时,那么所有的数据都是垃圾,数据湖也变成了造成企业老本高企的数据沼泽。
3. 数据湖有哪些劣势
- 轻松地收集数据:数据湖与数据仓库的一大区别就是,Schema On Read,即在应用数据时才须要 Schema 信息;而数据仓库是 Schema On Write,即在存储数据时就须要设计好 Schema。这样,因为对数据写入没有限度,数据湖能够更容易的收集数据。
- 从数据中挖掘更多价值:数据仓库和数据市场因为只应用数据中的局部属性,所以只能答复一些当时定义好的问题;而数据湖存储所有最原始、最细节的数据,所以能够答复更多的问题。并且数据湖容许组织中的各种角色通过自助剖析工具,对数据进行剖析,以及利用 AI、机器学习的技术,从数据中挖掘更多的价值。
- 打消数据孤岛:数据湖中会集了来自各个系统中的数据,这就打消了数据孤岛问题。
- 具备更好的扩展性和敏捷性:数据湖能够利用分布式文件系统来存储数据,因而具备很高的扩大能力。开源技术的应用还升高了存储老本。数据湖的构造没那么严格,因而天生具备更高的灵活性,从而进步了敏捷性。
4. 数据湖应该具备哪些能力
- 数据集成能力:
须要具备把各种数据源接入集成到数据湖中的能力。数据湖的存储也应该是多样的,比方 HDFS、HIVE、HBASE 等等。
- 数据治理能力:
治理能力的外围是保护好数据的元数据(metadata)。强制要求所有进入数据湖的数据必须提供相干元数据,应该作为最低限度的治理管控。没有元数据,数据湖就面临成为数据沼泽的危险。更丰盛的性能还包含:
- 主动提取元元数据,并依据元数据对数据进行分类,造成数据目录。
- 主动对数据目录进行剖析,能够基于 AI 和机器学习的办法,发现数据之间的关系。
- 主动建设数据之间血缘关系图。
- 跟踪数据的应用状况,以便将数据作为产品,造成数据资产。
- 数据搜寻和发现能力:
如果把整个互联网设想成一个微小的数据湖。那么,之所以人们能够这么无效的利用这个湖中的数据,就是因为有了 Google 这样的搜索引擎。人们能够通过搜寻,不便地找到他们想要的数据,进而进行剖析。搜寻能力是数据湖的非常重要的能力。
- 数据安全管控能力:
对数据的应用权限进行管控,对敏感数据进行脱敏或加密解决,也是数据湖能商用所必须具备的能力。
- 数据质量检验能力:
数据品质是剖析正确的要害。因而必须对进入数据湖中的数据的品质状况进行测验。及时发现数据湖中数据品质的问题。为无效的数据摸索提供保障。
- 自助数据摸索能力:
应该具备一系列好用的数据分析工具,以便各类用户能够对数据湖中的数据进行自助摸索。包含:
- 反对对流、NoSQL、图等多种存储库的联结剖析能力
- 反对交互式的大数据 SQL 剖析
- 反对 AI、机器学习剖析
- 反对相似 OLAP 的 BI 剖析
- 反对报表的生成
5. 数据湖的实现遇到了哪些问题
数据湖刚提出来时,只是一个奢侈的理念。而从理念变成一个能够落地的零碎,就面临着许多不得不思考的事实问题:
首先,把所有原始数据都存储下来的想法,要基于一个前提,就是存储老本很低。而今数据产生的速度越来越快、产生的量越来越大的状况下,把所有原始数据,不分价值大小,都存储下来,这个老本在经济上能不能承受,可能须要打一个问号。
其次,数据湖中寄存这各类最原始的明细数据,包含交易数据、用户数据等敏感数据,这些数据的平安怎么保障?用户拜访的权限如何管制?
再次,湖中的数据怎么治理?谁对数据的品质、数据的定义、数据的变更负责?如何确保数据的定义、业务规定的一致性?
数据湖的理念很好,然而它当初还不足像数据仓库那样,有一整套方法论为根底,有一系列具备可操作性的工具和生态为撑持。正因如此,目前把 Hadoop 用来对特定的、高价值的数据进行解决,构建数据仓库的模式,获得了较多的胜利;而用来落实数据湖理念的模式,遭逢了一系列的失败。这里,总结一些典型的数据湖失败的起因:
- 数据沼泽:当越来越多的数据接入到数据湖中,然而却没有无效的办法跟踪这些数据,数据沼泽就产生了。在这种失败中,人们把所有货色都放在 HDFS 中,冀望当前能够挖掘些什么,可没多久他们就忘那里有什么。
- 数据泥团:各种各样的新数据接入进数据湖中,它们的组织模式、品质都不一样。因为不足用于查看,清理和重组数据的自助服务工具,使得这些数据很难发明价值。
- 不足自助剖析工具:因为不足好用的自助剖析工具,间接对数据湖中的数据分析很艰难。个别都是数据工程师或开发人员创立一个整顿后的小局部数据集,把这些数据集交付给更宽泛的用户,以便他们应用相熟的工具进行数据分析。这限度了更宽泛的人参加到摸索大数据中,升高了数据湖的价值。
- 不足建模的方法论和工具:在数据湖中,仿佛每一项工作都得从头开始,因为以前的我的项目产生的数据简直没有方法重用。其实,咱们骂数据仓库很难变动以适应新需要,这其中有个起因就是它花很多工夫来对数据进行建模,而正是有了这些建模,使得数据能够共享和重用。数据湖也须要为数据建模,不然每次分析师都得从头开始。
- 短少数据安全治理:通常的想法是每个人都能够拜访所有数据,但这是行不通的。企业对本人的数据是有爱护本能的,最终肯定是须要数据安全治理的。
- 一个数据湖搞定所有:大家都对能在一个库中存储所有数据的想法很兴奋。然而,数据湖之外总会有新的存储库,很难把他们全都毁灭掉。其实,大多数公司所需的,是能够对多种存储库联结拜访性能。是不是在一个中央存储,并不是那么重要。
6. 数据湖与数据仓库的区别
数据仓库 ,精确说,是面向 历史数据积淀和剖析应用的,有三大特点:
- 其一是 集成性,因为数据起源泛滥,因此须要技术和标准来对立存储形式;
- 其二是 非易失和随工夫变动,数据仓库存储了过来每一天的快照且通常不更新,使用者能够在任一天向前或者向后比照数据的变动;
- 其三是 面向主题,依据业务对数据进行无效的编码,让实践最佳值在利用中落地。
数据湖 ,精确说,其出发点是 补全数据仓库实时处理能力、交互式剖析能力 等新技术缺失的状况。其最重要的特点,就是丰盛的计算引擎:批处理、流式、交互式、机器学习,该有的,包罗万象,企业须要什么,就用什么。数据湖也有三个特色:
- 其一是 灵活性,默认业务的不确定性是常态的,在无奈预期将来变动时,技术设施根底,就要具备“按需”贴合业务的能力;
- 其二是 管理性,数据湖须要保留原始信息和解决后的信息,在数据源、数据格式、数据周期等维度上,可能追溯数据的接入、存储、剖析和应用等流动过程;
- 其三是 多态性,自身的引擎须要进可能的丰盛,因为业务场景不固定,而多态的引擎反对、扩大能力,可能较好的适应业务的疾速变动。
7. 为什么要做数据湖?区别在于?
数据湖和数仓,就是原始数据和数仓模型的区别。因为数仓(广义)中的表,次要是事实表 - 维度表,次要用于 BI、出报表,和原始数据是不一样的。
为什么要强调数据湖呢?
真正的起因在于,data science 和 machine learning 进入支流了,须要用原始数据做剖析,而数仓的维度模型则通常用于聚合。
另一方面,机器学习用到的数据,也不止于结构化数据。用户的评论、图像这些非结构化数据,也都能够利用到机器学习中。
但数据湖背地其实还有更大的区别:
- 传统数仓的工作形式是集中式的:业务人员给需要到数据团队,数据团队依据要求加工、开发成维度表,供业务团队通过 BI 报表工具查问。
- 数据湖是凋谢、自助式的(self-service):凋谢数据给所有人应用,数据团队更多是提供工具、环境供各业务团队应用(不过集中式的维度表建设还是须要的),业务团队进行开发、剖析。
也就是组织架构和分工的差异 —— 传统企业的数据团队可能被当做 IT,终日要求提数,而在新型的互联网 / 科技团队,数据团队负责提供简略易用的工具,业务部门间接进行数据的应用。
8. 数据湖挑战
从传统集中式的数仓转为开放式的数据湖,并不简略,会碰到许多问题
- 数据发现:如何帮忙用户发现数据、理解有哪些数据?
- 数据安全:如果治理数据的权限和平安?因为一些数据是敏感的、或者不应间接凋谢给所有人的(比方电话号码、地址等)
- 数据管理:多个团队应用数据,如何共享数据成绩(比方画像、特色、指标),防止反复开发
这也是目前各大互联网公司都在改良的方向!
9. 湖仓一体
2020 年,大数据 DataBricks 公司首次提出了湖仓一体(Data Lakehouse)概念,心愿将数据湖和数据仓库技术合而为一,此概念一出各路云厂商纷纷跟进。
Data Lakehouse(湖仓一体)是新呈现的一种数据架构,它同时排汇了数据仓库和数据湖的劣势,数据分析师和数据科学家能够在同一个数据存储中对数据进行操作,同时它也能为公司进行数据治理带来更多的便利性。
1) 目前数据存储的计划
始终以来,咱们都在应用两种数据存储形式来架构数据:
- 数据仓库:次要存储的是以关系型数据库组织起来的结构化数据。数据通过转换、整合以及清理,并导入到指标表中。在数仓中,数据存储的构造与其定义的 schema 是强匹配的。
- 数据湖:存储任何类型的数据,包含像图片、文档这样的非结构化数据。数据湖通常更大,其存储老本也更为便宜。存储其中的数据不须要满足特定的 schema,数据湖也不会尝试去将特定的 schema 实施其上。相同的是,数据的拥有者通常会在读取数据的时候解析 schema(schema-on-read),当解决相应的数据时,将转换施加其上。
当初许多的公司往往同时会搭建数仓、数据湖这两种存储架构,一个大的数仓和多个小的数据湖。这样,数据在这两种存储中就会有肯定的冗余。
2) Data Lakehouse(湖仓一体)
Data Lakehouse 的呈现试图去交融数仓和数据湖这两者之间的差别,通过将数仓构建在数据湖上,使得存储变得更为便宜和弹性,同时 lakehouse 可能无效地晋升数据品质,减小数据冗余。在 lakehouse 的构建中,ETL 起了十分重要的作用,它可能将未经规整的数据湖层数据转换成数仓层结构化的数据。
上面具体解释下:
湖仓一体(Data Lakehouse):
根据 DataBricks 公司对 Lakehouse 的定义:一种联合了数据湖和数据仓库劣势的新范式,解决了数据湖的局限性。Lakehouse 应用新的零碎设计:间接在用于数据湖的低成本存储上实现与数据仓库中相似的数据结构和数据管理性能。
解释拓展:
湖仓一体,简略了解就是把面向企业的数据仓库技术与数据湖存储技术相结合,为企业提供一个对立的、可共享的数据底座。
防止传统的数据湖、数据仓库之间的数据挪动,将原始数据、加工荡涤数据、模型化数据,独特存储于一体化的“湖仓”中,既能面向业务实现高并发、精准化、高性能的历史数据、实时数据的查问服务,又能承载剖析报表、批处理、数据挖掘等剖析型业务。
湖仓一体计划的呈现,帮忙企业构建起全新的、交融的数据平台。通过对机器学习和 AI 算法的反对,实现数据湖 + 数据仓库的闭环,晋升业务的效率。数据湖和数据仓库的能力充沛联合,造成互补,同时对接下层多样化的计算生态。
11. 目前有哪些开源数据湖组件
目前开源的数据湖有江湖人称“数据湖三剑客”的Hudi、Delta Lake 和 IceBerg。
1) Hudi
Apache Hudi 是一种数据湖的存储格局,在 Hadoop 文件系统之上提供了更新数据和删除数据的能力以及生产变动数据的能力。
Hudi 反对如下两种表类型:
- Copy On Write
应用 Parquet 格局存储数据。Copy On Write 表的更新操作须要通过重写实现。
- Merge On Read
应用列式文件格式(Parquet)和行式文件格式(Avro)混合的形式来存储数据。Merge On Read 应用列式格局寄存 Base 数据,同时应用行式格局寄存增量数据。最新写入的增量数据寄存至行式文件中,依据可配置的策略执行 COMPACTION 操作合并增量数据至列式文件中。
利用场景
- 近实时数据摄取
Hudi 反对插入、更新和删除数据的能力。能够实时摄取音讯队列(Kafka)和日志服务 SLS 等日志数据至 Hudi 中,同时也反对实时同步数据库 Binlog 产生的变更数据。
Hudi 优化了数据写入过程中产生的小文件。因而,相比其余传统的文件格式,Hudi 对 HDFS 文件系统更加的敌对。
- 近实时数据分析
Hudi 反对多种数据分析引擎,包含 Hive、Spark、Presto 和 Impala。Hudi 作为一种文件格式,不须要依赖额定的服务过程,在应用上也更加的轻量化。
- 增量数据处理
Hudi 反对 Incremental Query 查问类型,能够通过 Spark Streaming 查问给定 COMMIT 后产生变更的数据。Hudi 提供了一种生产 HDFS 变动数据的能力,能够用来优化现有的零碎架构。
2) Delta Lake
Delta Lake 是 Spark 计算框架和存储系统之间带有 Schema 信息数据的存储中间层。它给 Spark 带来了三个最次要的性能:
第一,Delta Lake 使得 Spark 能反对数据更新和删除性能;
第二,Delta Lake 使得 Spark 能反对事务;
第三,反对数据版本治理,运行用户查问历史数据快照。
外围个性
- ACID 事务:为数据湖提供 ACID 事务,确保在多个数据管道并发读写数据时,数据能放弃完整性。
- 数据版本治理和工夫旅行:提供了数据快照,使开发人员可能拜访和还原晚期版本的数据以进行审核、回滚或重现试验
- 可伸缩的元数据管理:存储表或者文件的元数据信息,并且把元数据也作为数据处理,元数据与数据的对应关系寄存在事务日志中;
- 流和批对立解决:Delta 中的表既有批量的,也有流式和 sink 的;
- 数据操作审计:事务日志记录对数据所做的每个更改的详细信息,提供对更改的残缺审计跟踪;
- Schema 治理性能:提供主动验证写入数据的 Schema 与表的 Schema 是否兼容的能力,并提供显示减少列和自动更新 Schema 的能力;
- 数据表操作(相似于传统数据库的 SQL):合并、更新和删除等,提供齐全兼容 Spark 的 Java/scala API;
- 对立格局:Delta 中所有的数据和元数据都存储为 Apache Parquet。
3) IceBerg
Iceberg 官网定义:Iceberg 是一个通用的表格局(数据组织格局),它能够适配 Presto,Spark 等引擎提供高性能的读写和元数据管理性能。
数据湖相比传统数仓而言,最显著的便是优良的 T + 0 能力,这个解决了 Hadoop 时代数据分析的顽疾。传统的数据处理流程从数据入库到数据处理通常须要一个较长的环节、波及许多简单的逻辑来保证数据的一致性,因为架构的复杂性使得整个流水线具备显著的提早。
Iceberg 的 ACID 能力能够简化整个流水线的设计,升高整个流水线的提早。升高数据修改的老本。传统 Hive/Spark 在修改数据时须要将数据读取进去,批改后再写入,有极大的修改老本。Iceberg 所具备的批改、删除能力可能无效地升高开销,晋升效率。
- ACID 能力,无缝贴合流批一体数据存储最初一块幅员
随着 flink 等技术的一直倒退,流批一体生态不断完善,但在流批一体数据存储方面始终是个空白,直到 Iceberg 等数据湖技术的呈现,这片空白被缓缓填补。
Iceberg 提供 ACID 事务能力,上游数据写入即可见,不影响以后数据处理工作,这大大简化了 ETL;
Iceberg 提供了 upsert、merge into 能力,能够极大地放大数据入库提早;
- 对立数据存储,无缝连接计算引擎和数据存储
Iceberg 提供了基于流式的增量计算模型和基于批处理的全量表计算模型。批处理和流工作能够应用雷同的存储模型,数据不再孤立;Iceberg 反对暗藏分区和分区进化,不便业务进行数据分区策略更新。
Iceberg 屏蔽了底层数据存储格局的差别,提供对于 Parquet,ORC 和 Avro 格局的反对。Iceberg 起到了两头桥梁的能力,将下层引擎的能力传导到上层的存储格局。
- 凋谢架构设计,开发保护老本绝对可控
Iceberg 的架构和实现并未绑定于某一特定引擎,它实现了通用的数据组织格局,利用此格局能够不便地与不同引擎对接,目前 Iceberg 反对的计算引擎有 Spark、Flink、Presto 以及 Hive。
相比于 Hudi、Delta Lake,Iceberg 的架构实现更为优雅,同时对于数据格式、类型零碎有齐备的定义和可进化的设计;面向对象存储的优化。Iceberg 在数据组织形式上充分考虑了对象存储的个性,防止耗时的 listing 和 rename 操作,使其在基于对象存储的数据湖架构适配上更有劣势。
- 增量数据读取,实时计算的一把利剑
Iceberg 反对通过流式形式读取增量数据,反对 Structed Streaming 以及 Flink table Source。
11. 三大数据湖组件比照
1) 概览
Delta lake
因为 Apache Spark 在商业化上获得巨⼤胜利,所以由其背地商业公司 Databricks 推出的 Delta lake 也显得分外亮眼。在没有 delta 数据湖之前,Databricks 的客户⼀般会采⽤经典的 lambda 架构来构建他们的流批处理场景。
Hudi
Apache Hudi 是由 Uber 的⼯程师为满⾜其外部数据分析的需要⽽设计的数据湖项⽬,它提供的 fast upsert/delete 以及 compaction 等性能能够说是精准命中⼴⼤⼈民大众的痛点,加上项⽬各成员踊跃地社区建设,包含技术细节分享、国内社区推⼴等等,也在逐渐地吸引潜在⽤户的⽬光。
Iceberg
Netflix 的数据湖原先是借助 Hive 来构建,但发现 Hive 在设计上的诸多缺点之后,开始转为⾃研 Iceberg,并最终演化成 Apache 下⼀个⾼度形象通⽤的开源数据湖⽅案。
Apache Iceberg ⽬前看则会显得绝对平庸⼀些,简略说社区关注度临时⽐不上 delta,性能也不如 Hudi 丰盛,但却是⼀个野⼼勃勃的项⽬,因为它具备⾼度形象和⾮常优雅的设计,为成为⼀个通⽤的数据湖⽅案奠定了良好基础。
2) 共同点
三者均为 Data Lake 的数据存储中间层,其数据管理的性能均是基于⼀系列的 meta ⽂件。Meta ⽂件的⾓⾊相似于数据库的 catalog\wal,起到 schema 治理、事务管理和数据管理的性能。与数据库不同的是,这些 meta ⽂件是与数据⽂件⼀起寄存在存储引擎中的,⽤户能够间接看到。这个做法间接继承了⼤数据分析中数据对⽤户可见的传统,然而⽆形中也减少了数据被不⼩⼼毁坏的危险。⼀旦删了 meta ⽬录,表就被毁坏了,复原难度很⼤。
Meta 蕴含有表的 schema 信息。因而零碎能够⾃⼰把握 schema 的变动,提供 schema 演变的⽀持。Meta ⽂件也有 transaction log 的性能(须要⽂件零碎有原⼦性和⼀致性的⽀持)。所有对表的变更都会⽣成⼀份新的 meta ⽂件,于是零碎就有了 ACID 和多版本的⽀持,同时能够提供拜访历史的性能。在这些⽅⾯,三者是雷同的。
3) 对于 Hudi
Hudi 的设计⽬标正如其名,Hadoop Upserts Deletes and Incrementals(原为 Hadoop Upserts anD Incrementals),强调了其次要⽀持 Upserts、Deletes 和 Incremental 数据处理,其次要提供的写⼊⼯具是 Spark HudiDataSource API 和⾃⾝提供的 HoodieDeltaStreamer,均⽀持三种数据写⼊⽅式:UPSERT,INSERT 和 BULK_INSERT。其对 Delete 的⽀持也是通过写⼊时指定⼀定的选项⽀持的,并不⽀持纯正的 delete 接⼝。
在查问⽅⾯,Hudi ⽀持 Hive、Spark、Presto。
在性能⽅⾯,Hudi 设计了 HoodieKey,⼀个相似于主键的货色。对于查问性能,⼀般需要是依据查问谓词⽣成过滤条件下推⾄ datasource。Hudi 这⽅⾯没怎么做⼯作,其性能齐全基于引擎⾃带的谓词下推和 partition prune 性能。
Hudi 的另⼀⼤特⾊是⽀持 Copy On Write 和 Merge On Read。前者在写⼊时做数据的 merge,写⼊性能略差,然而读性能更⾼⼀些。后者读的时候做 merge,读性能差,然而写⼊数据会⽐较及时,因⽽后者能够提供近实时的数据分析能⼒。最初,Hudi 提供了⼀个名为 run_sync_tool 的脚本同步数据的 schema 到 Hive 表。Hudi 还提供了⼀个命令⾏⼯具⽤于治理 Hudi 表。
4) 对于 Iceberg
Iceberg 没有相似的 HoodieKey 设计,其不强调主键。没有主键,做 update/delete/merge 等操作就要通过 Join 来实现,⽽ Join 须要有⼀个相似 SQL 的执⾏引擎。
Iceberg 在查问性能⽅⾯做了⼤量的⼯作。值得⼀提的是它的 hidden partition 性能。Hidden partition 意思是说,对于⽤户输⼊的数据,⽤户能够选取其中某些列做适当的变换(Transform)造成⼀个新的列作为 partition 列。这个 partition 列仅仅为了将数据进⾏分区,并不间接体现在表的 schema 中。
5) 对于 Delta
Delta 的定位是流批⼀体的 Data Lake 存储层,⽀持 update/delete/merge。因为出⾃ Databricks,spark 的所有数据写⼊⽅式,包含基于 dataframe 的批式、流式,以及 SQL 的 Insert、Insert Overwrite 等都是⽀持的(开源的 SQL 写暂不⽀持,EMR 做了⽀持)。不强调主键,因而其 update/delete/merge 的实现均是基于 spark 的 join 性能。在数据写⼊⽅⾯,Delta 与 Spark 是强绑定的,这⼀点 Hudi 是不同的:Hudi 的数据写⼊不绑定 Spark(能够⽤ Spark,也能够使⽤ Hudi ⾃⼰的写⼊⼯具写⼊)。
在查问⽅⾯,开源 Delta ⽬前⽀持 Spark 与 Presto,然而,Spark 是不可或缺的,因为 delta log 的解决须要⽤到 Spark。这意味着如果要⽤ Presto 查问 Delta,查问时还要跑⼀个 Spark 作业。更为好受的是,Presto 查问是基于 SymlinkTextInputFormat。在查问之前,要运⾏ Spark 作业⽣成这么个 Symlink ⽂件。如果表数据是实时更新的,意味着每次在查问之前先要跑⼀个 SparkSQL,再跑 Presto。为此,EMR 在这⽅⾯做了改良能够不用当时启动⼀个 Spark 工作。
在查问性能⽅⾯,开源的 Delta ⼏乎没有任何优化。
Delta 在数据 merge ⽅⾯性能不如 Hudi,在查问⽅⾯性能不如 Iceberg,是不是意味着 Delta ⼀⽆是处了呢?其实不然。Delta 的⼀⼤长处就是与 Spark 的整合能⼒,尤其是其流批⼀体的设计,配合 multi-hop 的 data pipeline,能够⽀持剖析、Machine learning、CDC 等多种场景。使⽤灵便、场景⽀持欠缺是它相⽐ Hudi 和 Iceberg 的最⼤长处。另外,Delta 号称是 Lambda 架构、Kappa 架构的改进版,⽆需关⼼流批,⽆需关⼼架构。这⼀点上 Hudi 和 Iceberg 是⼒所不迭的。
6) 总结
三个引擎的初衷场景并不完全相同,Hudi 为了 incremental 的 upserts,Iceberg 定位于⾼性能的剖析与牢靠的数据管理,Delta 定位于流批⼀体的数据处理。这种场景的不同也造成了三者在设计上的差异。尤其是 Hudi,其设计与另外两个相⽐差异更为显著。因而后⾯是趋同还筑起各⾃特长劣势壁垒未可知。
Delta、Hudi、Iceberg 三个开源项⽬中,Delta 和 Hudi 跟 Spark 的代码深度绑定,尤其是写⼊门路。这两个项⽬设计之初,都基本上把 Spark 作为他们的默认计算引擎了。⽽ Apache Iceberg 的⽅向⾮常动摇,主旨就是要做⼀个通⽤化设计的 Table Format。
它完满的解耦了计算引擎和底下的存储系统,便于多样化计算引擎和⽂件格局,很好的实现了数据湖架构中的 Table Format 这⼀层的实现,因而也更容易成为 Table Format 层的开源事实标准。
另⼀⽅⾯,Apache Iceberg 也在朝着流批⼀体的数据存储层倒退,manifest 和 snapshot 的设计,无效地隔离不同 transaction 的变更,⾮常⽅便批处理和增量计算。并且,Apache Flink 曾经是⼀个流批⼀体的计算引擎,⼆者都能够完满匹配,合⼒打造流批⼀体的数据湖架构。
Apache Iceberg 这个项⽬背地的社区资源⾮常丰盛。在国外,Netflix、Apple、Linkedin、Adobe 等公司都有 PB 级别的⽣产数据运⾏在 Apache Iceberg 上;在国内,腾讯这样的巨头也有⾮常庞⼤的数据跑在 Apache Iceberg 之上,最⼤的业务每天有⼏⼗ T 的增量数据写⼊。
必备 SQL 题
1. 第二高的薪水
编写一个 SQL 查问,获取 Employee
表中第二高的薪水(Salary)。
+----+--------+
| Id | Salary |
+----+--------+
| 1 | 100 |
| 2 | 200 |
| 3 | 300 |
+----+--------+
例如上述 Employee
表,SQL 查问应该返回 200
作为第二高的薪水。如果不存在第二高的薪水,那么查问应返回 null
。
+---------------------+
| SecondHighestSalary |
+---------------------+
| 200 |
+---------------------+
SELECT
IFNULL(
(SELECT DISTINCT Salary
FROM Employee
ORDER BY Salary DESC
LIMIT 1 OFFSET 1),
NULL) AS SecondHighestSalary
2. 分数排名
编写一个 SQL 查问来实现分数排名。
如果两个分数雷同,则两个分数排名(Rank)雷同。请留神,平分后的下一个名次应该是下一个间断的整数值。换句话说,名次之间不应该有“距离”。
+----+-------+
| Id | Score |
+----+-------+
| 1 | 3.50 |
| 2 | 3.65 |
| 3 | 4.00 |
| 4 | 3.85 |
| 5 | 4.00 |
| 6 | 3.65 |
+----+-------+
例如,根据上述给定的 Scores
表,你的查问应该返回(按分数从高到低排列):
+-------+------+
| Score | Rank |
+-------+------+
| 4.00 | 1 |
| 4.00 | 1 |
| 3.85 | 2 |
| 3.65 | 3 |
| 3.65 | 3 |
| 3.50 | 4 |
+-------+------+
select Score,
dense_rank() over(order by Score desc) `rank`
from Scores
3. 间断呈现的数字
编写一个 SQL 查问,查找所有至多间断呈现三次的数字。
+----+-----+
| Id | Num |
+----+-----+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 2 |
| 5 | 1 |
| 6 | 2 |
| 7 | 2 |
+----+-----+
例如,给定下面的 Logs
表,1
是惟一间断呈现至多三次的数字。
+-----------------+
| ConsecutiveNums |
+-----------------+
| 1 |
+-----------------+
select distinct Num ConsecutiveNums
from
(
select
Num,
lead(Num,1,null) over(order by id) n2,
lead(Num,2,null) over(order by id) n3
from Logs
)t1
where Num = n2 and Num = n3
因文章最多只能 50000 字,已达到下限,故文章做了删减操作。
获取本文《2023 最新大数据面试宝典》完整版带目录的 PDF 文档,请搜寻公众号【五分钟学大数据】,在对话框发送 2023 面试,即可获取。
参考链接:
2023 版最新最弱小数据面试宝典,附答案解析