【Spark征服之路-2.5-Spark-Core编程(一)】

环境准备

  1. Jdk1.8版本
  2. Scala2.12版本
  3. Idea集成开发环境中需要安装scala插件

环境配置

· 添加 Scala 插件

Spark 由 Scala 语言开发的,所以接下来的开发所使用的语言也为 Scala,当前使用的 Spark 版本为 3.0.0,默认采用的 Scala 编译版本为 2.12,所以后续开发时,我们依然采用2.12的scala版本。开发前请保证 IDEA 开发工具中含有 Scala 开发插件

File---Settings---plugins

创建spark实现的WordCount程序

1 . 创建Maven项目

2 . 在pom.xml中添加依赖

<dependencies >
<dependency >
<groupId >org.apache.spark</groupId >
<artifactId >spark-core_2.12</artifactId >
<version >3.0.0</version >
</dependency >
<dependency >
<groupId >org.apache.maven.plugins</groupId >
<artifactId >maven-assembly-plugin</artifactId >
<version >3.1.0</version >
</dependency >
</dependencies >

<build >
<plugins >
<!-- 该插件用于将 Scala 代码编译成 class 文件 -->
<plugin >
<groupId >net.alchim31.maven</groupId >
<artifactId >scala-maven-plugin</artifactId >
<version >3.2.2</version >
<executions >
<execution >
<!-- 声明绑定到 maven compile 阶段 -->
<goals >
<goal >testCompile</goal >
</goals >
</execution >
</executions >
</plugin >
<plugin >
<groupId >org.apache.maven.plugins</groupId >
<artifactId >maven-assembly-plugin</artifactId >
<version >3.1.0</version >
<configuration >
<descriptorRefs >
<descriptorRef >jar-with-dependencies</descriptorRef >
</descriptorRefs >
</configuration >
<executions >
<execution >
<id >make-assembly</id >
<phase >package</phase >
<goals >
<goal >single</goal >
</goals >
</execution >
</executions >
</plugin >
</plugins >
</build >

保存之后重新加载。

3.创建Spark-core子模块

4 . 将spark-core当中的java文件夹重命名为scala。

5 . 在scala文件夹中创建Scala的object程序。

6 . 编写wordCount的spark程序

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

object WordCount {
def main(args: Array[String]): Unit = {
// 创建 Spark 运行配置对象
val sparkConf = new SparkConf().setMaster("local[*]" ).setAppName("WordCount" )
// 创建 Spark 上下文环境对象(连接对象)
val sc : SparkContext = new SparkContext(sparkConf)
// 读取文件数据
val fileRDD: RDD[String] = sc.

textFile(" Spark-core /input/word.txt" )
// 将文件中的数据进行分词
val wordRDD: RDD[String] = fileRDD.flatMap( .split(" " ) )
// 转换数据结构 word => (word, 1)
val word2OneRDD: RDD[(String, Int)] = wordRDD.map((
,1))
// 将转换结构后的数据按照相同的单词进行分组聚合
val word2CountRDD: RDD[(String, Int)] = word2OneRDD.reduceByKey(+)
// 将数据聚合结果采集到内存中
val word2Count: Array[(String, Int)] = word2CountRDD.collect()
// 打印结果
word2Count.foreach(println )
// 关闭 Spark 连接
sc.stop()

}
}

7 . 在Spark-core中创建名为input的文件夹,在此文件夹中创建word.txt文件,并在文件中添加需要进行统计的语句。

测试文本:

Spark is a unified analytics engine for large-scale data processing

It provides high-level APIs in Scala Java Python and R and an optimized engine that

supports general computation graphs for data analysis

It also supports a rich set of higher-level tools including Spark SQL for SQL and DataFrames

MLlib for machine learning GraphX for graph processing and Structured Streaming for stream processing

8. 运行编写好的Word C ount程序

9 . 配置日志文件

执行过程中,会产生大量的执行日志,如果为了能够更好的查看程序的执行结果,可以在项

目的 resources 目录中创建 log4j.properties 文件,并添加日志配置信息:

log4j.rootCategory =ERROR, console
log4j.appender.console =org.apache.log4j.ConsoleAppender
log4j.appender.console.target =System.err
log4j.appender.console.layout =org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern =%d{yy/MM/ddHH:mm:ss} %p %c{1}: %m%n
# Set the default spark-shell log level to ERROR. When running the spark-shell,the
# log level for this class is used to overwrite the root logger's log level, so that
# the user can have different defaults for the shell and regular Spark apps.
log4j.logger.org.apache.spark.repl.Main =ERROR
# Settings to quiet third party logs that are too verbose
log4j.logger.org.spark_project.jetty =ERROR
log4j.logger.org.spark_project.jetty.util.component.AbstractLifeCycle =ERROR
log4j.logger.org.apache.spark.repl.SparkIMainexprTyper**** =****ERROR**** ****log4j.logger.org.apache.spark.repl.SparkILoopSparkILoopInterpreter =ERROR
log4j.logger.org.apache.parquet =ERROR
log4j.logger.parquet =ERROR
# SPARK-9183: Settings to avoid annoying messages when looking up nonexistent UDFs in SparkSQL with Hive support
log4j.logger.org.apache.hadoop.hive.metastore.RetryingHMSHandler =FATAL
log4j.logger.org.apache.hadoop.hive.ql.exec.FunctionRegistry =ERROR

1 0. 配置完成后重新执行代码

1 1. 常见问题解决

如果本机操作系统是 Windows,在程序中使用了 Hadoop 相关的东西,比如写入文件到 HDFS,则会遇到如下异常:

出现这个问题的原因,并不是程序的错误,而是 windows 系统用到了 hadoop 相关的服 务,解决办法是通过配置关联到 windows 的系统依赖就可以了

首先确保在本地磁盘中有hadoop的相关内容且配置了环境变量

然后在Idea中配置 Run Configuration,添加 HADOOP_HOME 变量

创建RDD

在 Spark 中创建 RDD 的创建方式可以分为四种:

1. 从集合(内存)中创建 RDD

从集合中创建 RDD,Spark 主要提供了两个方法:parallelize 和 makeRDD

val sparkConf =
new SparkConf().setMaster("local[*]" ).setAppName("spark" )
val sparkContext = new SparkContext(sparkConf)

val rdd1 = sparkContext.parallelize(
List (1,2,3,4)
)
val rdd2 = sparkContext.makeRDD(
List (1,2,3,4)
)
rdd1.collect().foreach(println )
rdd2.collect().foreach(println )

sparkContext.stop()

从底层代码实现来讲,makeRDD 方法其实就是 parallelize 方法

def makeRDD[T: ClassTag](

seq: Seq[T],

numSlices: Int = defaultParallelism): RDD[T] = withScope {

parallelize(seq, numSlices)

}

2. 从外部存储(文件)创建 RDD

由外部存储系统的数据集创建 RDD 包括:本地的文件系统,所有 Hadoop 支持的数据集, 比如 HDFS、HBase 等。

val fileRDD: RDD[String] = sparkContext.textFile("spark-core/input" )
fileRDD.collect().foreach(println )

3. 从其他 RDD 创建

主要是通过一个 RDD 运算完后,再产生新的 RDD。

4. 直接创建 RDD(new)

使用 new 的方式直接构造 RDD,一般由 Spark 框架自身使用。

RDD并行度与分区

默认情况下,Spark 可以将一个作业切分多个任务(Task)后,发送给 Executor 节点并行计算,而能够并行计算的任务数量我们称之为并行度。这个数量可以在构建 RDD 时指定。记住,这里的并行执行的任务数量,并不是指的切分任务的数量

val dataRDD: RDD[Int] =
sparkContext.makeRDD(
List (1,2,3,4),
4)
val fileRDD: RDD[String] =
sparkContext.textFile(
"spark-core/input" ,
2)
fileRDD.collect().foreach(println )

读取内存数据时,数据可以按照并行度的设定进行数据的分区操作,数据分区规则的

Spark 核心源码如下:

def positions(length: Long, numSlices: Int): Iterator[(Int, Int)] = {

(0 until numSlices).iterator.map { i =>

val start = ((i * length) / numSlices).toInt

val end = (((i + 1) * length) / numSlices).toInt

(start, end)

}

}

读取文件数据时,数据是按照 Hadoop 文件读取的规则进行切片分区,而切片规则和数据读取的规则有些差异,具体 Spark 核心源码如下

public InputSplit[] getSplits(JobConf job, int numSplits)

throws IOException {

long totalSize = 0; // compute total size

for (FileStatus file: files) { // check we have valid files

if (file.isDirectory()) {

throw new IOException("Not a file: "+ file.getPath());

}

totalSize += file.getLen();

}

long goalSize = totalSize / (numSplits == 0 ? 1 : numSplits);

long minSize = Math.max(job.getLong(org.apache.hadoop.mapreduce.lib.input.

FileInputFormat.SPLIT_MINSIZE, 1), minSplitSize);

...

for (FileStatus file: files) {

...

if (isSplitable(fs, path)) {

long blockSize = file.getBlockSize();

long splitSize = computeSplitSize(goalSize, minSize, blockSize);

...

}

protected long computeSplitSize(long goalSize, long minSize,

long blockSize) {

return Math.max(minSize, Math.min(goalSize, blockSize));

}

相关推荐
沉着的码农1 小时前
【设计模式】基于责任链模式的参数校验
java·spring boot·分布式
zskj_zhyl3 小时前
智慧养老丨从依赖式养老到自主式养老:如何重构晚年生活新范式
大数据·人工智能·物联网
哲科软件3 小时前
从“电话催维修“到“手机看进度“——售后服务系统开发如何重构客户体验
大数据·智能手机·重构
zzywxc7873 小时前
AI 正在深度重构软件开发的底层逻辑和全生命周期,从技术演进、流程重构和未来趋势三个维度进行系统性分析
java·大数据·开发语言·人工智能·spring
专注API从业者3 小时前
构建淘宝评论监控系统:API 接口开发与实时数据采集教程
大数据·前端·数据库·oracle
一瓣橙子5 小时前
缺少关键的 MapReduce 框架文件
大数据·mapreduce
永洪科技12 小时前
永洪科技荣获商业智能品牌影响力奖,全力打造”AI+决策”引擎
大数据·人工智能·科技·数据分析·数据可视化·bi
weixin_3077791312 小时前
Hive集群之间迁移的Linux Shell脚本
大数据·linux·hive·bash·迁移学习
ZHOU_WUYI13 小时前
一个简单的分布式追踪系统
分布式
上海锝秉工控15 小时前
防爆拉线位移传感器:工业安全的“隐形守护者”
大数据·人工智能·安全