一、Spark的基本介绍
Spark是一款用于大规模数据处理分布式的分析引擎
与MapReduce比较
MR: 是一款用于大规模数据处理分布式的分析引擎
MR存在的弊端:
1- 使用API相对比较低级: 大量的功能代码都需要程序员自己来实现
2- 计算效率慢: 大量的经过磁盘和内存之间的交互, 基于磁盘计算 IO比较大 (IO密集型框架)
3- 迭代计算非常不方便
什么是迭代计算:
在计算过程中, 需要将计算流程划分为N个阶段, 每个阶段之间互相依赖, 后一个阶段必须等待前一个阶段执行完成后, 然后才能执行下一个阶段
对于市场来说, 虽然说离线计算对实时性要求一般不是特别的搞, 但是依然希望能够计算的越快越好, 所以在这样的背景下, 迫切需求一款能够支持大规模的分布式计算的引擎, 同时能有非常高效的迭代计算的性能
Spark其实就是在这样的背景下, 逐步的产生了出来
Spark最早来源于加州大学伯克利分校一帮博士以及教授共同发布的一篇论文而产生的, 论文: 弹性分布式数据集
RDD: Spark的核心, 是Spark的一个数据结构, 在后续Spark Core中主要讲解的内容, 目前可以先理解为就是一个庞大的容器, 整个迭代计算操作, 都是基于这个容器来进行, 整个计算可以基于内存来进行迭代
RDD出现, 提供了会更加高效的计算平台, 同时也提供了更加高阶的API
Spark的开发语言: Scala(基于Java)
官方网站: https://www.spark.apache.org Apache旗下的顶级开源项目
为什么说Spark运行效率要优于MR?
1- Spark提供了全新的数据结构: RDD 支持在内存中进行计算, 部分迭代操作支持直接在内存中进行迭代处理
2- Spark程序是基于线程运行的, 而MR是基于进程来运行, 线程的启动和销毁是优于进程的
二、单词统计案例实现
代码如下(示例):
import os
from pyspark import SparkConf, SparkContext
os.environ['SPARK_HOME'] = '/export/server/spark'
os.environ['PYSPARK_PYTHON'] = '/root/anaconda3/bin/python3'
os.environ['PYSPARK_DRIVER_PYTHON'] = '/root/anaconda3/bin/python3'
if __name__ == '__main__':
print("pyspark的入门案例: wordcount")
# 1- 创建Spark Context核心对象(Spark Core 核心对象)
conf = SparkConf().setAppName("wordcount").setMaster("local[*]")
sc = SparkContext(conf = conf)
# 2- 执行相关的操作
# 2.1 读取外部文件数据
"""
spark路径写法: 协议 + 路径
本地路径协议: file:///
HDFS路径协议: hdfs://host:port/
注意: 此处的路径, 千万不能写windows的路径地址, 因为咱们连接的是远程环境, 所以这里的本地路径应该指的是远端的linux本地地址
"""
path ="file:///export/data/workspace/ky07_spark_parent/_01_spark_base/data/words.txt"
rdd_init = sc.textFile(name=path)
print(rdd_init.collect())
# 2.2 对每一行的数据执行切割操作: 一个内容 转换为 多个内容 (一 转 多)
rdd_flatMap = rdd_init.flatMap(lambda line: line.split(" "))
print(rdd_flatMap.collect())
# 2.3 将每一个单词 转换为(单词,1): 一个单词 转换为一个 kv的键值对(一对一)
rdd_map = rdd_flatMap.map(lambda word: (word,1))
print(rdd_map.collect())
# 2.4 根据 key进行分组聚合统计
"""
lambda agg, curr: agg + curr
参数1(agg) : 表示的局部聚合的结果
参数2(curr): 表示的每一次遍历的value的值
规则: agg + curr 表示 将每一次遍历的value值不断的累加到agg上
比如说:
(hive,1),(hive,1),(hive,1),(hive,1),(hive,1),(hive,1)
reduceByKey: 根据key进行分组, 将相同组的value数据合并
hive: [1,1,1,1,1,1]
接下来执行lambda函数:
agg 初始值为 value的列表中第一个 也就是 1
curr: 依次从第二个1 往后遍历即可
规则:
相当于: 新的agg = 原有agg + curr
当遍历完成, agg的值即为当前这个组的最终的结果了
"""
res = rdd_map.reduceByKey(lambda agg, sum: agg + sum)
print(res.collect())
print("-----------------------------")
top = res.top(5)
print(top)
# 3 释放资源
sc.stop()
三、Spark On Yarn 环境配置
将Spark程序运行在Yarn集群中, 由Yarn集群完成资源调度工作
3.1 修改spark配置文件
修改spark-env.sh
cd /**/spark/conf
/** 为spark的存放路径
vim spark-env.sh
添加以下内容:
HADOOP_CONF_DIR=/export/server/hadoop/etc/hadoop
YARN_CONF_DIR=/export/server/hadoop/etc/hadoop
SPARK_HISTORY_OPTS="-Dspark.history.fs.logDirectory=hdfs://node1:8020/sparklog/ -Dspark.history.fs.cleaner.enabled=true"
多节点安装spark需要同步到其他节点
修改 spark-defaults.conf
vim spark-defaults.conf
添加以下内容:
spark.eventLog.enabled true
spark.eventLog.dir hdfs://node1:8020/sparklog/
spark.eventLog.compress true
spark.yarn.historyServer.address node1:18080
spark.yarn.jars hdfs://node1:8020/spark/jars/*
修改hadoop的yarn-site.xml
cd /***/hadoop
,/*** :hadoop的安装路径
vim yarn-site.xml
<configuration>
<!-- 配置yarn主节点的位置 -->
<property>
<name>yarn.resourcemanager.hostname</name>
<value>node1</value>
</property>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<!-- 设置yarn集群的内存分配方案 -->
<property>
<name>yarn.nodemanager.resource.memory-mb</name>
<value>20480</value>
</property>
<property>
<name>yarn.scheduler.minimum-allocation-mb</name>
<value>2048</value>
</property>
<property>
<name>yarn.nodemanager.vmem-pmem-ratio</name>
<value>2.1</value>
</property>
<!-- 开启日志聚合功能 -->
<property>
<name>yarn.log-aggregation-enable</name>
<value>true</value>
</property>
<!-- 设置聚合日志在hdfs上的保存时间 -->
<property>
<name>yarn.log-aggregation.retain-seconds</name>
<value>604800</value>
</property>
<!-- 设置yarn历史服务器地址 -->
<property>
<name>yarn.log.server.url</name>
<value>http://node1:19888/jobhistory/logs</value>
</property>
<!-- 关闭yarn内存检查 -->
<property>
<name>yarn.nodemanager.pmem-check-enabled</name>
<value>false</value>
</property>
<property>
<name>yarn.nodemanager.vmem-check-enabled</name>
<value>false</value>
</property>
</configuration>
配置依赖spark jar包
[root@node1 ~]# hadoop fs -mkdir -p /spark/jars/
[root@node1 ~]# hadoop fs -put /export/server/spark/jars/* /spark/jars/
[root@node1 ~]# cd /export/server/spark/conf
[root@node1 conf]# scp -r spark-defaults.conf root@node2:$PWD
[root@node1 conf]# scp -r spark-defaults.conf root@node3:$PWD
启动相关服务
## 启动HDFS和YARN服务,在node1执行命令
[root@node1 ~]# start-dfs.sh
[root@node1 ~]# start-yarn.sh
或
[root@node1 ~]# start-all.sh
注意:在onyarn模式下不需要启动start-all.sh(jps查看一下看到worker和master)
## 启动MRHistoryServer服务,在node1执行命令
[root@node1 ~]# mr-jobhistory-daemon.sh start historyserver
## 启动Spark HistoryServer服务,,在node1执行命令
[root@node1 ~]# /export/server/spark/sbin/start-history-server.sh
测试
进入spark目录下的bin目录
[root@node1 bin]./spark-submit \
--master yarn \
--conf "spark.pyspark.driver.python=/root/anaconda3/bin/python3" \
--conf "spark.pyspark.python=/root/anaconda3/bin/python3" \
/export/data/workspace/ky07_spark_parent/_01_spark_base/src/_05_pyspark_wordcount.py
总结
通常spark都是运行在yarn集群上,在测试开发时会python连接远端的python环境进行开发。会避免出现python版本不兼容的问题。