简介
Spark是专为大规模数据处理而设计的快速通用的计算引擎,第一次看到这句话估计会比较抽象。其实可以和MySQL数据库类比。
只不过侧重点不同,MySQL的侧重点在数据存储和查询,Spark的侧重点在于数据处理。MySQL处理的是预定义格式的数据,Spark处理的是没有预定义格式的数据,包括各种日志文件、用户行为之类的数据量比较大的文件数据分析处理。
例如,从大量用户行为日志中分析用户可能对哪些商品有兴趣,这个可以根据用户在页面驻留的时间,进入的次数等分析。
这种随时都在收集的,日志量非常的大的数据显然不适合直接存储在MySQL之类的关系数据库中,一般都是直接写日志。
那么分析这类日志Spark就非常合适了。
Spark下载与安装
下载之后解压就可以了
单机基本不需要额外的配置,可以直接运行spark-shell
spark UI界面
集群
拷贝conf目录下的.template并且重命名为,添加配置如下:
export JAVA_HOME=/usr/local/java/jdk873
export HADOOP_CONF_DIR=/usr/local/hadoop/hadoop-3.0.2/etc/hadoop
export SPARK_MASTER_HOST=192.168.9.6
# 提交Application的端口
export SPARK_MASTER_PORT=7077
# 每一个Worker最多可以使用的cpu
export SPARK_WORKER_CORES=1
# 每一个Worker最多可以使用的内存
export SPARK_WORKER_MEMORY=1g
export HADOOP_CONF_DIR=/usr/hadoop/xxx
不是必须的,但是如果要使用yarn方式提交就必须配置,就是使用下面的命令提交:
spark-submit
--class org.curitis.Start
--master yarn
--deploy-mode cluster
start.jar
Spark提交方式后面详细介绍。
如果要使用ZK,使用下面的配置代替SPARK_MASTER_PORT=7077
export SPARK_DAEMON_JAVA_OPTS="-Dspark.deploy.recoveryMode=ZOOKEEPER -Dspark.deploy.zookeeper.url=192.168.9.7,192.168.9.8,192.168.9.9 -Dspark.deploy.zookeeper.dir=/zk"
url是zk部署的地址。
拷贝slaves.template并且重命名为slaves,添加其他节点:
192.168.9.7
192.168.9.8
192.168.9.9
在主节点运行:
sparkUI:http://192.168.9.6:4040 提交Application的端口:http://192.168.9.6:7077
RDD
Spark是一个独立的计算引擎,不依赖hadoop,所以可以直接解压spark就可以使用了。Spark的核心是RDD(Resilient Distributed Dataset,弹性分布式数据集),处理数据集合。可以使用hdfs做为数据源,也可以使用HBase、Hive甚至文件做为数据源。
这里先简单的介绍一下RDD创建,可以使用下面的命令打开一个spark shell交互窗口:
spark-shell
从集合中创建RDD
主要使用parallelize和makeRDD函数
sc.parallelize(List(1,2,3))
sc.makeRDD(List(1,2,3))
sc.parallelize(Array(1 to 10))
从外部存储创建RDD
sc.textFile("hdfs://127.0.0.1:9000/tmp/in.txt")
sc.textFile("file://G:/tmp/in2.txt")
Java API
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.sql.SparkSession;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
/**
* http:///docs/latest/submitting-applications.html
*/
public class SparkStart {
public static void main(String[] args) {
SparkConf sparkConf = new SparkConf();
sparkConf.setAppName("create JavaSparkContext");
sparkConf.setMaster("local[*]");
//spark ui http://localhost:4040/jobs/
JavaSparkContext sc = new JavaSparkContext(sparkConf);
List<Integer> data = Arrays.asList(1, 2, 3, 4, 5);
JavaRDD<Integer> distData = sc.parallelize(data);
Integer sum = distData.reduce((a, b) -> a + b);
System.out.println(sum);
Scanner scanner = new Scanner(System.in);
scanner.nextLine();
}
private static JavaSparkContext createSparkContext(){
SparkConf sparkConf = new SparkConf();
sparkConf.setAppName("create JavaSparkContext");
sparkConf.setMaster("local[*]");
sparkConf.set("spark.yarn.tags","");//逗号分隔的字符串,传递YARN应用tags。其值将出现在YARN Application Reports中,可以用来过滤和查询YARN应用。
sparkConf.set("spark.yarn.maxAppAttempts","");//提交应用最大尝试次数。不应大于YARN全局配置的最大尝试次数。 (yarn.resourcemanager.am.max-attempts in YARN)
sparkConf.set("spark.yarn.user.classpath.first","");//是否将用户jars放在Spark类路径之前
sparkConf.set("spark.yarn.config.gatewayPath","");//与spark.yarn.config.replacementPath配合使用
sparkConf.set("spark.yarn.config.replacementPath","");//某些路径,可能在网关主机上能正常访问,而在其他节点上的访问方式可能不同。对于这样的路径,需要本属性配合 spark.yarn.config.replacementPath组合使用,对于支持异构配置的集群,必须配置好这两个值,Spark才能正确地启动远程进程。replacement path 通常包含一些YARN导出的环境变量(因此,对Spark containers可见)。例如,如果网关节点上Hadoop库安装在 /disk1/hadoop,并且其导出环境变量为 HADOOP_HOME,就需要将 spark.yarn.config.gatewayPath 设置为 /disk1/hadoop 并将 replacement path设为 $HADOOP_HOME,这样才能在远程节点上以正确的环境变量启动进程。
sparkConf.set("spark.yarn.queue","");//yarn上使用的队列名,默认为default
sparkConf.set("spark.yarn.historyServer.address","");//Spark history server地址,如:host.com:18080 。这个地址不要包含协议头(http://)。默认不设置,因为history server是可选的。应用程序结束以后,YARN资源管理器web UI通过这个地址链接到Spark history server UI。对于这属性,可以使用YARN属性变量,且这些变量是Spark在运行时组装的。例如,如果Spark history server和YARN资源管理器(ResourceManager)部署在同一台机器上运行,那么这个属性可以设置为 ${hadoopconf-yarn.resourcemanager.hostname}:18080
sparkConf.set("spark.yarn.archive","");//包含带有Spark类的jar文件的归档文件的位置
sparkConf.set("spark.yarn.jars","");//Spark jar文件位置,如果需要覆盖默认位置,请设定这个值。默认的,Spark on YARN会使用本地的Spark jar包,但Spark jar包同样可以使用整个集群可读的HDFS文件位置。这使YARN可以在各节点上缓存Spark jar包,而不需要每次运行一个应用的时候都要分发。使用 hdfs:///some/path 来指定HDFS上jar包文件路径。
sparkConf.set("spark.yarn.dist.archives","");//逗号分隔的文档列表,其指向的文档将被提取到每个执行器的工作目录下,默认无
sparkConf.set("spark.yarn.dist.files","");//逗号分隔的文件列表,其指向的文件将被复制到每个执行器的工作目录下,默认无
sparkConf.set("spark.yarn.dist.jars","");//
sparkConf.set("spark.yarn.preserve.staging.files","");//是否保存HDFS中由于job产生的临时文件,默认为 false 。如果设置为true,那么在作业运行完之后,会避免工程jar等文件被删除掉
sparkConf.set("spark.yarn.submit.file.replication","");//由spark提交到HDFS的文件的副本数,比如工程jar,依赖jar,配置文件等,默认 1
sparkConf.set("spark.yarn.stagingDir","");//提交应用时,staging的目录
sparkConf.set("spark.yarn.submit.waitAppCompletion","");//cluster mode下,client是否等到作业运行完再退出,默认为true
sparkConf.set("spark.yarn.report.interval","");//cluster mode下,当前app状态报告的间隔,默认1s
sparkConf.set(".waitTime","");//cluster模式下,Application Master要等待SparkContext初始化的时长; client模式下,application master等待driver来连接它的时长,默认 100s
sparkConf.set(".nodeLabelExpression","");//一个YARN节点标签表达式(node label expression),以此来限制AM可以被调度到哪些节点上执行。只有Hadoop 2.6+才能支持节点标签表达式,所以如果用其他版本运行,这个属性将被忽略。
sparkConf.set("spark.yarn.containerLauncherMaxThreads","");//application master能用来启动executor container的最大线程数量 ,默认25
sparkConf.set("spark.yarn.max.executor.failures","");//整个作业判定为失败之前,executor最大的失败次数 ,默认 executor数量*2,最小3
sparkConf.set("spark.yarn.scheduler.reporterThread.maxFailures","");//
sparkConf.set("spark.yarn.scheduler.heartbeat.interval-ms","");//application master向resourcemanager发送心跳的间隔,单位ms ,默认3000ms
sparkConf.set("spark.yarn.scheduler.initial-allocation.interval","");//Spark AM的初始带外心跳间隔(有待定的资源申请时)。其值不应该大于 spark.yarn.scheduler.heartbeat.interval-ms。该资源分配间隔会在每次带外心跳成功后但仍有待定资源申请时倍增,直至达到 spark.yarn.scheduler.heartbeat.interval-ms 所设定的值,默认为 200ms
sparkConf.set("spark.yarn.services","");//要添加到调度程序中的服务的类名的逗号分隔列表
sparkConf.set(".cores","");//Application Master使用的cpu数量,默认 1
sparkConf.set(".extraJavaOptions","");//client-mode下AM的JVM参数
sparkConf.set(".extraLibraryPath","");//client-mode下AM的额外库路径
sparkConf.set(".memoryOverhead","");//每个am的堆外内存大小,用来存放诸如常量字符串等东西,默认为AM内存的7%
sparkConf.set(".memory","");//YARN Application Master使用的内存总量,默认512MB
sparkConf.set("spark.driver.cores","");//cluster模式下,driver使用的cpu core数量,driver与Application Master运行在一个进程中,所以也控制了Application Master的cpu数量,默认 为1
sparkConf.set("spark.yarn.driver.memoryOverhead","");//每个driver的堆外内存大小,用来存放诸如常量字符串等东西,默认为driver内存 * 0.10或者 384MB中较大者
sparkConf.set("spark.executor.cores","");//
sparkConf.set("spark.yarn.executor.memoryOverhead","");//每个executor的堆外内存大小,用来存放诸如常量字符串等东西,默认为executor内存 * 0.10或者 384MB中较大者
sparkConf.set("spark.yarn.executor.nodeLabelExpression","");//一个YARN节点标签表达式(node label expression),以此来限制执行器可以被调度到哪些节点上启动。只有Hadoop 2.6+才能支持节点标签表达式,所以如果在其他版本上运行时,这个属性将被忽略
sparkConf.set("spark.executor.instances","");//执行器个数。注意,这个属性和 spark.dynamicAllocation.enabled是不兼容的。如果同时设置了 spark.dynamicAllocation.enabled,那么动态分配将被关闭,并使用 spark.executor.instances 所设置的值。 默认2
sparkConf.set("spark.yarn.credentials.file.retention.count","");//
sparkConf.set("spark.yarn.credentials.file.retention.days","");//
sparkConf.set("spark.yarn.credentials.file.retention.days","");//
sparkConf.set("spark.yarn.access.namenodes","");//spark作业能访问的hdfs namenode地址
sparkConf.set("spark.yarn.credentials.file","");//
sparkConf.set("spark.yarn.user.jar","");//内部配置,将用户jar的位置传播到驱动程序/执行程序
sparkConf.set("spark.yarn.secondary.jars","");//内部配置,以传播任何额外jar的位置,以添加到执行器的类路径中
sparkConf.set("spark.yarn.cache.filenames","");//
sparkConf.set("spark.yarn.cache.sizes","");//
sparkConf.set("spark.yarn.cache.timestamps","");//
sparkConf.set("spark.yarn.cache.visibilities","");//
sparkConf.set("spark.yarn.cache.types","");//
sparkConf.set("spark.yarn.cache.confArchive","");//conf archive在HDFS中的路径
JavaSparkContext sc = new JavaSparkContext(sparkConf);
return sc;
}
//spark sql
private static SparkSession createSparkSession(){
SparkSession sparkSession = SparkSession
.builder()
.appName("create SparkSession")
.master("local[*]")
.config("spark.yarn.tags", "")//逗号分隔的字符串,传递YARN应用tags。其值将出现在YARN Application Reports中,可以用来过滤和查询YARN 应用。
.config("spark.yarn.maxAppAttempts", "")//提交应用最大尝试次数。不应大于YARN全局配置的最大尝试次数。 (yarn.resourcemanager.am.max-attempts in YARN)
.config("spark.yarn.user.classpath.first", "")//是否将用户jars放在Spark类路径之前
.config("spark.yarn.config.gatewayPath", "")//与spark.yarn.config.replacementPath配合使用
.config("spark.yarn.config.replacementPath", "")//某些路径,可能在网关主机上能正常访问(Spark应用启动的地方),而在其他节点上的访问方式(路径)可能不同。对于这样的路径,需要本属性配合 spark.yarn.config.replacementPath组合使用,对于支持异构配置的集群,必须配置好这两个值,Spark才能正确地启动远程进程。replacement path 通常包含一些YARN导出的环境变量(因此,对Spark containers可见)。例如,如果网关节点上Hadoop库安装在 /disk1/hadoop,并且其导出环境变量为 HADOOP_HOME,就需要将 spark.yarn.config.gatewayPath 设置为 /disk1/hadoop 并将 replacement path设为 $HADOOP_HOME,这样才能在远程节点上以正确的环境变量启动进程。
.config("spark.yarn.queue", "")//yarn上使用的队列名,默认为default
.config("spark.yarn.historyServer.address", "")//Spark history server地址,如:host.com:18080 。这个地址不要包含协议头(http://)。默认不设置,因为history server是可选的。应用程序结束以后,YARN资源管理器web UI通过这个地址链接到Spark history server UI。对于这属性,可以使用YARN属性变量,且这些变量是Spark在运行时组装的。例如,如果Spark history server和YARN资源管理器(ResourceManager)部署在同一台机器上运行,那么这个属性可以设置为 ${hadoopconf-yarn.resourcemanager.hostname}:18080
.config("spark.yarn.archive", "")//包含带有Spark类的jar文件的归档文件的位置
.config("spark.yarn.jars", "")//Spark jar文件位置,如果需要覆盖默认位置,请设定这个值。默认的,Spark on YARN会使用本地的Spark jar包,但Spark jar包同样可以使用整个集群可读的HDFS文件位置。这使YARN可以在各节点上缓存Spark jar包,而不需要每次运行一个应用的时候都要分发。使用 hdfs:///some/path 来指定HDFS上jar包文件路径。
.config("spark.yarn.dist.archives", "")//逗号分隔的文档列表,其指向的文档将被提取到每个执行器的工作目录下,默认无
.config("spark.yarn.dist.files", "")//逗号分隔的文件列表,其指向的文件将被复制到每个执行器的工作目录下,默认无
.config("spark.yarn.dist.jars", "")//
.config("spark.yarn.preserve.staging.files", "")//是否保存HDFS中由于job产生的临时文件,默认为 false 。如果设置为true,那么在作业运行完之后,会避免工程jar等文件被删除掉
.config("spark.yarn.submit.file.replication", "")//由spark提交到HDFS的文件的副本数,比如工程jar,依赖jar,配置文件等,默认 1
.config("spark.yarn.stagingDir", "")//提交应用时,staging的目录
.config("spark.yarn.submit.waitAppCompletion", "")//cluster mode下,client是否等到作业运行完再退出,默认为true
.config("spark.yarn.report.interval", "")//cluster mode下,当前app状态报告的间隔,默认1s
.config(".waitTime", "")//cluster模式下,Application Master要等待SparkContext初始化的时长; client模式下,application master等待driver来连接它的时长,默认 100s
.config(".nodeLabelExpression", "")//一个YARN节点标签表达式(node label expression),以此来限制AM可以被调度到哪些节点上执行。只有Hadoop 2.6+才能支持节点标签表达式,所以如果用其他版本运行,这个属性将被忽略。
.config("spark.yarn.containerLauncherMaxThreads", "")//application master能用来启动executor container的最大线程数量 ,默认25
.config("spark.yarn.max.executor.failures", "")//整个作业判定为失败之前,executor最大的失败次数 ,默认 executor数量*2,最小3
.config("spark.yarn.scheduler.reporterThread.maxFailures", "")//
.config("spark.yarn.scheduler.heartbeat.interval-ms", "")//application master向resourcemanager发送心跳的间隔,单位ms ,默认3000ms
.config("spark.yarn.scheduler.initial-allocation.interval", "")//Spark AM的初始带外心跳间隔(有待定的资源申请时)。其值不应该大于 spark.yarn.scheduler.heartbeat.interval-ms。该资源分配间隔会在每次带外心跳成功后但仍有待定资源申请时倍增,直至达到 spark.yarn.scheduler.heartbeat.interval-ms 所设定的值,默认为 200ms
.config("spark.yarn.services", "")//要添加到调度程序中的服务的类名的逗号分隔列表
.config(".cores", "")//Application Master使用的cpu数量,默认 1
.config(".extraJavaOptions", "")//client-mode下AM的JVM参数
.config(".extraLibraryPath", "")//client-mode下AM的额外库路径
.config(".memoryOverhead", "")//每个am的堆外内存大小,用来存放诸如常量字符串等东西,默认为AM内存的7%
.config(".memory", "")//YARN Application Master使用的内存总量,默认512MB
.config("spark.driver.cores", "")//cluster模式下,driver使用的cpu core数量,driver与Application Master运行在一个进程中,所以也控制了Application Master的cpu数量,默认 为1
.config("spark.yarn.driver.memoryOverhead", "")//每个driver的堆外内存大小,用来存放诸如常量字符串等东西,默认为driver内存 * 0.10或者 384MB中较大者
.config("spark.executor.cores", "")//
.config("spark.yarn.executor.memoryOverhead", "")//每个executor的堆外内存大小,用来存放诸如常量字符串等东西,默认为executor内存 * 0.10或者 384MB中较大者
.config("spark.yarn.executor.nodeLabelExpression", "")//一个YARN节点标签表达式(node label expression),以此来限制执行器可以被调度到哪些节点上启动。只有Hadoop 2.6+才能支持节点标签表达式,所以如果在其他版本上运行时,这个属性将被忽略
.config("spark.executor.instances", "")//执行器个数。注意,这个属性和 spark.dynamicAllocation.enabled是不兼容的。如果同时设置了 spark.dynamicAllocation.enabled,那么动态分配将被关闭,并使用 spark.executor.instances 所设置的值。 默认2
.config("spark.yarn.credentials.file.retention.count", "")//
.config("spark.yarn.credentials.file.retention.days", "")//
.config("spark.yarn.credentials.file.retention.days", "")//
.config("spark.yarn.access.namenodes", "")//spark作业能访问的hdfs namenode地址
.config("spark.yarn.credentials.file", "")//
.config("spark.yarn.user.jar", "")//内部配置,将用户jar的位置传播到驱动程序/执行程序
.config("spark.yarn.secondary.jars", "")//内部配置,以传播任何额外jar的位置,以添加到执行器的类路径中
.config("spark.yarn.cache.filenames", "")//
.config("spark.yarn.cache.sizes", "")//
.config("spark.yarn.cache.timestamps", "")//
.config("spark.yarn.cache.visibilities", "")//
.config("spark.yarn.cache.types", "")//
.config("spark.yarn.cache.confArchive", "")//conf archive在HDFS中的路径
.getOrCreate();
return sparkSession;
}
}
pom
<project xmlns="http:///POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http:///POM/4.0.0
http:///xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.curitis</groupId>
<packaging>jar</packaging>
<artifactId>spark-learn</artifactId>
<version>1.0.0</version>
<properties>
<spring.test.version>5.1.8.RELEASE</spring.test.version>
<junit.test.version>4.11</junit.test.version>
<spark.version>2.4.3</spark.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.12</artifactId>
<version>${spark.version}</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.12</artifactId>
<version>${spark.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.56</version>
</dependency>
<!--test-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.test.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.test.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Spark提交方式
Local方式
Local模式就是运行在一台计算机上的模式,通常就是用于在本机上练手和测试。
- local: 所有计算都运行在一个线程当中,没有任何并行计算,用于本机执行一些测试代码
- local[K]: 指定使用K个线程来运行计算,比如local[4]就是运行4个worker线程
- local[*]: 按照cpu数量来设置worker线程数了
- local[K,F]: K个工作线程,最多失败F个
spark-submit --master local[*]
cluster方式
cluster方式就是使用集群运行的方式,它又包含3中模式:
standalone模式
这种模式下,Spark会自己负责资源的管理调度。它将cluster中的机器分为master机器和worker机器,master通常就一个,管理worker的节点,worker就是负责计算任务节点
spark-submit --cluster cluster_name --master spark://host:port
--master就是指定master那台机器的地址和端口
mesos模式
使用mesos来管理资源调度,自然就应该用mesos模式了
spark-submit --cluster cluster_name --master mesos://host:port
yarn模式
yarn来管理资源调度,由于很多时候我们需要和mapreduce使用同一个集群,所以都采用Yarn来管理资源调度,这也是生产环境大多采用yarn模式的原因。yarn模式又分为yarn cluster模式和yarn client模式。
- yarn cluster: 这个就是生产环境常用的模式,所有的资源调度和计算都在集群环境上运行。
- yarn client: 这个是说Spark Driver和ApplicationMaster进程均在本机运行,而计算任务在cluster上
spark-submit --cluster cluster_name --master yarn-cluster
spark-submit --class org.curitis.Start --name 'Start' --master yarn --driver-memory 1g --executor-memory 6g --executor-cores 4 --deploy-mode cluster --jars hdfs:///user/root/spark/spark-2.4/lib/user_lib/*.jar start.jar
文档
集群模式 spark提交 spark文档 spark java spark example spark sql
RDD的常用操作
RDD的操作分为两种,一种是转化(transformation)操作,一种是执行(action)操作,类似于SQL中的聚合函数。
转化(transformation)
转化操作并不会立即执行,而是到了执行操作才会被执行转化操作。
map
参数是函数,函数应用于RDD每一个元素,返回值是新的RDD
flatMap
参数是函数,函数应用于RDD每一个元素,将元素数据进行拆分,变成迭代器,返回值是新的RDD
filter
参数是函数,函数会过滤掉不符合条件的元素,返回值是新的RDD
distinct
没有参数,将RDD里的元素进行去重操作
union
参数是RDD,生成包含两个RDD所有元素的新RDD
intersection
参数是RDD,求出两个RDD的共同元素
subtract
参数是RDD,将原RDD里和参数RDD里相同的元素去掉
cartesian
参数是RDD,求两个RDD的笛卡儿积
行动(action)
collect
返回RDD所有元素
count
RDD里元素个数
val textFile = spark.read.textFile("file:///G:/tmp/in2.txt")
textFile.count()
textFile.first()
注意使用spark.read.textFile读取本地文件是以/开头的。
会把读到的数据按行拆分放到Datasets中。
countByValue
各元素在RDD中出现次数
reduce
并行整合所有RDD数据,例如求和操作
fold
和reduce功能一样,不过fold带有初始值
aggregate
和reduce功能一样,但是返回的RDD数据类型和原RDD不一样
foreach
对RDD每个元素都是使用特定函数