从今天起,我们踏上了新的Spark学习旅途。我们的目标是要像Spark官方机构那样有能力去定制Spark。

一.  我们最开始将从Spark Streaming入手。

为何从Spark Streaming切入Spark定制?Spark的子框架已有若干,为何选择Spark Streaming?让我们细细道来。

1.  Spark最开始只有Spark Core,没有目前的这些子框架。这些子框架是构建于Spark Core之上的。没有哪个子框架能摆脱Spark Core。我们通过对一个框架的彻底研究,肯定可以领会Spark力量的源泉,并精通所有问题的解决之道。

2.  我们再看看目前的这些子框架。Spark SQL有太多语法,研究这些会太浪费精力。SparkR还没完善。Spark GraphX已无太多可改进之处,图计算相关的数学知识也不是目前重点。Spark MLlib中的机器学习也有太多算法是与数学相关,也不是做改进的好的选择 。所以我们选择了Spark Streaming。

二 .对Spark Streaming的理解

1. Spark Streaming是流式计算,当今时代是一个流处理时代,一切数据如果不是流式处理, 或者说和流式处理不相关的话,都是无效的数据。

2. 流式处理才是我们对大数据的初步印象,而不是批处理和数据挖掘,当然Spark强悍的地方在于,他的流式处理可以在线的直接使用机器学习、图计算、SparkSQL、Spark R的成果。

3. 整个Spark的程序,基于Spark Streaming的最容易出问题,也是最受关注的地方,也是最需要人才的地方。

4. Spark Streaming和其他子框架的不同之处,Spark Streaming很像基于Spark Core之上的应用程序。

5. 寻龙点穴,Spark就是龙脉,Spark Streaming就是穴位

2015年是流式处理的一年。大家考虑用Spark,主要也是因为Spark Streaming。这是一个流处理的时代,一切数据如果与流式处理不相关的话,都是无效的数据。Spark之所以强悍的一个重要原因在于,它的流式处理可以在线使用图计算、机器学习或者SparkR的成果,这得益于Spark一体化、多元化的基础架构设计。也就是在Spark Streaming中可以调用其它子框架,无需任何设置。这是Spark的无可匹敌之处,也是Spark Streaming必将一统天下的根源。但Spark的应用中,Spark Streaming也是最容易出问题的。

Spark Streaming与其它子框架不同之处在于,它更像是Spark Core之上的一个应用程序。所以如果要做Spark的定制开发,Spark Streaming则提供了最好的参考。你想掌握Spark Streaming,但你不去精通Spark Core的话,那是不可能的。所以我们选择Spark Streaming来提升自己,是找到了关键点。

本期内容

1 Spark Streaming另类在线实验

2 瞬间理解Spark Streaming本质

1 Spark Streaming另类在线实验

我们在研究Spark Streaming的过程中,会有困惑的事情:如何清晰的看到数据的流入、被处理的过程?

使用一个小技巧,通过调节放大Batch Interval的方式,来降低批处理次数,以方便看清楚各个环节。

我们从已写过的广告点击的在线黑名单过滤的Spark Streaming应用程序入手。

ackage com.dt.spark.streaming

import org.apache.spark.SparkConf

import org.apache.spark.streaming.StreamingContext

import org.apache.spark.streaming.Seconds

object OnlineBlackListFilter {

def main(args: Array[String]){

/**

* 第1步:创建Spark的配置对象SparkConf,设置Spark程序的运行时的配置信息,

* 例如说通过setMaster来设置程序要链接的Spark集群的Master的URL,如果设置

* 为local,则代表Spark程序在本地运行,特别适合于机器配置条件非常差(例如

* 只有1G的内存)的初学者。

*/

// 创建SparkConf对象

val conf = new SparkConf()

// 设置应用程序的名称,在程序运行的监控界面可以看到名称

conf.setAppName("OnlineBlackListFilter")

// 此时,程序在Spark集群

conf.setMaster("spark://Master:7077")

val ssc = new StreamingContext(conf, Seconds(30))

/**

* 黑名单数据准备,实际上黑名单一般都是动态的,例如在Redis或者数据库中,

* 黑名单的生成往往有复杂的业务逻辑,具体情况算法不同,

* 但是在Spark Streaming进行处理的时候每次都能够访问完整的信息。

*/

val blackList = Array(("Spy", true),("Cheater", true))

val blackListRDD = ssc.sparkContext.parallelize(blackList, 8)

val adsClickStream = ssc.socketTextStream("Master", 9999)

/**

* 此处模拟的广告点击的每条数据的格式为:time、name

* 此处map操作的结果是name、(time,name)的格式

*/

val adsClickStreamFormatted = adsClickStream.map { ads => (ads.split(" ")(1), ads) }

adsClickStreamFormatted.transform(userClickRDD => {

// 通过leftOuterJoin操作既保留了左侧用户广告点击内容的RDD的所有内容,

// 又获得了相应点击内容是否在黑名单中

val joinedBlackListRDD = userClickRDD.leftOuterJoin(blackListRDD)

/**

* 进行filter过滤的时候,其输入元素是一个Tuple:(name,((time,name), boolean))

* 其中第一个元素是黑名单的名称,第二元素的第二个元素是进行leftOuterJoin的时候是否存在的值。

* 如果存在的话,表面当前广告点击是黑名单,需要过滤掉,否则的话是有效点击内容;

*/

val validClicked = joinedBlackListRDD.filter(joinedItem => {

if(joinedItem._2._2.getOrElse(false))

{

false

} else {

true

}

})

validClicked.map(validClick => {validClick._2._1})

}).print

/**

* 计算后的有效数据一般都会写入Kafka中,下游的计费系统会从kafka中pull到有效数据进行计费

*/

ssc.start()

ssc.awaitTermination()

}

}

我们把程序的Batch Interval设置成300秒:

val ssc = new StreamingContext(conf, Seconds(300))

我们重新生成一下jar包 。

Spark集群有4台机器:Master、Worker1、Worker2、Worker3、Worker4。

启动Spark的History Server。

打开数据发送的端口:

nc -lk 9999

用spark-submit运行前面生成的jar包。

在数据发送端口输入若干数据,比如:

1375864674543 Tom

1375864674553 Spy

1375864674571 Andy

1375864688436 Cheater

1375864784240 Kelvin

1375864853892 Steven

1375864979347 John

打开浏览器,看History Server的日志信息:

点击最新的应用,看我们目前运行的应用程序中有些什么Job:

总共竟然有5个Job。这完全不是我们此前做Spark SQL之类的应用程序时看到的样子。

我们接下来看一看这些Job的内容,主要揭示一些现象,不会做完全深入的剖析,只是为了先让大家进行一些思考。

Job 0:此Job不体现我们的业务逻辑代码。这个Job是出于对后面计算的负载均衡的考虑。

Job 0包含有Stage 0、Stage 1。随便看一个Stage,比如Stage 1。看看其中的Aggregated Metrics by Executor部分:

发现此Stage在所有Executor上都存在。

Job 1:运行时间比较长,耗时1.5分钟。

点击Stage 2的链接,进去看看Aggregated Metrics By Executor部分:

可以知道,Stage 2只在Worker4上的一个Executor执行,而且执行了1.5分钟。

是否会觉得奇怪:从业务处理的角度看,我们发送的那么一点数据,没有必要去启动一个运行1.5分钟的任务吧。那这个任务是做什么呢?

从DAG Visualization部分,就知道此Job实际就是启动了一个接收数据的Receiver:

原来Receiver是通过一个Job来启动的。那肯定有一个Action来触发它。

看看Tasks部分:

只有一个Worker运行此Job。是用于接收数据。

Locality Level是PROCESS_LOCAL,原来是内存节点。所以,默认情况下,数据接收不会使用磁盘,而是直接使用内存中的数据。

看来,Spark Streaming应用程序启动后,自己会启动一些Job。默认启动了一个Job来接收数据,为后续处理做准备。

重要启示:一个Spark应用程序中可以启动很多Job,而这些不同的Job之间可以相互配合。这一认识为我们写复杂Spark程序奠定了良好的基础。

Job 2:看Details可以发现有我们程序的主要业务逻辑,体现在Stag 3、Stag4、Stag 5中。

我们看Stag3、Stage4的详情,可以知道这2个Stage都是用4个Executor执行的。所有数据处理是在4台机器上进行的。

Stag 5只在Worker4上。这是因为这个Stage有Shuffle操作。

Job3:有Stage 6、Stage 7、Stage 8。其中Stage 6、Stage 7被跳过。

看看Stage 8的Aggregated Metrics by Executor部分。可以看到,数据处理是在4台机器上进行的:

Job4:也体现了我们应用程序中的业务逻辑 。有Stage 9、Stage 10、Stage 11。其中Stage 9、Stage 10被跳过。

  

看看Stage 11的详情。可以看到,数据处理是在Worker4之外的其它3台机器上进行的:

综合以上的现象可以知道,Spark Streaming的一个应用中,运行了这么多Job,远不是我们从网络博客或者书籍上看的那么简单。

我们有必要通过这些现象,反过来回溯去寻根问源。不过这次暂不做深入分析。

我们的神奇之旅才刚刚开始。

2 瞬间理解Spark Streaming本质

以上的连续4个图,分别对应以下4个段落的描述:

Spark Streaming接收Kafka、Flume、HDFS和Kinesis等各种来源的实时输入数据,进行处理后,处理结果保存在HDFS、Databases等各种地方。

Spark Streaming接收这些实时输入数据流,会将它们按批次划分,然后交给Spark引擎处理,生成按照批次划分的结果流。

Spark Streaming提供了表示连续数据流的、高度抽象的被称为离散流的DStream。DStream本质上表示RDD的序列。任何对DStream的操作都会转变为对底层RDD的操作。

Spark Streaming使用数据源产生的数据流创建DStream,也可以在已有的DStream上使用一些操作来创建新的DStream。

在我们前面的实验中,每300秒会产生一批数据,基于这批数据会生成RDD,进而触发Job,执行处理。

DStream是一个没有边界的集合,没有大小的限制。

DStream代表了时空的概念。随着时间的推移,里面不断产生RDD。

锁定到时间段后,就是空间的操作。也就是对本时间段的对应批次的数据的处理。

下面用实例来讲解数据处理过程。

数据处理会有若干个对DStream的操作,这些操作之间的依赖关系,构成了DStreamGraph。如以下图例所示:

上图中每个foreach都会触发一个作业,就会顺着依赖从后往前回溯,形成DAG,如下图所示:

空间维度确定之后,随着时间不断推进,会不断实例化RDD Graph,然后触发Job去执行处理。

现在再去读官方的Spark Streaming的文档,就好理解多了。

看来我们的学习,将从Spark Streaming的现象开始,深入到Spark Core和Spark Streaming的本质。

Dream_Spark版本定制第一课的更多相关文章

  1. MySQL数据库初用(5.6版本)第一课

    参考:http://wenku.baidu.com/link?url=NlX55fDDQ02wESO1HNkxpvju2xATwe9Fym0MfojWddXbYaJcjEKKRF9z9EX4b7shV ...

  2. spark版本定制课程-第1课

    spark版本定制课程-第1课 1.学习本课程可以自己动手改进spark,或者给spark增加功能.增加某些官方没有提供的功能,通过本课程希望早就一些顶级spark专家,根据整个社会的需要对spark ...

  3. Dream_Spark定制第二课

    Spark版本定制第2天:通过案例对SparkStreaming透彻理解之二 本期内容: 1 解密Spark Streaming运行机制 2 解密Spark Streaming架构 一切不能进行实时流 ...

  4. Magento学习第一课——目录结构介绍

    Magento学习第一课--目录结构介绍 一.Magento为何强大 Magento是在Zend框架基础上建立起来的,这点保证了代码的安全性及稳定性.选择Zend的原因有很多,但是最基本的是因为zen ...

  5. NeHe OpenGL教程 第一课:OpenGL窗口

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  6. 【Linux探索之旅】开宗明义+第一部分第一课:什么是Linux?

    内容简介 1.课程大纲 2.第一部分第一课:什么是Linux? 3.第一部分第二课预告:下载Linux,免费的噢!   开宗明义 我们总听到别人说:Linux挺复杂的,是给那些追求逼格的程序员用的.咱 ...

  7. emacs 入门第一课:Emacs里的基本概念

    Table of Contents 无聊的开场白 buffer(缓冲区) window(窗口)与frame Emacs的mode Emacs Lisp 函数function.命令command.键绑定 ...

  8. <-0基础学python.第一课->

    初衷:我电脑里面的歌曲很久没换了,我想听一下新的歌曲,把他们下载下来听,比如某个榜单的,但是一首一首的点击下载另存为真的很恶心 所以我想有没有办法通过程序的方式来实现,结果还真的有,而且网上已经有有人 ...

  9. OpenCV 第一课(安装与配置)

    OpenCV 第一课(安装与配置) win10,opencv-2.4.13, 安装, vs2013, 配置 下载安装软件 官网OpenCV下载地址下载最新版本,我下载的是opencv.2.4.13,然 ...

随机推荐

  1. LeetCode 551. Student Attendance Record I (C++)

    题目: You are given a string representing an attendance record for a student. The record only contains ...

  2. X86主要的几种寻址方式

    一.首先 P33: 严格来说有三种寻址方式 与数据有关的寻址方式 与转移指令或过程调用指令有关的寻址方式 与IO指令有关的寻址方式 这篇博客只讲1.2两条 二.然后 1. 与数据有关的寻址方式 数据, ...

  3. SpringMVC(三)-- springmvc的系统学习之数据的处理,乱码及restful

    资源:尚学堂 邹波 springmvc框架视频 一.提交数据的处理 1.提交的域名称和处理方法的参数一致 (1)提交的数据:http://localhost:8080/data/hello.do?na ...

  4. 2017-08-20 block,inline和inline-block概念和区别

    display:inline.block.inline-block的区别 display:block就是将元素显示为块级元素. block元素的特点是: 总是在新行上开始: 高度,行高以及顶和底边距都 ...

  5. Alpha冲刺——day8

    Alpha冲刺--day8 作业链接 Alpha冲刺随笔集 github地址 团队成员 031602636 许舒玲(队长) 031602237 吴杰婷 031602220 雷博浩 031602634 ...

  6. python 如何写CMD命令工具

    #-*- coding: UTF- -*- import argparse import sys: sys.argv.append('--help') parser = argparse.Argume ...

  7. ORM的详解

    有很多小伙伴都不太理解ORM是什么,其实不用想象的那么复杂.我们先根据3W1H去理解. who:首先ORM可以立即为(Object/Relation Mapping): 对象/关系映射 what:其次 ...

  8. Python [练习题] :字典扁平化

    习题:将source字典扁平化,输出为 target 格式的字典.source = {'a': {'b': 1, 'c': 2}, 'd': {'e': 3, 'f': {'g': 4}}}targe ...

  9. 【bzoj4596】[Shoi2016]黑暗前的幻想乡 容斥原理+矩阵树定理

    题目描述 给出 $n$ 个点和 $n-1$ 种颜色,每种颜色有若干条边.求这张图多少棵每种颜色的边都出现过的生成树,答案对 $10^9+7$ 取模. 输入 第一行包含一个正整数 N(N<=17) ...

  10. ssm框架中Controller层的junit测试_我改

    Controller测试和一般其他层的junit测试可以共用一个BaseTest 一.BaseTest如下: @RunWith(SpringJUnit4ClassRunner.class) @WebA ...