大数据实践解析(下):Spark的读写流程分析
导读:
众所周知,在大数据/数据库领域,数据的存储格式直接影响着系统的读写性能。spark是一种基于内存的快速、通用、可扩展的大数据计算引擎,适用于新时代的数据处理场景。在“大数据实践解析(上):聊一聊spark的文件组织方式”中,我们分析了spark的多种文件存储格式,以及分区和分桶的设计。接下来,本文通过简单的例子来分析在Spark中的读写流程,主要聚焦于Spark中的高效并行读写以及在写过程中如何保证事务性。
1、文件读
如何在Spark中做到高效的查询处理呢?这里主要有两个优化手段:
1)减少不必要的数据处理。数据处理涉及文件的IO以及计算,它们分别需要耗费大量的IO带宽和CPU计算。在实际的生产环境中,这两类资源都是有限的,同时这些操作十分耗时,很容易成为瓶颈,所以减少不必要的数据处理能有效提高查询的效率;
以下面的查询为例:
spark.read.parquet("/data/events")
.where("year = 2019")
.where("city = 'Amsterdam'")
.select("timestamp")
由于在events表中按照year字段做了分区,那么首先通过 year 字段我们就可以过滤掉所有year字段不为 2019 的分区:

因为文件是parquet的文件格式,通过谓词下推可以帮助我们过滤掉 city 字段不是 "Amsterdam" 的 row groups;同时,由于我们的查询最终需要输出的投影字段只有 "timestamp" ,所以我们可以进行列裁剪优化,不用读取其他不需要的字段,所以最终整个查询所读的数据只有剩下的少部分,过滤掉了大部分的数据,提升了整体的查询效率:

2)并行处理,这里主流的思想分为两类:任务并行和数据并行。任务并行指充分利用多核处理器的优势,将大的任务分为一个个小的任务交给多个处理器执行并行处理;数据并行指现如今越来越丰富的SIMD指令,一次动作中处理多个数据,比如AVX-512可以一次处理16个32bit的整型数,这种也称为向量化执行。当然,随着其他新硬件的发展,并行也经常和GPU联系在一起。本文主要分析Spark读流程中的任务并行。
下面是Spark中一个读任务的过程,它主要分为三个步骤:

(1)将数据按照某个字段进行hash,将数据尽可能均匀地分为多个大小一致的Partition;
(2)发起多个任务,每个任务对应到图中的一个Executor;
(3)任务之间并行地进行各自负责的Partition数据读操作,提升读文件效率。
2、文件写
Spark写过程的目标主要是两个:并行和事务性。其中并行的思想和读流程一样,将任务分配给不同的Executor进行写操作,每个任务写各自负责的数据,互不干扰。

为了保证写过程的事务性,Spark在写过程中,任何未完成的写都是在临时文件夹中进行写文件操作。如下图所示:写过程中,results文件夹下只存在一个临时的文件夹_temporary;不同的job拥有各自job id的文件目录,相互隔离;同时在各目录未完成的写操作都是存在临时文件夹下,task的每次执行都视为一个taskAttempt,并会分配一个task attempt id,该目录下的文件是未commit之前的写文件。

当task完成自己的写任务时,会进行commit操作,commit成功后,该任务目录下的临时文件夹会移动,写文件移到对应的位置,表示该任务已经写完成。


当写任务失败时,首先需要删除之前写任务的临时文件夹和未完成的文件,之后重新发起该写任务(relaunch),直到写任务commit提交完成。

整个任务的描述可用下图表示,如果commit成功,将写完成文件移动到最终的文件夹;如果未commit成功,写失败,删除对应的文件,重新发起写任务。当写未完成时,所有写数据都存在对应的临时文件中,其他任务不可见,直到整个写commit成功,保证了写操作的事务性。

当所有任务完成时,所有的临时文件夹都移动,留下最终的数据文件,它是最终commitJob之后的结果。

本文介绍的算法是 FileOutputCommitter v1的实现,它的commitJob阶段由Driver负责依次移动数据到最终的目录。但是在当前广泛应用的云环境下,通常采取存算分离的架构,这时数据一般存放在对象存储中(如AWS S3,华为云OBS),Spark FileOutputCommitter中的数据移动并不像HDFS文件系统移动那么高效,v1的commitJob过程耗时可能会非常长。为了提升FileOutputCommitter 的性能,业界提出了FileOutputCommitter v2的实现,它们可以通过 spark.hadoop.mapreduce.fileoutputcommitter.algorithm.version = 1或2 配置项来设置,它和v1的不同点在于,每个Task在commitTask时就将文件移动到最终的目录,而在commitJob时,Driver只需要负责将Task留下来的空目录删除,这样相比 v1 带来好处是性能提升, 但是由于commit task时直接写最终目录,在执行未完成时,部分数据就对外可见。同时,如果job失败了,成功的那部分task产生的数据也会残留下来。这些情况导致spark写作业的事务性和一致性无法得到保障。
其实v1也不完全一定能保证数据一致性,文件移动过程中完成的数据对外是可见的,这部分数据外部已经可以读取,但是正在移动和还未移动的数据对外是不可见的,而在云环境下,这个移动耗时会进一步加长,加重数据不一致的情况。
那么有没有能够使得Spark 分析在云环境下也可以保证数据的事务性和一致性的解决方案呢?华为云数据湖探索DLI(Data Lake Insight)改进了v1和v2这两种算法,使得Spark 分析在云环境下也可以保证数据的事务性和一致性,同时做到高性能,并且完全兼容Apache Spark和Apache Flink生态, 是实现批流一体的Serverless大数据计算分析服务,欢迎点击体验。
参考
【1】Databricks. 2020. Apache Spark's Built-In File Sources In Depth - Databricks. [online] Available at: <https://databricks.com/session_eu19/apache-sparks-built-in-file-sources-in-depth>.
大数据实践解析(下):Spark的读写流程分析的更多相关文章
- 大数据系列文章-Hadoop的HDFS读写流程(二)
在介绍HDFS读写流程时,先介绍下Block副本放置策略. Block副本放置策略 第一个副本:放置在上传文件的DataNode:如果是集群外提交,则随机挑选一台磁盘不太满,CPU不太忙的节点. 第二 ...
- spark block读写流程分析
之前分析了spark任务提交以及计算的流程,本文将分析在计算过程中数据的读写过程.我们知道:spark抽象出了RDD,在物理上RDD通常由多个Partition组成,一个partition对应一个bl ...
- 大数据基础知识问答----spark篇,大数据生态圈
Spark相关知识点 1.Spark基础知识 1.Spark是什么? UCBerkeley AMPlab所开源的类HadoopMapReduce的通用的并行计算框架 dfsSpark基于mapredu ...
- 大数据为什么要选择Spark
大数据为什么要选择Spark Spark是一个基于内存计算的开源集群计算系统,目的是更快速的进行数据分析. Spark由加州伯克利大学AMP实验室Matei为主的小团队使用Scala开发开发,其核心部 ...
- 老李分享:大数据框架Hadoop和Spark的异同 1
老李分享:大数据框架Hadoop和Spark的异同 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨 ...
- Hadoop优势,组成的相关架构,大数据生态体系下的模式
Hadoop优势,组成的相关架构,大数据生态体系下的模式 一.Hadoop的优势 二.Hadoop的组成 2.1 HDFS架构 2.2 Yarn架构 2.3 MapReduce架构 三.大数据生态体系 ...
- 大数据实践:ODI 和 Twitter (二)
大数据实践:ODI和Twitter(二) 在前面的文章中,我们已经使用flume将数据从twitter抓取到Hive中,现在我们来看看ODI(Oracle Data Integrator)如何在HIV ...
- 大数据入门第二十二天——spark(一)入门与安装
一.概述 1.什么是spark 从官网http://spark.apache.org/可以得知: Apache Spark™ is a fast and general engine for larg ...
- 大众点评的大数据实践-CSDN.NET
大众点评的大数据实践-CSDN.NET 大众点评的大数据实践 爬虫工程师成大数据时代的"宠儿" - 杭州新闻中心 - 杭州网 爬虫工程师成大数据时代的"宠儿"
- S3C6410 SPI全双工读写流程分析(原创)【转】
转自:http://blog.csdn.net/hustyangju/article/details/21165721 原创博文,知识共享!转载请注明出处:http://blog.csdn.net/h ...
随机推荐
- Dash 2.14版本开始支持动态回调注册!
本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/dash-master 大家好我是费老师,就在昨晚,Dash框架发布了其2.14.0新版本,新增的功能 ...
- 拿到开发板需要做的事情 -- 配置Python环境
1.查看系统时间 date -R 2.修改系统时间 windows上时间项目时间正常,Ubuntu16.04上时间错误 - 贾斯丁哔哔 - 博客园 (cnblogs.com) 3.安装pip3 sud ...
- 数据结构-线性表-单循环链表(使用尾指针)(c++)
目录 单循环链表 说明 注意 (一)无参构造函数 (二)有参构造函数 (三)析构函数 (四)获取长度 (五)打印数组 (六)获取第i个元素的地址 (七)插入 (八)删除 (九)获取值为x的元素的位置 ...
- 在centos7上使用 docker安装mongodb挂载宿主机以及创建其数据库的用户名和密码(最新版本)
前言 因为博主在使用docker安装mongodb并挂载时,发现在网上搜了好多都是以前版本的mongodb,并且按照他们操作总是在进入mongodb出问题,博主搞了好久终于弄好了,故写下博客,供有需要 ...
- Acwing127周赛第三题 构造矩阵 (套路)
题目链接:构造矩阵 题目描述 我们希望构造一个 n×m 的整数矩阵. 构造出的矩阵需满足: 每一行上的所有元素之积均等于 k. 每一列上的所有元素之积均等于 k. 保证 k 为 1 或 −1. 请你计 ...
- 【PySide6】QChart笔记(二)—— QBarSeries的使用
一.QBarSeries简介 1. 官方描述 https://doc.qt.io/qtforpython-6/PySide6/QtCharts/QBarSeries.html [译注:官方文档内容过于 ...
- decltype关键词
简述 decltype 是 C++11 新增的一个关键字,它和 auto 的功能一样,都用来在编译时期进行自动类型推导. decltype 是"declare type"的缩写,译 ...
- python函数str()避免类型错误
python中当输出需要拼接字符串(char)和整数(int)时,需要用到str()函数 如果编写如下代码: age = 23 print("Happy " + age +&quo ...
- Spring配置文件的魔法炼金术:如何制造容器化时代的完美配方
前言 基于现代服务的云原生十二要素理论,我们在采用容器化部署时,要保证同一个镜像可以满足不同环境的部署要求,而不是不同环境打包不同的镜像.本文档主要介绍一种基于spring框架的满足不同环境配置的编译 ...
- 【Android】使用litepal实现数据库的创建和升级
1.配置litepal 配置过程见:2.进行创建和升级数据库,可以省略sql语句的录入 定义一个Note类,代码如下 接下来将note类添加到映射模型列表当中,修改litepal.xml中的代码.如下 ...