统一配置环境:
zk:3.4.9
jdk:1.8
IDEA:2019.1.x64
Spark概述
spark主要用在计算机集群上进行并行数据处理
集群搭建
(1)下载spark安装包
# 下载 Spark
cd /export/softwares
wget https://archive.apache.org/dist/spark/spark-2.2.0/spark-2.2.0-bin-hadoop2.7.tgz
(2)上传并解压
使用ssh工具上传安装包到/export/softwore
tar -zxvf
(3)配置spark-env.sh
//拷贝配置文件模板,在对模板进行修改
cp spark-env.sh.templat spark-env.sh
使用Notepad++连接node01进行修改配置文件
# 指定 Java Home
export JAVA_HOME=/export/servers/jdk1.8.0
# 指定 Spark Master 地址
export SPARK_MASTER_HOST=node01
export SPARK_MASTER_PORT=7077
(5)修改slaves
1.使用场景环境
- 修改配置文件 slaves, 的ip映射可以实现从在使用 sbin/start-all.sh 启动集群的时候, 可以一键启动整个配置映射的集群,的所有的 Worker
2.配置流程
进入配置目录, 并复制一份新的配置文件, 以供在此基础之上使用Notepad++连接node01进行修改
//拷贝配置文件模板,在对模板进行修改
cp slaver.templat slaver
//配置从节点地址
node01
node02
node03
(4)配置HistoryServe
1.使用场景
默认情况下, Spark 程序运行完毕后, 就无法再查看运行记录的 Web UI 了, 通过 HistoryServer 可以提供一个服务, 通过读取日志文件, 使得我们可以在程序运行结束后, 依然能够查看运行过程
2.配置流程
- 进入配置目录, 并复制一份新的配置文件, 以供在此基础之上使用Notepad++连接node01进行修改
cp spark-defaults.conf.template spark-defaults.conf
- 将以下内容复制到
spark-defaults.conf
末尾处, 通过这段配置, 可以指定 Spark 将日志输入到 HDFS 中
spark.eventLog.enabled true
spark.eventLog.dir hdfs://node01:8020/spark_log
spark.eventLog.compress true
将以下内容复制到spark-env.sh
的末尾, 配置 HistoryServer 启动参数, 使得 HistoryServer 在启动的时候读取 HDFS 中写入的 Spark 日志
# 指定 Spark History 运行参数
export SPARK_HISTORY_OPTS="-Dspark.history.ui.port=4000 -Dspark.history.retainedApplications=3 -Dspark.history.fs.logDirectory=hdfs://node01:8020/spark_log"
为 Spark 创建 HDFS 中的日志目录
hdfs dfs -mkdir -p /spark_log
(5)分发
将 Spark 安装包分发给集群中其它机器
cd /export/servers
scp -r spark root@node02:$PWD
scp -r spark root@node03:$PWD
启动 Spark Master 和 Slaves, 以及 HistoryServer
cd /export/servers/spark
sbin/start-all.sh
sbin/start-history-server.sh
(6)高可用配置
1.使用场景
对于 Master 来说, 是会出现单点失败的, 为了避免可能出现的单点失败问题
解决办法:
- 使用 Zookeeper 实现 Masters 的主备切换
2.实现流程
- 停止spark集群
cd /export/servers/spark
sbin/stop-all.sh
- 修改配置文件,指定zookeeper位置
- 编辑 spark-env.sh, 添加 Spark 启动参数, 并去掉 SPARK_MASTER_HOST 地址
# 指定 Java Home
export JAVA_HOME=/export/servers/jdk1.8.0_141
# 指定 Spark Master 地址
# export SPARK_MASTER_HOST=node01
export SPARK_MASTER_PORT=7077
# 指定 Spark History 运行参数
export SPARK_HISTORY_OPTS="-Dspark.history.ui.port=4000 -Dspark.history.retainedApplications=3 -Dspark.history.fs.logDirectory=hdfs://node01:8020/spark_log"
# 指定 Spark 运行时参数
export SPARK_DAEMON_JAVA_OPTS="-Dspark.deploy.recoveryMode=ZOOKEEPER -Dspark.deploy.zookeeper.url=node01:2181,node02:2181,node03:2181 -Dspark.deploy.zookeeper.dir=/spark"
3.分发配置到整个集群
cd /export/servers/spark/conf
scp spark-env.sh node02:$PWD
scp spark-env.sh node03:$PWD
4.启动
- 在 node01 上启动整个集群
cd /export/servers/spark
sbin/start-all.sh
sbin/start-history-server.sh
- 在 node02 上单独再启动一个 Master
cd /export/servers/spark
sbin/start-master.sh
Service | port |
---|---|
Master WebUI | node01:8080 |
Worker WebUI | node01:8081 |
History Server | node01:4000 |
(7)配置spark环境
1.修改配置文件
vim /etc/profile
export SPARK_BIN=/export/servers/spark/bin
export PATH=$PATH:$SPARK_BIN //将SPARK_BIN目录添加到PATH的查找路径中
2.使得配置生效
source /etc/profile
spark shell
1.使用场景
- 数据集的探索
- 测试
2.读取本地文件
(1)准备文件
在 Node01 中创建文件 /export/data/wordcount.txt
//文件内容
hadoop spark flume
spark hadoop
flume hadoop
(2)启动 Spark shell
cd /export/servers/spark
bin/spark-shell --master local[2]
Master地址可用有以下几种设置方式
地址 | 解释 |
---|---|
local[N] | 使用 N 条 Worker 线程在本地运行 |
spark://host:port | 在 Spark standalone 中运行, 指定 Spark 集群的 Master 地址, 端口默认为 7077 |
mesos://host:port | 在 Apache Mesos 中运行, 指定 Mesos 的地址 |
yarn | 在 Yarn 中运行, Yarn 的地址由环境变量 HADOOP_CONF_DIR 来指定 |
读取本地文件进行词频统计流程
- 读取文件
val rdd1 = sc.textFile("file:///export/data/wordcount.txt")
- 拆分文件
val rdd2 = rdd1.flatMap(item => item.split(" "))
- 给与每个单词的词频为1
val rdd3 = rdd2.map(word => word -> 1)
- 安装单词进行词频聚合
val rdd4 = rdd3.reduceByKey((curr,agg) => curr+agg)
rdd4.collect()
2.读取HDFS文件进行词频统计
(1)上传文件到 HDFS 中
cd /export/data
hdfs dfs -mkdir /dataset
hdfs dfs -put wordcount.txt /dataset/
(2)在 Spark shell 中访问 HDFS
val sourceRdd = sc.textFile("hdfs://node01:8020/dataset/wordcount.txt")
val flattenCountRdd = sourceRdd.flatMap(_.split(" ")).map((_, 1))
val aggCountRdd = flattenCountRdd.reduceByKey(_ + _)
val result = aggCountRdd.collect
spark 采用IDEA编写WordCount案例
1.创建maven
<properties>
<scala.version>2.11.8</scala.version>
<spark.version>2.2.0</spark.version>
<slf4j.version>1.7.16</slf4j.version>
<log4j.version>1.2.17</log4j.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>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.6.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<sourceDirectory>src/main/scala</sourceDirectory>
<testSourceDirectory>src/test/scala</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<version>3.2.0</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>3.1.1</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>
在main和text下分别创建scala的目录.在目录被编写scala代码
2.wordcount实现并本地运行
package cn.ityuge.spark.rdd
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
object WordCount {
def main(args: Array[String]): Unit = {
//1,创建sparkContext
val conf = new SparkConf().setMaster("local[6]").setAppName("word_count")
val sc = new SparkContext(conf)
//2.加载文件
//2.1准备文件
//2.2读取文件
val rdd1: RDD[String] = sc.textFile("./data/wordcount.txt")
//3.处理
//3.1把整句话拆分为多个单词
val rdd2: RDD[String] = rdd1.flatMap(x=>x.split(" "))
//3.2把每个单词指定词频1
val rdd3: RDD[(String, Int)] = rdd2.map(x=>(x,1))
println(rdd3)
//3.3聚合操作
val rdd4 = rdd3.reduceByKey((curr,agg)=>curr+agg) //curr当前值,agg局部结果
//4.获得结果
val result = rdd4.collect()
result.foreach(item => println(item))
}
}
3.提交到集群运行
先把idea编写的代码通过maven插件打成jar包通过ssh传输到node01节点上
spark-submit --master spark://node01:7077 \
--class cn.itcast.spark.WordCounts \
original-spark-0.1.0.jar
RDD编程模型
spark并行计算(RDD)的五个特性
-
有一个分片列表.只有当数据可以进行切分,分发到每台计算节点上才可以实现并行计算
-
有一个函数计算每一个分片
-
key-value型的RDD是根据哈希来分区的,类型于mapreduce当中的Paritioner接口,控制key分到哪个reduce
RRD代码
1.程序入口
程序入口一个方法叫SparkContext(conf), conf是一个配置用SparkConf()方法来进行设置
2.mapflat算子
先是使用map令一个字符串变为以指定方式进行分割,生成一个数组,在通过flat打开数组得到每一个元素
2.reduceByKey
curr 是获取的一个k对应的值,agg的一个累加的结果,来一个Hello,获取到值为1和agg相加,就更新了agg的值从0到1了
在来一个Hello,获取其值为1,和agg相加,就是从1到2.