一. Spark 新特性

  1. DataFrame = Dataset[Row]
  2. SparkSession:统一SQLContext和HiveContext,新的上下文入口
  3. 支持缓存和程序运行的堆外内存管理
  4. Accumulator功能增强:便捷api、web ui支持、性能更高
  5. whole-stage code generation
    Spark 2.0中配备了第二代Tungsten引擎,通过在运行期间优化那些拖慢整个查询的代码到一个单独的函数中(复杂的代码可能会打包到多个函数中),消除虚拟函数的调用以及利用CPU寄存器来存放那些中间数据
    其实现方式是在可能的情况下将把不同的Operator放在一起生成一个大块的处理函数。这样的好处是,去掉了冗余的operator之间的数据传递(这个可能是性能开销的大头),并且一个大的代码段不跨越函数边界,将更有可能被JVM JIT优化。终极目标是,生成的代码和手写代码有近似的速度。
    explain()可以看到通过whole-stage code generation生成的代码的执行计划,*号表示自动生成的代码
    eg:
select id + 1 from students where id <> 0;
复制代码

上面的Plan的计算部分将会有两个Operator:id+1对应Projection Operator,id <> 0对应Filter Operator。新的Spark代码生成可以将这两个部分合并生成一个大的代码块进行计算

  1. vectorization
    只有在无法使用whole-stage code generation技术时(如action算子复杂,使用第三方组件代码),可以使用vectorization技术
    核心思想是:不是一次只处理一行数据,而是将许多行的数据分别组成batches,而且采用列式格式存储;然后每个算子对每个batch进行简单的循环来遍历其中的数据。所以每次调用next()函数都会返回一批的元组,这样可以分摊虚函数调用的开销。采用了这些措施之后,这些简单的循环也会使得编译器和CPU运行的更加高效。
    vectorization仍然需要将临时数据存放在内存中而不是存放在CPU的寄存器中。所以只有在无法使用Whole-stage code-generation技术的情况下才会使用vectorization技术。用在例如Parquet Reader的解码部分
  2. 结构化流 Structured Streaming

1.1 spark1 VS spark2

Spark2.x重点改造的是Tungsten Engine、Dataframe/Dataset以及Structured Streaming

Spark 1.x:Spark Core(RDD)、Spark SQL(SQL+Dataframe+Dataset)、Spark Streaming、Spark MLlib、Spark Graphx

Spark 2.x:Spark Core(RDD)、Spark SQL(ANSI-SQL+Subquery+Dataframe/Dataset)、Spark Streaming、Structured Streaming、Spark MLlib(Dataframe/Dataset)、Spark Graphx、Second Generation Tungsten Engine(Whole-stage code generation+Vectorization)

1.2 RDD使用场景

  1. 底层操作
    手动管理RDD的分区,底层调优,troubleshooting
  2. 处理非结构化数据
    如多媒体数据,文本数据
  3. 不使用第二代tungsten引擎提供的whole-stage code generation等性能优化技术

1.3 Dataset VS RDD

RDD的序列化机制是基于Java序列化机制或者是Kryo的,而Dataset的序列化机制基于一种特殊的Encoder来将对象进行高效序列化,以进行高性能处理或者是通过网络进行传输。
Dataset除了Encoder,也同时支持Java序列化机制,但是encoder的特点在于动态的代码生成,同时提供一种特殊的数据格式,来让spark不将对象进行反序列化,即可直接基于二进制数据执行一些常见的操作,比如filter、sort、hash等。

1.4 Dataframe/Dataset使用场景

  1. 需要更加丰富的计算语义,high-level的抽象语义,以及domain-specific API。
  2. 计算逻辑需要high-level的expression. filter. map. aggregation. average. sum. SQL. 列式存储. lambda表达式等语义,来处理半结构化或结构化的数据。
  3. 需要高度的编译时以及运行时的类型安全保障。
  4. 想要通过Spark SQL的Catalyst(SparkSQL的优化器,类似数据库引擎的执行计划优化模块)和Spark 2.x的第二代Tungsten引擎来提升性能。
  5. 想要通过统一的API来进行离线,流式,机器学习等计算操作。
  6. R或Python用户,只能使用Dataframe。

1.5 Dataframe VS Dataset

Dataframe = Dataset[Row]

  • untyped API(Dataframe)
    Row就是一个untyped类型的对象,因为Row是类似于数据库中的一行,只知道里面有哪些列,但是有些列即使不存在,也可以这对这些不存在的列进行操作。因此其被定义为untyped,即弱类型
    DataFrame由于接近SQL的API模型,将完全享受Catalyst优化器,而原生的RDD由于过于自由的API,则无法享受这一优化
    DataFrame因为解析的时候Schema还没有注入,无法完整静态类型检查,因此无法做到类型安全。
  • typed API(Dataset)
    Dataset[T]本身,是一种typed类型的API,其中的Object通常都是自定义的typed类型的对象,因为对象是自定义的,所以包括字段命名以及字段类型都是强类型的
    DataSet支持lambda API,有类型支持并享受Catalyst优化。又由于它也有Schema支持,因此存储的时候能根据类型序列化到Native内存上(而非Java堆空间),无须使用Java Object,因此速度更快更省内存

二. spark SQL

Dataframe untyped操作

val df = spark.read.json("people.json")
df.show()
df.printSchema()
df.select("name").show()
df.select($"name", $"age" + 1).show()
df.filter($"age" > 21).show()
df.groupBy("age").count().show()

df.createOrReplaceTempView("people")
val sqlDF = spark.sql("SELECT * FROM people")
sqlDF.show()
复制代码

三. Structured Streaming

3.1 Structured Streaming与其他流式计算应用的对比

属性

Structured Streaming

Spark Streaming

Apache Storm

Apache Flink

Kafka Stream

Google Dataflow

Streaming API

增量执行批处理计算

基于批处理计算引擎

与批处理无关

与批处理无关

与批处理无关

基于批处理计算引擎

基于数据位置前缀的计算完整性的保证



×

×

×

×

一致性语义

exactly once

exactly once

exactly once

exactly once

at least once

exactly once

事务性操作存储支持


部分

部分

部分

×

×

交互式查询




×

×

×

与静态数据进行join



×

×

×

×

output模式

  • complete mode,被更新后的整个结果表中的数据,都会被写入外部存储
  • append mode,只有最近一次trigger之后,新增加到result table中的数据,会被写入外部存储。只有确定result table中已有的数据是肯定不会被改变时,才应该使用append mode。
  • update mode,只有最近一次trigger之后,result table中被更新的数据,包括增加的和修改的,会被写入外部存储。

参考资料

  1. Spark 2.0从入门到精通