MapReduce过程复习
Spark由五部分组成
RDD五大特征
1、 Spark -- 代替MapReduce <<<<< scala是单机的,spark是分布式的。>>>>>
开源的分布式计算引擎
可以快速做计算 -- 因为可以利用内存来做一些计算
(1) 分为5个库(模块) :
1、 Spark SQL
2、 Spark Streaming -- 流处理
3、 MLlib(maching learning) -- 机器学习
4、 GraphX(graph) -- 图计算(人际关系图、网络关系图)
5、 Spark Core -- 核心 类似MapReduce
-- 5是核心, 1、2、3、4都是基于5做的封装。
(2) 为什么说spark比hadoop快?(但spark不稳定)
1、hadoop是基于磁盘做迭代的
spark是将数据放在内存中做迭代的
2、对同一份数据进行多次查询时,hadoop每次都会去磁盘读取数据
而spark会先将数据放在内存里面,然后再基于内存做查询
使用内存也会有问题 :
1、 成本变高
2、 数据量太大,可能会内存溢出 (内存溢出 : 先出现GC 、 再出现 oom)
3、 闪存,怕断电
(3) 运行的 4 种模式 :
1、 Local -- 本地 多用于测试
2、 Standalone -- 独立集群
3、 Mesos -- 资源管理框架 和yarn同一种东西,但更多的是使用yarn
4、 YARN -- 资源管理框架 使用最多
2、 新建 Spark 的 maven项目 :
(1) 在pom文件中 导入3个org.scala-lang依赖, 再导入Java Compiler - Java 编译的插件、 Scala Compiler - Scala 编译的插件,
最后导入Spark核心插件 : spark core
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.11</artifactId>
<version>2.4.5</version>
</dependency>
(2) 创建Spark环境
// 1、 创建配置对象
val conf = new SparkConf()
// 2、 设置任务名
conf.setAppName("wordCount")
// 3、 指定spark代码运行方式 --- local : 本地测试
conf.setMaster("local")
// 4、 spark 上下文对象 --- 用于读取数据
val sc = new SparkContext(conf)
(3) 大数据处理引擎步骤 :
1、读取数据
2、处理数据
3、保存结果
(4) RDD: 弹性的分布式数据集
暂时可以将rdd当成scala中的list使用
如果是提交到集群运行,会自动切换为读取hdfs数据
// 1、读取数据
val linesRDD: RDD[String] = sc.textFile("data/words.txt")
运行时出现报错 : Could not locate executable null\bin\winutils.exe in the Hadoop binaries.
解决方法 :
1、将hadoop-3.1.0安装包解压到电脑C:\soft\hadoop目录
2、将winutils.exe工具粘贴到hadoop-3.1.0\bin目录
3、配置环境变量 :
3.1、 新建 HADOOP_HOME 值: C:\soft\hadoop\hadoop-3.1.0
3.2、 点击path -> 编辑 -> 新建%HADOOP_HOME%\bin
3.3、 一路确认
4、重启IDEA
3、 RDD的五大特性 :
RDD : 弹性的分布式数据集
RDD里面默认是没有数据的,处理数据时边读数据边处理,是一个持续的过程。
如果对同一份数据做多次查询,需要将数据缓存到内存,RDD就有数据了。
RDD是在编写代码时的一个抽象的概念, 类似搭建了一个管道,数据会流经RDD。
RDD的引入是为了更方便的写代码。
spark没有自己的切片规则,使用的是MapReduce的切片规则
RDD五大特性 :
(1) RDD由一组分区(切片)组成 -- 默认一个block块对应一个分区(partition), 分区越多计算的并行度越高
(2) 算子(方法)是作用在每一个分区上的 -- 即每一个分区(切片)对应一个task
(3) RDD之间有一系列的依赖关系 -- 有shuffle : 宽依赖 无shuffle : 窄依赖
在宽依赖的地方切一刀,前面被称为一个阶段或一个stage,后面也被称为一个阶段; 或者称前面为map端,后面为reduce端
(4) 分区类的算子只能作用于KV格式的RDD上 -- 如 groupBykey、reduceBykey、sortBykey、join
(5) spark为task提供了最佳的计算位置 -- spark会尽量将task发送到数据所在的节点执行(移动计算而不是移动数据)
读取速度: 从内存中 > 从磁盘中 > 从网络中
所以Spark尽量将task发送到数据所在的节点执行,避免网络拉取数据,提高效率。
spark运行程序 先将整体的RDD搭建起来,再一起执行。而不是一步一步的执行。
4、 RDD 分区(切片)
分区决定因素 :
(1) 读取hdfs数据
-
默认一个block块对应一个分区,切片规则和MR一样。
-
设置最小分区数据(minPartitions), RDD的分区数会大于等于(>=)这个值, 具体多少分区需要通过计算得到
计算原则是保证每一个切片的数据量是差不多的
(2) 窄依赖算子 -- RDD一对一
-
没有shuffle, 返回的新的RDD的分区数等于前一个RDD的分区数, 不可以修改
-
如 map、 filter、 flatmap、 mappartition
(3) 宽依赖算子 -- RDD一对多 (会在宽依赖切一刀)
-
会产生shuffle, 默认也是等于前一个RDD的分区数。 所有的宽依赖算子都可以手动设置分区数
-
通过参数 (numPartitions) 修改
一般来说保证每一个分区类的数据量在128M左右是比较合适的
默认不会修改分区数, 除非资源无限的情况下, 分区越多, 执行的并发越高, 效率越高
一个分区就是一个并行度(task), 分区越多并行度越高。
设置一个死循环,运行代码时点击出现的网址 : http://XiaoWang:4040
或者直接在浏览器输入 : localhost:4040
(1) 可以看见 Job Id -- 一个job就是一个spark任务
Tasks 显示 8个 -- 6 + 2
(2) 点击Description下的带颜色的部分, 进入可以看到Stage Id 分为两个部分, 分别是0 -- map阶段、1 -- reduce阶段
5、 RDD 缓存
RDD里面默认是没有数据的,如果对同一份数据做多次查询,需要将数据缓存到内存,RDD就有数据了。
即对同一个RDD进行多次使用的时候,可以将这个RDD缓存起来,减少重复计算,提高效率。
第一次需要从HDFS中读取数据,后续任务再使用这个RDD时可以直接从缓存中获取数据。
当数据量太大时,不适合使用缓存
格式 :
stuRDD.cache() -- 直接在这个RDD后面加上
缓存级别 :
(1) MEMORY_ONLY (默认) -- 数据量不大, 内存充足
(2) MEMORY_AND_DISK_SER -- 数据量较大, 内存不能完全放下数据 。 一般适用于RDD前的计算逻辑很长的时候。
因为不管压缩与否,放内存都比放磁盘快,所以尽量将数据放在内存中。
// 默认的缓存级别是 MEMORY_ONLY
stuRDD.cache()
//可以手动设置缓存级别为 MEMORY_AND_DISK_SER
stuRDD.persist(StorageLevel.MEMORY_AND_DISK_SER)