大数据之路系列之spark(08)



SPARK

  • 大数据之路系列之spark(08)
  • 一、spark是什么?
  • 二、spark包含什么?
  • 三、测试spark on yarn
  • 1.spark测试执行
  • 四、Spark的工作原理
  • 2.RDD的特点
  • 五、Spark的架构
  • 六、WordCount程序
  • 1.创建maven项目
  • 2.添加Scala
  • 3.xml 依赖
  • 4.Scala代码
  • 5.Java代码
  • 6.任务提交
  • 1.idea
  • 2.使用spark-submit
  • 1.打包配置
  • 2.spark-core作用于设置成provided
  • 3.删除master名称配置
  • 4.打包后执行jar
  • 3.使用spark-shell
  • 八、transformation和action算子
  • 1.创建RDD
  • (1).集合方式
  • (2).本地方式和hdfs方式创建RDD
  • 2.Transformation和Action
  • 3.常用Transformation介绍
  • 4.常用action介绍
  • 九、RDD持久化
  • 十、共享变量



提示:以下是本篇文章正文内容,下面案例可供参考

一、spark是什么?

spark是大规模数据处理的计算引擎,基于内存的计算引擎。

二、spark包含什么?

spark Initialized BlockManager 卡住 spark spill(memory)_jar


底层是Hadoop的hdfs和yarn

Spark core指的是Spark的离线批处理

Spark Streaming指的是Spark的实时流计算

SparkSQL指的是Spark中的SQL计算

Spark Mlib指的是Spark中的机器学习库,这里面集成了很多机器学习算法

最后这个Spark GraphX是指图计算

三、测试spark on yarn

yarn地址:http://node01:8088/cluster/apps

1.spark测试执行

不需要启动spark进程--class 指定需要指定的入口类,表示计算π值--master指定集群的地址接着指定需要提交的任务jar包,最后的一个参数是计算π值这个任务自身需要的 接着指定需要提交的任务jar包,最后的一个参数是计算π值这个任务自身需要的

bin/spark-submit --class org.apache.spark.examples.SparkPi --master yarn --deploy-mode cluster examples/jars/spark-examples_2.11-2.4.3.jar 2

四、Spark的工作原理

spark Initialized BlockManager 卡住 spark spill(memory)_jar_02


工作原理:首先通过spark客户端提交任务到spark集群,然后spark任务在执行的过程中会读取数据源(hdfs等),将数据加载到内存中,转化为RDD,RDD会落在不同的分区,对RDD调用高阶函数进行并行处理。

2.RDD的特点

RDD是弹性分布式数据集
分布式:RDD是被分区的,被并行执行
容错性:自动从节点失败中恢复过来

五、Spark的架构

spark Initialized BlockManager 卡住 spark spill(memory)_scala_03

  1. 首先我们在spark的客户端机器上通过driver进程执行我们的Spark代码
  2. 当我们通过spark-submit脚本提交Spark任务的时候Driver进程就启动了。
  3. Driver进程启动之后,会做一些初始化的操作,会找到集群master进程,对Spark应用程序进行注册
  4. 当Master收到Spark程序的注册申请之后,会发送请求给Worker,进行资源的调度和分配
  5. Worker收到Master的请求之后,会为Spark应用启动Executor进程会启动一个或者多个Executor,具体启动多少个,会根据你的配置来启动
  6. Executor启动之后,会向Driver进行反注册,这样Driver就知道哪些Executor在为它服务了
  7. Driver会根据我们对RDD定义的操作,提交一堆的task去Executor上执行
  8. task里面执行的其实就是具体的map、flatMap这些操作。

六、WordCount程序

1.创建maven项目

spark Initialized BlockManager 卡住 spark spill(memory)_hadoop_04

2.添加Scala

1.下载Scala的插件

2.设置全局的依赖

spark Initialized BlockManager 卡住 spark spill(memory)_hadoop_05


3.当前模块添加依赖

spark Initialized BlockManager 卡住 spark spill(memory)_hadoop_06

3.xml 依赖

2.11代表Scala的版本
org.apache.spark
spark-core_2.11
2.4.3

4.Scala代码

package com.scala

import org.apache.spark.{SparkConf, SparkContext}

/**
 * 需求:单词计数
 * Created by xuwei
 */
object WordCountScala {

  def main(args: Array[String]): Unit = {
    //第一步:创建SparkContext
    val conf = new SparkConf()
    conf.setAppName("WordCountScala")//设置任务名称
      .setMaster("local")//local表示在本地执行
    val sc = new SparkContext(conf)

    //第二步:加载数据
    val linesRDD = sc.textFile("D:\\hello.txt")

    //第三步:对数据进行切割,把一行数据切分成一个一个的单词
    val wordsRDD = linesRDD.flatMap(_.split(" "))

    //第四步:迭代words,将每个word转化为(word,1)这种形式
    val pairRDD = wordsRDD.map((_,1))

    //第五步:根据key(其实就是word)进行分组聚合统计
    val wordCountRDD = pairRDD.reduceByKey(_ + _)

    //第六步:将结果打印到控制台
    wordCountRDD.foreach(wordCount=>println(wordCount._1+"--"+wordCount._2))

    //第七步:停止SparkContext
    sc.stop()
  }

}

5.Java代码

public static void main(String[] args) {
        SparkConf sparkConf = new SparkConf().setAppName("wordCountJava").setMaster("local");
        JavaSparkContext sc = new JavaSparkContext(sparkConf);
        JavaRDD<String> testRDD = sc.textFile("C:\\project\\db_spark\\src\\main\\resources\\TODO.txt");
        JavaRDD<String> flatMapRDD = testRDD.flatMap(x -> Arrays.stream(StringUtils.split(x, " ")).iterator());
        JavaPairRDD<String, Integer> mapTPair = flatMapRDD.mapToPair(x -> new Tuple2<String, Integer>(x, 1));
        JavaPairRDD<String, Integer> reduceByKeyRDD = mapTPair.reduceByKey((x, y) -> x + y);
        reduceByKeyRDD.foreach(x-> System.out.println(x._1+":"+x._2));
        sc.stop();
    }

6.任务提交

1.idea

本地测试,执行运行

2.使用spark-submit

1.打包配置
<build>
    <plugins>
        <!-- java编译插件 -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.6.0</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <encoding>UTF-8</encoding>
            </configuration>
        </plugin>
        <!-- scala编译插件 -->
        <plugin>
            <groupId>net.alchim31.maven</groupId>
            <artifactId>scala-maven-plugin</artifactId>
            <version>3.1.6</version>
            <configuration>
                <scalaCompatVersion>2.11</scalaCompatVersion>
                <scalaVersion>2.11.12</scalaVersion>
            </configuration>
            <executions>
                <execution>
                    <id>compile-scala</id>
                    <phase>compile</phase>
                    <goals>
                        <goal>add-source</goal>
                        <goal>compile</goal>
                    </goals>
                </execution>
                <execution>
                    <id>test-compile-scala</id>
                    <phase>test-compile</phase>
                    <goals>
                        <goal>add-source</goal>
                        <goal>testCompile</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <!-- 打包插件 -->
        <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <configuration>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
                <archive>
                    <manifest>
                        <mainClass></mainClass>
                    </manifest>
                </archive>
            </configuration>
            <executions>
                <execution>
                    <id>make-assembly</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
2.spark-core作用于设置成provided
<dependency>
    <groupId>org.apache.spark</groupId>
    <artifactId>spark-core_2.12</artifactId>
    <version>2.4.3</version>
    <scope>provided</scope>
</dependency>
3.删除master名称配置

local表示的本地测试执行
//.setMaster(“local”)//local表示在本地执行
//第二步:加载数据
var path = “D:\hello.txt”
if(args.length==1){
path = args(0)
}

4.打包后执行jar

提示:这里的包目录不需要文件的后缀名--deploy-mode client 和--deploy-mode cluster 区别下一章有说明

[root@bigdata04 sparkjars]# vi wordCountJob.sh
spark-submit \
--class com.imooc.scala.WordCountScala \
--master yarn \
--deploy-mode cluster \
--executor-memory 1G \
--num-executors 1 \
db_spark-1.0-SNAPSHOT-jar-with-dependencies.jar \
hdfs://bigdata01:9000/test/hello.txt

3.使用spark-shell

park-shell --master yarn --deploy-mode client

八、transformation和action算子

1.创建RDD

(1).集合方式

val arr=Array(1,2,3,4)
    val arrRDD: RDD[Int] = sc.parallelize(arr)

(2).本地方式和hdfs方式创建RDD

Spark默认会为HDFS文件的每一个Block创建一个partition,也可以通过textFile()的第二个参数手动设置分区数量,只能比Block数量多,不能比Block数量少,比Block数量少的话你的设置是不生效的:

JavaRDD<String> testRDD = sc.textFile(filePath,2);

2.Transformation和Action

transformation:转换,lazy特性,transformation不会触发spark任务的执行,直到遇到action操作以后才会执行,避免过多中间结果产生。
action:执行

3.常用Transformation介绍

算子			介绍
map			将RDD中的每个元素进行处理,一进一出
filter		对RDD中每个元素进行判断,返回true则保留
flatMap		与map类似,但是每个元素都可以返回一个或多个新元素
groupByKey	根据key进行分组,每个key对应一个Iterable<value>
reduceByKey	对每个相同key对应的value进行reduce操作
sortByKey	对每个相同key对应的value进行排序操作(全局排序)
join		对两个包含<key,value>对的RDD进行join操作
distinct	对RDD中的元素进行全局去重

4.常用action介绍

算子				介绍
reduce			将RDD中的所有元素进行聚合操作
collect			将RDD中所有元素获取到本地客户端(Driver)
count			获取RDD中元素总数
take(n)			获取RDD中前n个元素
saveAsTextFile	将RDD中元素保存到文件中,对每个元素调用toString
countByKey		对每个key对应的值进行count计数
foreach			遍历RDD中的每个元素

九、RDD持久化

在一个RDD需要反复执行多次的时候,就可以持久化RDD避免重复计算。
代码

rdd.cache(); //简化版本等同于  rdd.persist(MEMORY_ONLY());
        rdd.persist(StorageLevel.MEMORY_ONLY()); //使用内存
        rdd.persist(StorageLevel.MEMORY_ONLY_SER(h)); //序列化
        rdd.persist(StorageLevel.MEMORY_ONLY_SER_2()); //多备份一份

选择策略
1.优先使用MEMORY_ONLY,纯内存速度最快,而且没有序列化不需要消耗CPU进行反序列化操作,缺点就是比较耗内存
2.MEMORY_ONLY_SER,将数据进行序列化存储,纯内存操作还是非常快,只是在使用的时候需要消耗CPU进行反序列化
3.如果需要进行数据的快速恢复,就选择后缀带_2的策略,进行数据备份,这样失败的时候就不需要重新计算了。

十、共享变量

##1.broadcast val 广播变量

普通的变量,每个task都会拷贝一份,广播变量是每个节点拷贝一份。

广播变量是定值,不能修改

作用就是减少内存消耗

spark Initialized BlockManager 卡住 spark spill(memory)_hadoop_07

//定义广播变量
Broadcast<Integer> broadcast = sc.broadcast(2);
//使用广播变量
JavaRDD<Integer> map = dataRDD.map(x -> x * broadcast.value());

##2.accumulator

LongAccumulator longAccumulator = sc.sc().longAccumulator("2");
dataRDD.foreach(x->longAccumulator.add(x));
System.out.println(longAccumulator.value());