Spark Release 2.2.0 最新版本发布,Spark 2.2.0是Spark 2.x中第一个在生产环境可以使用的版本,对于Spark具有里程碑意义

来源:互联网 发布:vc map数据如何拷贝 编辑:程序博客网 时间:2024/05/20 19:32

第2章 Spark 2.X技术及原理

Apache官方网站于2017711日发布了Spark Release 2.2.0版本, Apache Spark 2.2.0版本是Spark 2.x系列上的第三个版本。Spark 2.2.0Spark 2.x中第一个在生产环境可以使用的版本,对于Spark具有里程碑意义。Spark 2.2.0版本中 Structured Streaming 的实验性标记(experimental tag)已经被移除,此版本更多地侧重于系统的可用性(usability)、稳定性(stability)以及代码的polish,解决了1100tickets。此外,只要安装pyspark,在Spark 2.2.0版本中PySpark可用于pypiSpark 2.2.0版本移除了对 Java 7 以及 Hadoop 2.5及其之前版本的支持,移除了对Python 2.6的支持。

Apache Spark2.2.0版本的一些新功能:

·          Core and Spark SQL

·          Structured Streaming

·          MLlib

·          SparkR

·          GraphX

·          Deprecations

·          Changes of behavior

·          Known Issues

·          Credits

如无特殊说明,本书所有内容都基于最新最稳定的Spark 2.2.0版本的源代码编写,为体现Spark源代码的演进过程,部分核心源代码在Spark 1.6.xSpark 2.1.x源码的基础上,新增Spark 2.2.0版本的源代码,便于读者系统比对、研习Spark源码。

2.1   Spark2.X综述  

Spark 2.0中更新发布了新的流处理框架(Structured Streaming);对于API的更新,Spark 2.0版本API的更新主要包括DataFrame、DataSet、SparkSession、累加器API、Aggregator API等API的变动。

2.1.1 连续应用程序  

自从Spark得到广泛使用以来,其流处理框架Spark Streaming也逐渐地吸引到了很多用户,得益于其易用的高级API和一次性语义,使其成为使用最广泛的流处理框架之一。但是我们不仅仅需要流处理来构建实时应用程序,很多时候我们的应用程序只有一部分需要用到流处理,对于这种应用程序,Databricks公司把它称为ContinuousApplication(实时响应数据的端到端的应用程序),也就是连续的应用程序。在Continuous Application中会有许多难点,比如数据交互的完整性、流数据与离线数据的结合使用、在线机器学习等。

Spark2.0最重磅的更新是新的流处理框架——Structured Streaming。它允许用户使用DataFrame/DataSetAPI编写与离线批处理几乎相同的代码,便可以作用到流数据和静态数据上,引擎会自动增量化流数据计算,同时保证了数据处理的一致性,并且提供了和存储系统的事务集成。

2.1.2 新的API  

在Spark2.0版本的API中共有如下几个API的变动:

1)统一了DataFrame和DataSet。现在DataFrame不再是一个独立的类,而是作为DataSet[Row]的别名定义在org.apache.spark.sql这个包对象中。

sql\package.scala源代码如下:

1.           packageobject sql {

2.          

3.           /**

4.            * Converts a logical plan into zero or moreSparkPlans.  This API is exposed forexperimenting

5.            * with the query planner and is not designedto be stable across spark releases. Developers

6.            * writing libraries should instead considerusing the stable APIs provided in

7.            * [[org.apache.spark.sql.sources]]

8.            */

9.           @DeveloperApi

10.        @InterfaceStability.Unstable

11.        type Strategy = SparkStrategy

12.       

13.        type DataFrame = Dataset[Row]

14.      }

2)加入了SparkSession用于替换DataFrame和Dataset API的SQLContext和HiveContext(这两个API仍然可以使用)。

3)为SparkSession为SparkSQL加入一个新的,精简的配置参数–RuntimeConfig,可以用来设置和获得跟SparkSQL有关的Spark或者Hadoop设置。

SparkSession.scala源代码:

1.           /**

2.            * Runtime configuration interface for Spark.

3.            *

4.            * This is the interface through which theuser can get and set all Spark and Hadoop

5.            * configurations that are relevant to SparkSQL. When getting the value of a config,

6.            * this defaults to the value set in theunderlying `SparkContext`, if any.

7.            *

8.            * @since 2.0.0

9.            */

10.        @transient lazy val conf: RuntimeConfig = newRuntimeConfig(sessionState.conf)

 

4)更简单,更高性能的累加器API。

5)用于DataSet中类型化聚合的新的改进的AggregatorAPI。

2.2   Spark2.X Core  

         本节讲解Tungsten引擎的新特性;SparkSession使用方法;以及一个更加简单和更高性能的累加器API的使用。

2.2.1 第二代Tungsten引擎

Spark备受瞩目的原因之一在于它的高性能,Spark开发者为了保持这个优势一直在不断的进行各种层次的优化,其中最令人兴奋的莫过于钨丝计划(ProjectTungsten),因为钨丝计划的提出给Spark带来了极大的性能提升,并且在一定程度上引导了Spark的发展方向。

Spark是使用Scala和Java语言开发的,不可避免的运行JVM之上,当然内存管理也是依赖于JVM的内存管理机制,而对于大数据量的基于内存的处理,JVM对象模型对内存的额外开销,以及频繁的GC和Full GC都是非常致命的问题。另外,随着网络带宽和磁盘IO的不断提升,内存和CPU又重新作为性能瓶颈受到关注,JVM对象的序列化、反序列化带来的性能损耗急需解决。Spark1.5版本加入的钨丝计划从3大方面着手解决这些问题:

1) 统一内存管理模型和二进制处理(BinaryProcessing)。统一内存管理模型来代替

之前基于JVM的静态内存管理,引入Page来管理堆内存和堆外内存(on-heap和off-heap),并且直接操作内存中的二进制数据而不是Java对象,很大程度上摆脱了JVM内存管理的限制。

2) 基于缓存感知的计算(Cache-aware Computation)。Spark内存读取操作也会带来

一部分性能损耗,钨丝计划便设计了缓存友好的算法和数据结构来提高缓存命中率,充分利用L1/L2/L3三级缓存,大幅提高了内存读取速度,进而缩短了内存中的整个计算过程的时间。

3) 代码生成(Code Generation)。在JVM中,所有代码的执行由解释器来一步步的

解释执行,CodeGeneration这一功能则在Spark运行时动态生成用于部分算子求值的bytecode,减少了对基础数据类型的封装,并且缓解了调用虚函数的额外开销。

Spark2.0升级了第二代Tungsten引擎。其中最重要的一点是把CodeGeneration作用于全阶段的SparkSQL和DataFrame之上,(即全阶段代码生成Whole Stage Code Generation),为常见的算子带来了十倍左右的性能提升!

2.2.2 SparkSession  

加入SparkSession,取代原来的SQLContext和HiveContext,为了兼容两者仍然保留。SparkSession使用方法如下:

1.           SparkSession.builder()

2.               .master("local")

3.               .appName("Word Count")

4.               .config("spark.some.config.option","some-value")

5.               .getOrCreate()

 

首先获得SparkSession的Builder,然后使用Builder来为SparkSession设置参数,最后使用getOrCreate方法来检测当前线程是否有一个已经存在的Thread-local级别的SparkSession,如果有则返回它,没有则检测是否有全局级别的SparkSession,有则返回没有则创建新的SparkSession。

在程序中如果要使用SparkContext时可以调用sparkSession.sparkContext即可。在程序的最后我们需要调用sparkContext.stop方法,这个方法会调用sparkContext.stop来关闭sparkContext。

从Spark2.0开始,DataFrame和DataSet既可以容纳静态、有限的数据,也可以容纳无限的流数据,所以用户也可以使用SparkSession像创建静态数据集一样来创建流式数据集,并且可以使用相同的操作算子。这样整合了实时流处理和离线处理的框架,结合其它容错、扩展等特性形成了完整的Lambda架构。

 

2.2.3 Accumulator API 

Spark2.0引入了一个更加简单和更高性能的累加器API,比如在1.X版本中可以这样使用累加器:

1.         //定义累加器,这里直接使用SparkContext内置的累加器,设置初始值为0,名字为"My Accumulator"

2.         val accum = sc.accumulator(0,"My Accumulator")

3.         //计算值

4.         sc.parallelize(Array(1, 2, 3,4)).foreach(x => accum += x)

5.         //获取累加器的值,(Executor上面只能对累加器进行累加操作,只有Driver才能读取累加器的值,Driver读取值的时候会把各个Executor上存储的本地累加器的值加起来),这里结果是10。

6.         accum.value

在2.X版本里使用SparkContext里内置的累加器:

1.          //与1.X不同的是需要指定累加器的类型,目前SparkContext有Long类型和Double类型的累加器可以直接使用(不需要指定初始值)。

2.         val accum =sc.longAccumulator("My Accumulator")

3.         sc.parallelize(Array(1, 2, 3,4)).foreach(x => accum.add(x))

4.         print(accum.value)

 

只使用SparkContext里内置的累加器功能肯定不能满足略微复杂的业务类型,此时我们就可以自定义累加器。在1.X版本的做法是(下面是官网的例子):

1.          //继承AccumulatorParam[Vector],返回类型为Vector。

2.         object VectorAccumulatorParamextends AccumulatorParam[Vector] {

3.         //定义“零”值,这里把传入的初始值的size作为“零”值。

4.         def zero(initialValue: Vector):Vector = {

5.             Vector.zeros(initialValue.size)

6.           }

7.         //定义累加操作的计算方式

8.           def addInPlace(v1: Vector, v2: Vector):Vector = {

9.             v1 += v2

10.        }

11.      }

 

上面的累加器元素和返回类型是相同的,在Scala中还有另外一种方式来自定义累加器,用户只需要继承Accumulable,就可以把元素和返回值定义为不同的类型,这样我们就可以完成添加操作(比如像Int类型的List里添加整数,此时元素为Int类型,而返回类型为List)。

在Spark2.X中,加入了一个新的抽象类--AccumulatorV2,继承这个类要实现几个方法:

add方法:指定元素相加操作。

copy方法:指定对自定义的累加器的拷贝操作。

isZero方法:返回该累加器的值是否为“零”。

merge方法:合并两个相同类型的累加器。

reset方法:重置累加器。

value方法:返回累加器当前的值。

     在重写这几个方法之后,只需实例化自定义累加器,并连同累加器名字一起传给sparkContext.register方法即可。

我们来简单实现一个把字符串合并为数组的累加器:

1.          //首先要继承AccumulatorV2,并指定输入为String类型,输出为ArrayBuffer[String]

2.         class MyAccumulator extendsAccumulatorV2[String, ArrayBuffer[String]] {

3.         //设置累加器的结果,类型为ArrayBuffer[String]

4.           private var result = ArrayBuffer[String]()

5.          

6.         //判断累加器当前值是否为“零值”,这里我们指定如果result的size为0则累加器的当前值是“零值”

7.           override def isZero: Boolean =this.result.size == 0

8.          

9.         //copy方法设置为新建本累加器,并把result赋给新的累加器

10.        override def copy(): AccumulatorV2[String,ArrayBuffer[String]] = {

11.          val newAccum = new MyAccumulator

12.          newAccum.result = this.result

13.          newAccum

14.        }

15.      //reset方法设置为把result设置为新的ArrayBuffer

16.      override def reset(): Unit =this.result == new ArrayBuffer[String]()

17.       

18.      //add方法是把传进来的字符串添加到result内

19.      override def add(v: String):Unit = this.result += v

20.       

21.      //merge方法:把两个累加器的result合并起来

22.      override def merge(other:AccumulatorV2[String, ArrayBuffer[String]]): Unit = {

23.            result.++=:(other.value)

24.          }

25.      //value方法返回result

26.        override def value: ArrayBuffer[String] =this.result

27.      }

28.      接着在main方法里使用累加器:

29.      val Myaccum = newMyAccumulator()

30.       

31.      //向SparkContext注册累加器

32.          sc.register(Myaccum)

33.       

34.      //把“a”,“b”“c”“d”添加进累加器的result这个数组并打印出来

35.          sc.parallelize(Array("a","b","c","d")).foreach(x=> Myaccum.add(x))

36.          println(Myaccum.value)

 

运行结果显示的ArrayBuffer里的值顺序是不固定的,取决于各个Executor的值到达Driver的顺序。

 

2.3   Spark2.X SQL   

Spark 2.0通过对SQL2003的支持增强了SQL功能,Catalyst新引擎提升了Spark查询优化的速度;本节对DataFrame和Dataset API、时间窗口进行了讲解。   

Apache Spark2.2.0版本中核心和Spark SQL的更新:

1、  API更新

·          SPARK-19107: Supportcreating hive table with DataFrameWriter and Catalog

·          SPARK-13721: Add support forLATERAL VIEW OUTER explode()

·          SPARK-18885: Unify CREATE TABLEsyntax for data source and hive serde tables

·          SPARK-16475: Added BroadcastHints BROADCAST, BROADCASTJOIN, and MAPJOIN, for SQL Queries

·          SPARK-18350: Support sessionlocal timezone

·          SPARK-19261: Support ALTERTABLE table_name ADD COLUMNS

·          SPARK-20420: Add events tothe external catalog

·          SPARK-18127: Add hooks andextension points to Spark

·          SPARK-20576: Support generichint function in Dataset/DataFrame

·          SPARK-17203: Data sourceoptions should always be case insensitive

·          SPARK-19139: AES-basedauthentication mechanism for Spark

2、  性能优化和系统稳定性

基于成本的优化:

·          SPARK-17075 SPARK-17076SPARK-19020 SPARK-17077 SPARK-19350: Cardinality estimation for filter, join,aggregate, project and limit/sample operators

·          SPARK-17080: Cost-based joinre-ordering

·          SPARK-17626: TPC-DS performanceimprovements using star-schema heuristics

·          SPARK-17949: Introduce a JVMobject based aggregate operator

·          SPARK-18186: Partialaggregation support of HiveUDAFFunction

·          SPARK-18362 SPARK-19918:File listing/IO improvements for CSV and JSON

·          SPARK-18775: Limit the maxnumber of records written per file

·          SPARK-18761: Uncancellable /unkillable tasks shouldn’t starve jobs of resources

·          SPARK-15352: Topology awareblock replication

3、  其他的一些变化

·          SPARK-18352: Support forparsing multi-line JSON files

·          SPARK-19610: Support forparsing multi-line CSV files

·          SPARK-21079: Analyze TableCommand on partitioned tables

·          SPARK-18703: Drop StagingDirectories and Data Files after completion of Insertion/CTAS againstHive-serde Tables

·          SPARK-18209: More robustview canonicalization without full SQL expansion

·          SPARK-13446: [SPARK-18112]Support reading data from Hive metastore 2.0/2.1

·          SPARK-18191: Port RDD API touse commit protocol

·          SPARK-8425:Add blacklistmechanism for task scheduling

·          SPARK-19464: Remove supportfor Hadoop 2.5 and earlier

·          SPARK-19493: Remove Java 7support

 

2.3.1 Spark SQL 

Spark 2.0通过对SQL2003的支持大幅增强了SQL功能,现在可以运行所有99个TPC-DS查询。这个版本中的SparkSQL主要有以下几点改进:

1)  引入了支持ANSISQL和HiveSQL的本地解析器。

2)  本地实现DDL命令。

3)  支持非相关标量子查询。

4)  在Where与having条件中,支持(not)in和(not)exists。

5)  即使Spark没有和Hive集成搭建,SparkSQL也支持它们一起搭建时的除了Hive连接、Hive UDF(UserDefinedFunction用户自定义函数)和脚本转换之外的大部分功能。

6)  Hive式的分桶方式的支持。

 

另外Catalyst查询优化器对于常见的工作负载也有了很多提升,对比如nullability propagation之类的查询做了更好的优化。Catalyst查询优化器从最早的应用于SparkSQL到现在应用于DataSetAPI,对Spark程序的高效率运行起到了非常重要的作用,并且随着DataSetAPI的流行,以及优化器自身的不断演进,未来肯定会对Spark的所有框架带来更高的执行效率。

2.3.2 DataFrame和Dataset API 

在Spark 1.x版本中,DataFrame的API存在很多问题,比如说DataFrame不是类型安全的(nottype-safe)、不是面向对象的(notobject-oriented),为了克服这些问题,Spark在1.6版本引入了Dataset并在2.0版本的Scala和Java中将二者进行了统一(在Python和R中,由于缺少类型安全性,DataFrame仍是主要的编程接口),DataFrame成为了DataSet[Row]的别名,而且Spark2.0版本为DataSet的类型化聚合加入了一个新的聚合器,让基于DataSet的聚合更加高效。

在2.1版本中DataFrame和Dataset API晋升为稳定的API,也就是说可以在生产环境中使用它们,且后续会基于向后兼容的前提下不断强化。

DataSetAPI是High-LevelAPI,有更高的抽象级别,与RDDAPI这样的Low-LevelAPI相比更加易用,它对于提升用户的工作效率,以及提高程序的可读性而言意义非凡。由于WholeStageCodeGeneration的引入,SparkSQL和DataSetAPI中的常见算子的性能提升了2到10倍。加上Catalyst查询优化器和Tungsten的帮助,用户可以不用过多的关注对程序优化,也能获得很好的执行效率。

所以毋庸置疑地,这样一种简单高效的API将成为Spark未来主流的编程接口!

 

2.3.3 Timed window    

对于经常用到复杂SQL的用户而言,窗口函数一直以来都是不可或缺的,在Spark2.X版本中通过对Hive中的窗口函数的本地化实现,来使用spark的内存管理机制,从而提升了窗口函数的性能。

2.4 Spark 2.X Streaming 

Spark2.0为我们带来了一个新的流处理框架Structured Streaming,这是一个基于Spark SQL和Catalyst优化器构建的高级流API。它允许用户使用与操作静态数据的DataFrame / Dataset API对流数据进行编程,利用Catalyst优化器自动地增量化查询计划。并且它不但支持流数据的不断写入,还支持其他的静态数据的插入。

Apache Spark2.2.0版本中Structured Streaming的更新:

1、    整体可用性:

·          SPARK-20844: The StructuredStreaming APIs are now GA and is no longer labeled experimental

2、  Kafka 提升

·          SPARK-19719: Support forreading and writing data in streaming or batch to/from Apache Kafka

·          SPARK-19968: Cached producerfor lower latency kafka to kafka streams.

3、    API 更新:

·          SPARK-19067: Support forcomplex stateful processing and timeouts using [flat]MapGroupsWithState

·          SPARK-19876: Support for onetime triggers

4、    其它的一些变化:

·          SPARK-20979: Rate source fortesting and benchmarks

 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 上海大牌拍中了怎么办 买新车牌下不了怎么办 临沂上小学没报上名怎么办 早教中心倒闭了怎么办 企业税没交联系不上法人怎么办 企业被拉黑法人联系不到怎么办 支票根写错了怎么办 月结客户不付款怎么办 退市整理期过了怎么办 老板跑了财务负责人怎么办 在南京加入嘀嘀代驾怎么办 苹果盗刷支付宝怎么办 街电支付宝掉了怎么办 转转上号器没有苹果版的怎么办 安卓6不支持的应用怎么办 银行卡被存款机吞了怎么办 去银行卡存款机器故障怎么办 银行卡存款没有存进去怎么办 被黑网站黑钱了怎么办 饿了吗账户异常怎么办 单位里有人整你怎么办 乌鲁木齐信息采集结束后怎么办 头发很长时间不长怎么办啊 打嘟噜时间不长怎么办 阴茎勃起的时间不长怎么办 睡觉的时间不长怎么办 每次锻炼时间不长怎么办 微信好友不知道是谁怎么办 就一个软件闪退怎么办 葫芦侠修改闪退怎么办 戴尔游匣磁盘占用100怎么办 步步高家教机扫描笔不亮怎么办 社保卡手机号换了怎么办 香港公司进出口没有申报怎么办 智能电视右上角网络未连接怎么办 电子秤按键板不好用怎么办失灵 桑塔纳车钥匙锁车里了怎么办 舌头上有锯齿印怎么办 夏天有脚气脚臭怎么办 xp分辨率太高黑屏怎么办 农村淘宝标识类目没了怎么办