大数据实时阶段----【Spark01】

10 篇文章 0 订阅
7 篇文章 0 订阅

spark_01学习笔记

1、目标
  • 1、掌握spark相关概念

  • 2、掌握搭建一个spark集群

  • 3、掌握编写简单的spark应用程序

2、spark概述
2.1 什么是spark
  • Apache Spark™ is a unified analytics engine for large-scale data processing.

  • apache的spark是一个针对于大规模数据处理的统一分析引擎

    spark是基于内存计算的大数据处理框架,由于基于内存计算,处理数据非常快。这里仅仅只涉及到数据的计算,并没有涉及到数据的存储,后期就需要对接各种不同的外部数据源,比如处理HDFS上的数据。
    
2.2 为什么要学习spark
  • 就是因为spark处理速度比mapreduce快很多,提高任务运行的速度,很受企业青睐。
  • spark不在是一个简单的框架,而是发展成一个生态系统,它里面有很多不同的子项目
    • sparksql
    • sparkStreaming
    • Graphx
    • Mlib
2.3 spark 四大特性
  • 1、速度快

    • spark比mapreduce在内存中快100倍,比mapreduce在磁盘中快10倍

    • spark比mapreduce快的主要2个原因

      (1)mapreduce的任务每一个job它的输出结果只能够保存在磁盘,后续有其他的job需要依赖于前面job的输出结果,这个时候需要进行大量的磁盘io操作。 spark的任务每一个job它的输出结果可以保存在内存中,后续有其他的job需要依赖于前面job的输出结果,这个时候就可以直接在内存中获取得到,大大减少磁盘io操作,最后提升了性能。
      
      例如: select name,age from (select * from user where age >30 and age <40)
      
      (2) mapreduce的任务它是以进程的方式运行在yarn集群中,比如一个job有100个MapTask,这个时候就需要开启100个进程去处理这个100个task。spark的任务它是以线程的方式运行在进程中,比如一个job有100个MapTask,这个时候就可以极端一点:只启动一个进程,在这个进程运行100个线程。这里开启一个进程和开启一个线程代价是不一样,开启一个进程需要的时间和资源比线程要大大增加。spark中可以减少大量的时间资源调度,提升性能。
      
  • 2、易用性

    • 可以快速开发一个spark应用程序,通过java、scala、python、R、sql不同语言开发代码程序
  • 3、通用性

    • spark框架是一个生态系统,可以通过不同子项目sparksql、sparkStreaming、Mlib、Graphx应用到不同的应用场景。
  • 4、兼容性

    • spark任务就是一个计算程序,哪里可以给当前这个程序提供对应的计算资源,我们就可以把程序提交到哪里去。

      • yarn

        • spark程序可以提交到yarn中去运行,整个任务的资源分配由resourcemanager去负责
      • standalone

        • 它是spark自带的集群模式,整个任务的资源分配由Master去负责
      • mesos

        • 它是一个apache开源类似于yarn的资源管理平台
3、spark集群安装部署
  • 1、下载spark对应的安装包

  • 2、规划安装目录

    • /export/servers
  • 3、上传安装包到服务器中

  • 4、解压安装包到指定的规划目录中

    • tar -zxvf spark-2.1.3-bin-hadoop2.7.tgz -C /export/servers
  • 5、重命名解压目录

    • mv spark-2.1.3-bin-hadoop2.7 spark
  • 6、修改配置文件

    • 进入到spark安装目录有一个conf文件夹

      • vim spark-env.sh (mv spark-env.sh.template spark-env.sh)

        #配置java环境变量 ,集合自己的java_home路径
        export JAVA_HOME=/export/servers/jdk
        #指定master的地址
        export SPARK_MASTER_HOST=node1
        #指定master的端口
        export SPARK_MASTER_PORT=7077
        
      • vim slaves (mv slaves.template slaves)

        在slaves配置文件的最后将localhost删除 , 然后添加node-2 , node-3
        #指定哪些节点是worker
        node-2
        node-3
        
  • 7、配置spark环境变量

    • vim /etc/profile

      export SPARK_HOME=/export/servers/spark
      export PATH=$PATH:$SPARK_HOME/bin:$SPARK_HOME/sbin
      
  • 8、分发spark安装目录和spark环境变量

    scp -r spark node-2:/export/servers
    scp -r spark node-3:/export/servers
    
    scp /etc/profile node2:/etc
    scp /etc/profile node3:/etc
    
  • 9、让所有节点的spark环境变量生效

    • 在所有节点上执行
      • source /etc/profile
4、spark集群启动和停止
  • 启动spark集群

    • 需要在主节点(master所有在机器)中进入到spark安装目录下有一个sbin文件夹
      • ./start-all.sh
  • 停止spark集群

    • 需要在主节点(master所有在机器)中进入到spark安装目录下有一个sbin文件夹

      • ./stop-all.sh
5、 spark集群web管理界面
  • 启动好spark集群之后可以访问spark集群web管理界面
    • 地址
      • master所在的主机名:8080 ==>node-1:8080
      • 可以看到很多spark集群信息
        • 整个spark集群所有信息
        • 整个spark集群总的资源信息
        • 整个spark集群使用的资源信息
        • 整个spark集群还剩的资源信息
        • 整个spark集群worker信息
        • 正在运行的任务信息
        • 已经完成的任务信息
6、基于zk构建高可用的spark集群
  • 1、搭建zk集群

  • 2、修改配置文件

    • vim spark-env.sh

      #注释掉手动指定master地址配置
      #export SPARK_MASTER_HOST=node-1
      #引入zk构建spark高可用集群
      export SPARK_DAEMON_JAVA_OPTS="-Dspark.deploy.recoveryMode=ZOOKEEPER  -Dspark.deploy.zookeeper.url=node-1:2181,n
      ode-2:2181,node-3:2181  -Dspark.deploy.zookeeper.dir=/spark"
      
    • 然后拷贝到其他机器上

    scp spark-env.sh node-2:$PWD
    scp spark-env.sh node-3:$PWD
    PWD表示统计目录
    
  • 3、启动zk集群

  • 4、启动spark集群

    • 可以在任意一台机器启动脚本(前提条件:实现任意2台机器之间的ssh免密登录)

      • start-all.sh
      • 它首先会在当前机器启动一个Master进程
      • 整个集群的worker由slaves文件决定
    • 可以在其他机器单独启动master

      • start-master.sh
    • spark高可用集群master恢复

      引入zk之后,可以启动很多个master,其中有一个master被选举成活着的master,它去提供服务,其他多个naster处于standBy状态(备用),启动好之后,它会把整个spark集群的元数据信息写入到zk配置好的节点中(/spark).
      如果活着的master挂掉了,首先zk会感知到,接下来它会在所有处于standBy中的master进行选举生成一个新的活着的master,活着的master它会读取到zk中保存spark集群元数据信息的节点,最后进行恢复,恢复到上一次挂掉的master状态,整个恢复过程需要1-2分钟。
      
      
      当前活着的master挂掉之后有什么影响?
      (1)对于正在运行的任务有没有影响?
         没有任何影响。原因:对于正在运行的任务,就说明已经获取得到资源,这个时候就不需要master,可以继续运行,不受任何影响。
         
      (2)对于要提交的任务有没有影响?
        有影响,由于没有这样一个活着的master提供资源的分配,这个任务就获取不到资源,既然获取不到资源,任务就无法运行。 
      
7、spark角色介绍

在这里插入图片描述

  • 1、Driver端

    • 它会运行客户端写好的main方法和构建SparkContext对象,SparkContext对象是所有spark程序执行入口。
  • 2、Application

    • 它就是一个应用程序,它包括了Driver的代码逻辑和当前这个任务在运行的时候所有需要的资源信息
  • 3、ClusterManager

    • 它可以给当前任务提供计算资源的外部服务
      • standAlone
        • spark自带的集群模式,整个任务的资源分配由Master去负责
      • yarn
        • spark程序可以提交到yarn中去运行,整个任务的资源分配由ResourceManager去负责
      • mesos
        • 它是一个apache开源的类似于yarn的资源管理平台
  • 4、Master

    • 它是spark集群的老大,它负责给任务分配资源,它不会参与计算。
  • 5、Worker

    • 它是spark集群的小弟,它负责任务计算的节点
  • 6、Executor

    • 它就是一个进程,它会正在worker节点启动executor进程
  • 7、task

    • 它就是一个线程,task是以线程的方式运行在worker节点的executor进程中
8、初识spark程序
  • 1、普通模式提交任务(就是我们事先知道了哪个Master是活着的Master)

    bin/spark-submit \
    --class org.apache.spark.examples.SparkPi \
    --master spark://node2:7077 \
    --executor-memory 1G \
    --total-executor-cores 2 \
    examples/jars/spark-examples_2.11-2.1.3.jar \
    10
    
  • 2、高可用模式下提交任务(整个集群有很多个Master,事先并不知道哪个master是活着的master)

    bin/spark-submit \
    --class org.apache.spark.examples.SparkPi \
    --master spark://node1:7077,node3:7077,node2:7077 \
    --executor-memory 1G \
    --total-executor-cores 2 \
    examples/jars/spark-examples_2.11-2.1.3.jar \
    10
    
    实际企业中,master肯定是很多个,这个时候任务的提交需要找活着的master申请资源,由于master特别多,我们无法快速判断哪个master是活着的master,即使判断出了哪个master是活着的master,它也有可能下一秒就挂掉了,这个时候就可以在提交任务的时候指定 --master spark://node-1:7077,node-3:7077,node-2:7077 把所有的master地址都进行罗列。
    
    后期整个程序会依次轮训整个master列表,最后找到活着的master,然后向这个活着的master申请资源。
    资源分配根据自己电脑性能来
    
9、spark-shell使用
9.1 通过spark-shell --master local[N] 读取本地数据文件实现单词统计
  • –master local[N]

    • local:表示本地运行spark程序,跟spark集群没有任何关系
    • N:表示一个正整数,在这里local[N]表示本地采用N个线程去运行任务
  • 提交脚本

    • spark-shell --master local[2] 它会产生一个SparkSubmit进程

      sc.textFile("file:///root/words.txt").flatMap(x=>x.split(" ")).map(x=>(x,1)).reduceByKey((x,y)=>x+y).collect
      
      sc.textFile("file:///root/words.txt").flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_).collect
      
9.2 通过spark-shell --master local[N] 读取HDFS上数据文件实现单词统计
  • spark整合hdfs

    • vim spark-env.sh

      export HADOOP_CONF_DIR=/export/servers/hadoop/etc/hadoop
      
  • 提交脚本

    • spark-shell --master local[2]

      sc.textFile("/words.txt").flatMap(x=>x.split(" ")).map(x=>(x,1)).reduceByKey((x,y)=>x+y).collect
      
      sc.textFile("hdfs://node-1:9000/words.txt").flatMap(x=>x.split(" ")).map(x=>(x,1)).reduceByKey((x,y)=>x+y).collect
      
9.3 通过spark-shell --master 指定具体活着的master,把最后的统计结果写入到hdfs上保存
  • 把任务提交到集群中运行

  • 提交脚本

    • spark-shell --master spark://node-2:7077

      sc.textFile("/words.txt").flatMap(x=>x.split(" ")).map(x=>(x,1)).reduceByKey((x,y)=>x+y).collect
      
      sc.textFile("/words.txt").flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_).saveAsTextFile("/out")
      
10、利用IDEA开发spark应用程序
  • 1、引入pom依赖

    <properties>
            <scala.version>2.11.8</scala.version>
            <hadoop.version>2.7.4</hadoop.version>
            <spark.version>2.1.3</spark.version>
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.scala-lang</groupId>
                <artifactId>scala-library</artifactId>
                <version>${scala.version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.spark</groupId>
                <artifactId>spark-core_2.11</artifactId>
                <version>${spark.version}</version>
            </dependency>
    
        </dependencies>
    
        <build>
            <sourceDirectory>src/main/scala</sourceDirectory>
            <testSourceDirectory>src/test/scala</testSourceDirectory>
            <plugins>
                <plugin>
                    <groupId>net.alchim31.maven</groupId>
                    <artifactId>scala-maven-plugin</artifactId>
                    <version>3.2.2</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>compile</goal>
                                <goal>testCompile</goal>
                            </goals>
                            <configuration>
                                <args>
                                    <arg>-dependencyfile</arg>
                                    <arg>${project.build.directory}/.scala_dependencies</arg>
                                </args>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-shade-plugin</artifactId>
                    <version>2.4.3</version>
                    <executions>
                        <execution>
                            <phase>package</phase>
                            <goals>
                                <goal>shade</goal>
                            </goals>
                            <configuration>
                                <filters>
                                    <filter>
                                        <artifact>*:*</artifact>
                                        <excludes>
                                            <exclude>META-INF/*.SF</exclude>
                                            <exclude>META-INF/*.DSA</exclude>
                                            <exclude>META-INF/*.RSA</exclude>
                                        </excludes>
                                    </filter>
                                </filters>
                                <transformers>
                                    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                        <mainClass></mainClass>
                                    </transformer>
                                </transformers>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    
10.1 利用scala语言开发spark的wordcount程序(本地运行)
  • 代码开发

    package cn.itcast.spark
    
    import org.apache.spark.rdd.RDD
    import org.apache.spark.{SparkConf, SparkContext}
    
    //todo:利用scala语言开发spark的wordcount程序(本地运行)
    object WordCount {
      def main(args: Array[String]): Unit = {
           //1、创建SparkConf对象 设置applicationName和master地址   local[2]表示本地采用2个线程
          val sparkConf: SparkConf = new SparkConf().setAppName("WordCount").setMaster("local[2]")
    
           //2、创建SparkContext对象,它是所有spark程序执行入口,它内部会构建DAGScheduler和TaskScheduler
         val sc = new SparkContext(sparkConf)
            //设置日志输出级别
          sc.setLogLevel("warn")
    
         //3、读取文件数据
          val data: RDD[String] = sc.textFile("E:\\words.txt")
    
         //4、切分每一行,获取所有的单词
          val words: RDD[String] = data.flatMap(x=>x.split(" "))
    
        //5、每个单词计为1
         val wordAndOne: RDD[(String, Int)] = words.map(x =>(x,1))
    
        //6、相同单词出现的1累加
        val result: RDD[(String, Int)] = wordAndOne.reduceByKey((x:Int,y:Int)=>x+y)
    
          //按照单词出现的次数降序排列  默认第二个参数是true,在这里表示升序,改为false就是降序
        val sortedRDD: RDD[(String, Int)] = result.sortBy(x => x._2,false)
    
    
        //7、收集数据打印
        val finalResult: Array[(String, Int)] = sortedRDD.collect
        finalResult.foreach(x=>println(x))
    
        //8、关闭sc
          sc.stop()
      }
    }
    
    
10.2 利用scala语言开发spark的wordcount程序(打成jar包集群运行)
  • 1、代码开发

    package cn.itcast.spark
    
    import org.apache.spark.{SparkConf, SparkContext}
    import org.apache.spark.rdd.RDD
    
    //todo:利用scala语言开发spark的wordcount程序(集群运行)
    object WordCount_Online {
      def main(args: Array[String]): Unit = {
        //1、创建SparkConf对象 设置applicationName
        val sparkConf: SparkConf = new SparkConf().setAppName("WordCount_Online")
    
        //2、创建SparkContext对象,它是所有spark程序执行入口,它内部会构建DAGScheduler和TaskScheduler
        val sc = new SparkContext(sparkConf)
        //设置日志输出级别
        sc.setLogLevel("warn")
    
        //3、读取文件数据
        val data: RDD[String] = sc.textFile(args(0))
    
        //4、切分每一行,获取所有的单词
        val words: RDD[String] = data.flatMap(x=>x.split(" "))
    
        //5、每个单词计为1
        val wordAndOne: RDD[(String, Int)] = words.map(x =>(x,1))
    
        //6、相同单词出现的1累加
        val result: RDD[(String, Int)] = wordAndOne.reduceByKey((x:Int,y:Int)=>x+y)
    
        //7、把最后的结果数据保存到hdfs上
          result.saveAsTextFile(args(1))
    
        //8、关闭sc
        sc.stop()
      }
    }
    
    
  • 2、打成jar包集群运行

    spark-submit --master spark://node-1:7077,node-2:7077,node-3:7077 --class cn.itcast.spark.WordCount_Online --executor-memory 512M --total-executor-cores 1 original-spark_class14-1.0-SNAPSHOT.jar /words.txt /out_spark
    
10.3 利用java语言开发spark的wordcount程序(本地运行)
  • 1、代码开发

    package cn.itcast.spark;
    
    import org.apache.spark.SparkConf;
    import org.apache.spark.api.java.JavaPairRDD;
    import org.apache.spark.api.java.JavaRDD;
    import org.apache.spark.api.java.JavaSparkContext;
    import org.apache.spark.api.java.function.FlatMapFunction;
    import org.apache.spark.api.java.function.Function2;
    import org.apache.spark.api.java.function.PairFunction;
    import scala.Tuple2;
    
    import java.util.Arrays;
    import java.util.Iterator;
    import java.util.List;
    
    //todo:利用java语言开发spark的wordcount程序(本地运行)
    public class WordCount_Java {
        public static void main(String[] args) {
            //1、创建SparkConf
            SparkConf sparkConf = new SparkConf().setAppName("WordCount_Java").setMaster("local[2]");
    
            //2、创建JavaSparkContext
            JavaSparkContext jsc = new JavaSparkContext(sparkConf);
    
            //3、读取文件数据
            JavaRDD<String> data = jsc.textFile("E:\\words.txt");
    
            //4、切分每一行,获取所有的单词
            JavaRDD<String> words = data.flatMap(new FlatMapFunction<String, String>() {
                public Iterator<String> call(String line) throws Exception {
                    String[] lines = line.split(" ");
                    return Arrays.asList(lines).iterator();
                }
            });
    
            //5、每个单词计为1
            JavaPairRDD<String, Integer> wordAndOne = words.mapToPair(new PairFunction<String, String, Integer>() {
                public Tuple2<String, Integer> call(String word) throws Exception {
                    return new Tuple2<String, Integer>(word, 1);
                }
            });
    
            //6、相同单词出现的1累加
            JavaPairRDD<String, Integer> result = wordAndOne.reduceByKey(new Function2<Integer, Integer, Integer>() {
                public Integer call(Integer v1, Integer v2) throws Exception {
                    return v1 + v2;
                }
            });
    
               //按照单词出现的次数降序排列  (单词,次数)----->(次数,单词).sortByKey----->(单词,次数)
    
            JavaPairRDD<Integer, String> reverseRDD = result.mapToPair(new PairFunction<Tuple2<String, Integer>, Integer, String>() {
                public Tuple2<Integer, String> call(Tuple2<String, Integer> t) throws Exception {
                    return new Tuple2<Integer, String>(t._2, t._1);
                }
            });
    
            JavaPairRDD<String, Integer> sortedRDD = reverseRDD.sortByKey(false).mapToPair(new PairFunction<Tuple2<Integer, String>, String, Integer>() {
                public Tuple2<String, Integer> call(Tuple2<Integer, String> t) throws Exception {
                    return new Tuple2<String, Integer>(t._2, t._1);
                }
            });
    
            //7、收集打印
            List<Tuple2<String, Integer>> finalResult = sortedRDD.collect();
            for (Tuple2<String, Integer> t : finalResult) {
                System.out.println("单词:"+t._1+" 次数:"+t._2);
            }
    
            //8、关闭jsc
            jsc.stop();
        }
    
    }
    
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值