Spark学习(一)

Spark

Spark简介

Lightning-fast unified analytics engine(快如闪电的统一分析引擎),是一个用于大规模数据处理的统一分析引擎。

Apache Spark 是一个快速的, 多用途的集群计算系统。它提供了 Java, Scala, Python 和 R 的高级 API,以及一个支持通用的执行图计算的优化过的引擎. 它还支持一组丰富的高级工具, 包括使用 SQL 处理结构化数据处理的Spark SQL, 用于机器学习的 MLlib, 用于图计算的 GraphX, 以及 Spark Streaming。

Spark的特点

1)速度快

与Hadoop的MapReduce相比,Spark基于内存的运算要快100倍以上,基于硬盘的运算也要快10倍以上。Spark实现了高效的DAG执行引擎,可以通过基于内存来高效处理数据流。(有向无关图、缓存机制)

2)易用性

Spark支持Java、Python和Scala的API,还支持超过80种高级算法,使用户可以快速构建不同的应用。

3)通用性

Spark提供了统一的解决方案。Spark可以用于批处理、交互式查询(Spark SQL)、实时流处理(SparkStreaming)、机器学习(Spark MLlib)和图计算(GraphX)。(实时业务、离线业务)

4)兼容性

Spark可以非常方便地与其他的开源产品进行融合。比如,Spark可以使用Hadoop的YARN和Apache Mesos作为它的资源管理和调度器,并且可以处理所有Hadoop支持的数据,包括HDFS、HBase和Cassandra等。这对于已经部署Hadoop集群的用户特别重要,因为不需要做任何数据迁移就可以使用Spark的强大处理能力。Spark也可以不依赖于第三方的资源管理和调度器,它实现了Standalone作为其内置的资源管理和调度框架,这样进一步降低了Spark的使用门槛,使得所有人都可以非常容易地部署和使用Spark。此外,Spark还提供了在EC2上部署Standalone的Spark集群的工具。(资源调度方式处理数据的位置)(兼容性高、可以到处跑)

Spark 核心组件 ##(Spark Core)

Spark Core是整个BDAS生态系统的核心组件,是一个分布式的大数据处理框架。Spark Core提供了多种资源调度管理,通过内存计算、有向无环图等机制保证分布式计算的快速,并引入了RDD的抽象保证数据的高容错性,其重要性描述如下:

  • Spark Core提供了多种运行模式,不仅可以使用自身运行模式处理任务,如本地模式、Standalone,而且可以使用第三方资源调度来处理任务,如YARN、MESOS等。
  • Spark Core 提供了有向无环图的分布式计算框架,并提供内存机制来支持多次迭代计算或者数据共享,大大减少迭代计算的之间读取数据的开销,这对于需要进行对此迭代的数据挖掘和分析性能有极大提升,另外在任务处理过程中移动计算而非移动数据,RDD Partition可以就近读取分布式文件系统中数据块到各个节点内存中进行计算。
  • 在Spark中引入了RDD的抽象,它是分布在一组节点中的只读对象集合,这些集合是弹性的,如果数据一部分丢失,可以根据“血统”进行重建,保证了数据的高容错性。

Spark Streaming: Spark Streaming提供的处理引擎和RDD编程模型可以同时进行批处理和流处理。Spark Streaming使用的是将流数据离散化处理,通过该方式能够进行秒级一下的数据批处理。它使用DStream,简单来说就是一个弹性分布式数据集(RDD)系列,处理实时数据。
Spark Core: Spark SQL可以通过JDBC API将Spark数据集暴露出去,而且还可以用传统的BI和可视化工具在Spark数据上执行类似SQL的查询。
Spark MLlib: MLlib是一个可扩展的Spark机器学习库,由通用的学习算法和工具组成,包括二元分类、线性回归、聚类、协同过滤、梯度下降以及底层优化原语。用于机器学习和统计等场景。
Spark GraphX: GraphX在Spark基础上提供了一站式的数据解决方案,可以高效地完成图计算的完整流水作业。GraphX是用于图计算和并行图计算的新的(alpha)Spark API。通过引入弹性分布式属性图(Resilient Distributed Property Graph),一种顶点和边都带有属性的有向多重图,扩展了Spark RDD。

Spark集群

集群搭建

standalone模式

环境预准备,多台机器互通互联,免密登录,时间同步,之后是选择版本,包括选择Hadoop版本,选择Spark版本,Spark版本之间的差异是什么,怎么选择Scala,怎么选择Java等,官网:http://spark.apache.org/

官网文档:http://spark.apache.org/docs/latest/

Databricks: spark商用

安装:

tar -zxvf spark-1.6.3-bin-hadoop2.6.tgz -C /usr/local
cd /usr/local/spark-1.6.3-bin-hadoop2.6
cd conf/
cp spark-env.sh.template spark-env.sh
vi spark-env.sh

> export JAVA_HOME=/usr/local/jdk1.8.0_181
> export SPARK_MASTER_IP=node01  ##node01修改为自己的主机名
> export SPARK_MASTER_PORT=7077

然后新建slaves文件

vi slaves
> node02
> node03  ##这里添加子节点所在的位置

最后将配置好的Spark分发到其他节点上相同目录

scp -r ./spark-1.6.3-bin-hadoop2.6/ node02:$PWD
scp -r ./spark-1.6.3-bin-hadoop2.6/ node03:$PWD

然后执行:/usr/local/spark-1.6.3-bin-hadoop2.6/sbin/start-all.sh,此时使用命令jps,查看java进程(Master、Worker)是否正常启动,正常,在浏览器输入:master主机IP:8080,查看spark web.

Spark高可用模式

关于Spark集群的单点故障的解决,需要借助zookeeper,并且启动至少两个Master节点来实现高可用,配置如下:

Spark集群规划:node01 node02为Master、node03 node04 node05为Worker
安装配置zookeeper集群,并启动zookeeper集群,停止spark所有服务,修改spark-env.sh,在该配置文件中删掉SPARK_MASTER_IP并添加如下配置(其中zk1,zk2,zk3为zk的hosts列表)

export SPARK_DAEMON_JAVA_OPTS="-Dspark.deploy.recoveryMode=ZOOKEEPER -Dspark.deploy.zookeeper.url=zk1,zk2,zk3 -Dspark.deploy.zookeeper.dir=/spark"

注意:
1.在node01节点上修改slaves配置文件内容指定worker节点
2.在node01上执行sbin/start-all.sh脚本,然后在node02上执行sbin/start-master.sh启动第二个Master

yarn模式

配置:

修改spark-env.sh

export HADOOP_CONF_DIR = /opt/apps/hadoop/etc/hadoop
exprot YARN_CONF_DIR = /opt/apps/hadoop/etc/hadoop

集群架构

sparkContext:sparkContext在spar的应用程序的执行过程中起着主导作用,它负责与程序和spark集群之间进行交互,包括申请集群资源、创建RDD、accumulators及广播变量等、SparkContext是spark的入口,相当于main函数。目前一个JVM进程中可以创建多个sparkContext,但是只有一个active级别的。如果你需要创建一个新的SparkContext实例,必须先调用stop方法停掉当前active级别的SparkContext实例。

注意点:
(1)不同的Spark应用程序对应该不同的Executor,这些Executor在整个应用程序执行期间都存在并且Executor中可以采用多线程的方式执行Task。这样做的好处是,各个Spark应用程序的执行是相互隔离的(主要意思是两个方面,不同应用程序任务调度是独立的,不同应用程序的任务跑在不同JVM上)。除Spark应用程序向外部存储系统写数据进行数据交互这种方式外,各Spark应用程序(sparkContext实例)间无法进行数据共享。
(2)Spark对于其使用的集群资源管理器没有感知能力,只要它能对Executor进行申请并通信即可。这意味着不管使用哪种资源管理器(如Mesos/Yarn),其执行流程都是不变的。这样Spark可以不同的资源管理器进行交互。
(3)Spark应用程序(驱动程序)在整个执行过程中要与Executors进行来回通信。
(4)Driver端负责Spark应用程序任务的调度,因此最好Driver应该靠近Worker节点,最好在一个局域网。

Spark集群的启动流程:

执行start-all.sh后,启动Master进程
Master开始解析conf目录的slaves配置文件,找到相应的Worker节点,开始启动Worker进程
Worker进程开始向Master发送注册信息
Master接受到Worker的注册信息后并保存到内存和磁盘里,然后向Worker发送注册成功信息
Worker开始向Master周期性发送心跳,Master每次接收到心跳后更新WorkerInfo的最后一次心跳时间,若发现worker节点死亡,则删掉节点

Spark任务提交流程

Spark任务提交流程:
1)Driver端首先启动SparkSubmit进程,启动后开始于Master进行通信,此时创建了一个非常重要的对(SparkContext),接着向Master发送任务信息;
2)Master接收到任务信息后,开始资源调度,此时会和所有的Worker进行通信,找到比较空闲的Worker,并通知Worker来取任务和启动相应的Executor;
3) Executor启动后,开始与Driver进行反向注册,接下来Driver开始把任务发送给相应的Executor,Executor开始计算任务。

集群任务部署

spark-submit 应用程序部署工具bin/spark-submit,可以完成将Spark应用程序在local、Standalone、YARN、Mesos等集群上的快捷部署。

查看所有spark-submit参数:./spark-submit

[root@hadoop01 bin]# ./spark-submit
Usage: spark-submit [options] <app jar | python file> [app arguments]
Usage: spark-submit --kill [submission ID] --master [spark://...]
Usage: spark-submit --status [submission ID] --master [spark://...]

Options:
  --master MASTER_URL         spark://host:port, mesos://host:port, yarn, or local.
  --deploy-mode DEPLOY_MODE   Whether to launch the driver program locally ("client") or
                              on one of the worker machines inside the cluster ("cluster")
                              (Default: client).
  --class CLASS_NAME          Your application's main class (for Java / Scala apps).
  --name NAME                 A name of your application.
  --jars JARS                 Comma-separated list of local jars to include on the driver
                              and executor classpaths.
  --packages                  Comma-separated list of maven coordinates of jars to include
                              on the driver and executor classpaths. Will search the local
                              maven repo, then maven central and any additional remote
                              repositories given by --repositories. The format for the
                              coordinates should be groupId:artifactId:version.
  --exclude-packages          Comma-separated list of groupId:artifactId, to exclude while
                              resolving the dependencies provided in --packages to avoid
                              dependency conflicts.
  --repositories              Comma-separated list of additional remote repositories to
                              search for the maven coordinates given with --packages.
  --py-files PY_FILES         Comma-separated list of .zip, .egg, or .py files to place
                              on the PYTHONPATH for Python apps.
  --files FILES               Comma-separated list of files to be placed in the working
                              directory of each executor.

  --conf PROP=VALUE           Arbitrary Spark configuration property.
  --properties-file FILE      Path to a file from which to load extra properties. If not
                              specified, this will look for conf/spark-defaults.conf.

  --driver-memory MEM         Memory for driver (e.g. 1000M, 2G) (Default: 1024M).
  --driver-java-options       Extra Java options to pass to the driver.
  --driver-library-path       Extra library path entries to pass to the driver.
  --driver-class-path         Extra class path entries to pass to the driver. Note that
                              jars added with --jars are automatically included in the
                              classpath.

  --executor-memory MEM       Memory per executor (e.g. 1000M, 2G) (Default: 1G).

  --proxy-user NAME           User to impersonate when submitting the application.

  --help, -h                  Show this help message and exit
  --verbose, -v               Print additional debug output
  --version,                  Print the version of current Spark

 Spark standalone with cluster deploy mode only:
  --driver-cores NUM          Cores for driver (Default: 1).

 Spark standalone or Mesos with cluster deploy mode only:
  --supervise                 If given, restarts the driver on failure.
  --kill SUBMISSION_ID        If given, kills the driver specified.
  --status SUBMISSION_ID      If given, requests the status of the driver specified.

 Spark standalone and Mesos only:
  --total-executor-cores NUM  Total cores for all executors.

 Spark standalone and YARN only:
  --executor-cores NUM        Number of cores per executor. (Default: 1 in YARN mode,
                              or all available cores on the worker in standalone mode)

 YARN-only:
  --driver-cores NUM          Number of cores used by the driver, only in cluster mode
                              (Default: 1).
  --queue QUEUE_NAME          The YARN queue to submit to (Default: "default").
  --num-executors NUM         Number of executors to launch (Default: 2).
  --archives ARCHIVES         Comma separated list of archives to be extracted into the
                              working directory of each executor.
  --principal PRINCIPAL       Principal to be used to login to KDC, while running on
                              secure HDFS.
  --keytab KEYTAB             The full path to the file that contains the keytab for the
                              principal specified above. This keytab will be copied to
                              the node running the Application Master via the Secure
                              Distributed Cache, for renewing the login tickets and the
                              delegation tokens periodically.

spark-submit参数以及参数解读:

./spark-submit \
--class <main-class> \
--master <master-url> \
--executor-memory 1G \
--total-executor-cores <number of cores> \
... # other option
<application - jar>
[application-arguments]

提交Spark提供的利用蒙特·卡罗算法求π的例子,其中100这个参数是计算因子

/usr/local/spark-1.6.3-bin-hadoop2.6/bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master spark://hadoop01:7077 \
/usr/local/spark-1.6.3-bin-hadoop2.6/lib/spark-examples-1.6.3-hadoop2.6.0.jar \
100

Spark shell

Spark Shell是什么

spark shell 也是一个客户端,他是spark自带的交互式的shell程序,方便用户进行交互式编程,用户可以在该命令行下用scala或者python编写spark程序,Spark Shell程序一般用作Spark程序测试练习来用。

Spark Shell启动模式

Spark shell有两种模式:local模式和cluster模式

1)local模式

/usr/local/spark-1.6.3-bin-hadoop2.6/bin/spark-shell

local模式下:

  • 任务在本地执行,不会提交任务到集群
  • local模式仅在本机启动一个spark-submit进程,没有雨进群建立联系
  • 在spark UI上查找不到应用程序的提交

2)cluster模式

/usr/local/spark-1.6.3-bin-hadoop2.6/bin/spark-shell \
--master spark://hadoop01:7077 \
--executor-memory 1G \
--total-executor-cores 2

参数说明:
–master spark://hadoop01:7077 指定Spark集群的Master的地址,即spark web上的URL
–executor-memory 1G 指定每个worker可用内存为1G
–total-executor-cores 2 指定整个集群使用的cup核数为2个
注:spark-shell中已经默认将SparkContext和SQLContext对象初始化为sc和sqlContext。如果需要用到,则直接应用sc和sqlContext即可

使用Spark Shell实现WordCount

在spark shell中用Scala语言编写spark程序:

sc.textFile("/root/123.txt").flatMap(.split(" ")).map((,1)).reduceByKey(+).saveAsTextFile("/root/out123")

说明:
sc是SparkContext对象,该对象是提交spark程序的入口
textFile("/root/123.txt")是读取数据,当然也可以在hdfs中读取
flatMap(.split(""))先map再压平
map((
,1))将单词和1构成元组
reduceByKey(+)按照key进行reduce,并将value累加
saveAsTextFile("/root/out123")将结果写入磁盘

编写Spark应用程序

Scala实现WordCount
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
object SparkWordCount {
  def main(args: Array[String]): Unit = {
      //创建配置文件
    // setAppName设置应用程序名称
    // setMaster 设置为本地测试模式
    // local[2]:本地用两个线程模拟集群运行任务
    // local:本地用一个线程模拟集群运行任务
    // local[*]:本地用所有空闲的线程模拟集群运行任务

    val conf:SparkConf = new SparkConf()
      .setAppName("sparkwc")
      .setMaster("local")
    //local模拟一个集群环境运行任务
    //local[num],使用的线程数目取模拟一个集群
    //创建spark上下文对象,也叫集群入口类
    val sc:SparkContext = new SparkContext(conf)

    // 读取HDFS的数据
    val lines: RDD[String] = sc.textFile(args(0))
    // val lines: RDD[String] = sc.parallelize(Array("hello tom", "hello jerry hello jerry","hello hello"))
    // 对数据做单词计数
    val words: RDD[String] = lines.flatMap(_.split(" "))
    val tuples: RDD[(String, Int)] = words.map((_, 1))
    val reduced: RDD[(String, Int)] = tuples.reduceByKey(_+_)
    val res: RDD[(String, Int)] = reduced.sortBy(_._2, false)
    // 打印结果
    // println(res.collect.toBuffer)
    // 保存
    res.saveAsTextFile(args(1))
    sc.stop()
  }
}
Java实现WordCount
public class JavaWordCount {
    public static void main(String[] args) {
        // 配置信息类
        SparkConf conf = new SparkConf()
                .setAppName("JavaWC")
                .setMaster("local[2]");

        // 上下文对象
        final JavaSparkContext jsc = new JavaSparkContext(conf);

        // 获取数据
        final JavaRDD<String> lines = jsc.textFile(args[0]);
        // 切分
        final JavaRDD<String> words = lines.flatMap(new FlatMapFunction<String, String>() {
            @Override
            public Iterable<String> call(String s) throws Exception {
                return Arrays.asList(s.split(" "));
            }
        });
        // 把每个单词生成一个个元组
        final JavaPairRDD<String, Integer> pairRDD = words.mapToPair(
                new PairFunction<String, String, Integer>() {
                    @Override
                    public Tuple2<String, Integer> call(String s) throws Exception {
                        return new Tuple2<String, Integer>(s, 1);
                    }
                });

        // 聚合
        final JavaPairRDD<String, Integer> reduced = pairRDD.reduceByKey(new Function2<Integer,
                        Integer, Integer>() {
            @Override
            public Integer call(Integer v1, Integer v2) throws Exception {
                return v1 + v2;
            }
        });
        
        // Java并没有提供sortBy算子,如果需要一value来进行排序时,此时需要把数据反转一下,
        // 排序完成后,再反转回来
        final JavaPairRDD<Integer, String> swaped = reduced.mapToPair(new PairFunction<Tuple2<String, Integer>, Integer, String>() {
            @Override
            public Tuple2<Integer, String> call(Tuple2<String, Integer> tup) throws Exception {
                return tup.swap();
            }});
        // 排序
        final JavaPairRDD<Integer, String> sorted = swaped.sortByKey(false);

        // 把数据再反转回来
        final JavaPairRDD<String, Integer> res = sorted.mapToPair(new PairFunction<Tuple2<Integer, String>, String, Integer>() {
            @Override
            public Tuple2<String, Integer> call(Tuple2<Integer, String> tup) throws Exception {
                return tup.swap();
                }
        });
        
        // System.out.println(reduced.collect());`
        res.saveAsTextFile(args[1]);
        jsc.stop();   
    }
}

测试:使用Maven把我们写好的程序打包,上传到spark的节点上,使用spark-submit进行测试即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值