👦👦一个帅气的boy,你可以叫我Love And Program
🖱 ⌨个人主页:Love And Program的个人主页
💖💖如果对你有帮助的话希望三连💨💨支持一下博主

CSDN话题挑战赛第2期
参赛话题:学习笔记

Spark基础理论知识

  • 前言
  • RDDS
  • shared variables(共享变量)
  • Hadoop
  • MapReduce
  • 缓存
  • Windows下Spark基础操作
  • 参考

前言

       Spark 的 shell 作为一个强大的交互式数据分析工具,提供了一个简单的方式来学习 API,这里我选择使用Scala 环境学习这部分内容。至于为什么不用Python呢?第一个原因:工作需要,第二个原因:我搜集了很多资料,我发现从Python入手spark确实也可以,甚至对我来说从Python学习更简单,但是Scala 本身也有它自己的优点,作为静态语言,他能帮你避免诸多低级错误,简单来说就是降低你运行时的报错的可能性,并且在大规模的代码中更占优势,最后学完Scala 后再学Python对应的模块也会更容易,本家都学会了,Python调用接口就相对更容易。
最后:对初学者来说建议从Python版本入手,但是对于已经学有所成的同学来说还是先学习Scala版本更加合适

RDDS

       Spark 最主要的抽象是叫Resilient Distributed Dataset(RDD) 的弹性分布式集合,本来我想把它理解为一个数组,但是发现并不可行,就像下面说的,对外只提供基本信息并隐藏它的细节,如果非要用一个比喻的话我更倾向于把它看作一个元组,它是在集群节点上的不可变的、已分区的集合对象!

数据抽象是一种依赖于接口和实现分离的编程(设计)技术,指对外只提供基本信息并且隐藏他们的背景细节,即只呈现程序中所需的信息而没有提供细节。

       RDD的actions,我们叫他动作算子,返回一个结果给驱动程序或将结果写入存储的操作,并开始一个计算(动作算子就像使用pandas中对应的函数一样,比如下面这个是不是和pandas.head()很像?)

#action示例
scala> textFile.first() // RDD 的第一行数据
res0: String = spark.RDD[String] = spark.MappedRDD@2ee9b6e3

       RDD 的 transformations(转换) 可以转换成一个新 RDD 并返回它的引用,如果用Python理解的话可以想象成执行某对象然后再return一个新的对象回来,下面这行代码是返回文本文档内包含的"Spark"的RDD结构

scala> val lines = textFile.filter(line => line.contains("Spark"))
lines: org.apache.spark.rdd. 8 RDD[String] = MapPartitionsRDD[2] at filter at <console>:23
  • 一个RDD共分为五大特性
    1. A list of partitions
      • 一个列表的分区,需要哪些切分哪些,啧,很直白的翻译,给它美化一下,一揽子分区,哪里需要哪里切🉑🉑👉注意,Spark是分布式运算框架,所以一台机器中有很多分区非常合理,一个分区放在一台机器的内存上,每个分区分布在集群中的不同节点上
    2. A function for computing each split
      • 一个函数作用于一个分区中,我更喜欢这位博主解释的,更具有威严性
    3. A list of dependencies on other RDDs
      • 不同 RDDs 之间的依赖关系,具体依赖关系可分为宽依赖和窄依赖(有点复杂,这里功力有限,不详细展开,只介绍其作用),通过Lineage方式我们可以恢复丢失的数据 通过检查点的方式恢复丢失数据(具体内容),这两者都用到它们之间的依赖关系,保证了容错性。
    4. Optionally, a Partitioner for Key-value RDDs
      • 可选项,以键值对存储数据的弹性分布式数据集的分区程序,比如:HashPartitionerRangePartitioner,都是以key-value键值对这种形式存储的,他们都具备 Partitioner属性来决定 RDD 如何分区
    5. Optionally, a list of preferred locations to compute each split on
      • 可选项,每个分区都有一个优先位置的列表,具有本地性,其意思是 Spark在运行前就已经知道任务会发生在哪个节点,索引在进行任务调度时会尽可能地将任务分配到处理数据的数据块所在的具体位置 即最优的位置去计算,比如 Hadoop分布式文件系统(HDFS)block的所在位置就是优先计算的位置
      • HDFS 指被设计成适合运行在通用硬件上的分布式文件系统。那么HDFS的block是什么呢?👉👉一般情况下,任何磁盘都有‘最小读写单位’的概念,可以理解为该磁盘的blockHDFS与普通的管理单个磁盘的文件系统一样,也将文件分割成block,每个block都作为一个独立的单元分别保存的,默认为128MB,不过与之不同的是,在HDFS中,小于block的文件不会占用一个block的空间。(比如,文件大小为1MB,那么它会占用一个HDFS的block,但是只使用底层磁盘1MB的空间,而不是128MB。)
      • 本地性如何解释?👉👉通过其对应属性preferredLocations 可知,其记录了数据的位置,给任务调度提供依据,但是最理想的情况下在原地对数据进行计算,也就是在本地机中而不是通过网络节点,因为网络延迟要远大于计算延迟,这也就解释了数据本地性就是在本机数据所在的节点完成计算,这也就对应了上面Spark会尽可能地将任务分配到处理数据的数据块所在的具体位置(体现了数据的本地性),所以我理解为在本地就快呗

我观察完RDD的五大特点我会发现他浑身上下都在透露着:我很快,不仅仅是并行运算,从各个方面都透露着 “ 我不仅性能牛X,还能恢复数据,学我没错!”的感觉🤣

shared variables(共享变量)

       Spark 的第二个抽象是共享变量,共享一词占据相当的份量,共享变量可以在并行运算被计算,(默认情况下)Spark 运行一个并行函数时,这个并行函数会作为一个任务集在不同的节点上运行,它会把函数里使用的每个变量都复制搬运到每个任务中,具体如图所示:

       Spark提供两种类型共享变量:仅仅只能执行**“添加(added)”操作**,例如:记数器(counters)和求和(sums)

  1. 广播变量(broadcast variables),用来在所有节点的内存中缓存一个值;
  2. 累加器(accumulators)
    (详解见:Spark----Shared Variables(共享变量))

Hadoop

       Hadoop是一个由Apache*基金会所开发的分布式系统基础架构,由Spark在下载时就必须同时下载Hadoop可以见得:Spark在很多时候都会用上Hadoop**,但是并非必不可少,因为其存在一个独立部署模式,它的意义在于可以大大提升效率。(Spark——需要HADOOP来运行SPARK吗?)

  • Spark是由scala语言编写的计算框架,基于内存的快速、通用、可扩展的大数据分析引擎,可以快速处理MapReduce
  • Hadoop是开发的分布式系统基础架构,实现了一个分布式文件系统,其框架最核心的设计就是:HDFS(提供高吞吐量来访问应用程序的数据)和MapReduce(为数据提供计算)

MapReduce

  • MapReduce是一种编程模型,用于大规模数据集(大于1TB)的并行运算,而且,MapReduce是面向大数据并行处理的计算模型、框架和平台,隐含了下面三层意思:
    1. MapReduce是一个基于集群的高性能并行计算平台,这一点毋庸置疑,而且很多科技公司的都在使用
    2. MapReduce是一个并行计算与运行软件框架,因为其本身最早被Google提出的时候本身的目的就是为了解决其搜索引擎中大规模网页数据的并行化处理,这个思想被后续开源模仿实现也就Hadoop
    3. MapReduce是一个并行程序设计模型与方法,MapReduce的灵感来源于函数式语言(比如Lisp)中的内置函数map和reduce用Map(可以高度并行)和Reduce(理解为一个快速有效的化简函数)两个函数编程实现基本的并行计算任务,提供了抽象的操作和并行编程接口,以简单方便地完成大规模数据的编程和计算处理

LISP是一种通用高级计算机程序语言,长期以来垄断人工智能领域的应用。LISP作为应用人工智能而设计的语言,是第一个声明式系内函数式程序设计语言,有别于命令式系内过程式的C、Fortran和面向对象的Java、C#等结构化程序设计语言。(第二古老的语言,这也是我第一次听说)

具体执行步骤:

缓存

        缓存大家应该很熟悉,没错,跟打开网页保留缓存是一个意思,即数据交换的缓冲区,Spark 支持把数据集拉到集群内的内存缓存中,在进行重复访问操作的时候缓存显得尤为重要,想想几千万条数据时不加缓存进行重复访问…这简直是一场灾难,缓存很好的提升了运行的效率,缓存操作也非常简单👇👇

# 就算直接缓存好了
scala> 变量.cache()

Windows下Spark基础操作

       在Win下操作需要在进入spark-shell前进入对应文件夹,否则会报错,比如在执行读取文档时,我们文档存储在D:/Scala/text中,但是我们读取时在D:\Scala文件夹下进入,就会发生无法找到文件的报错:

D:\Scala>spark-shell
val textFile = sc.textFile("README.md")
#可以正常读取
textFile: org.apache.spark.rdd.RDD[String] = README.md MapPartitionsRDD[1] at textFile at <console>:23
#但是当你对它进行操作时会报错
textFile.count()
org.apache.hadoop.mapred.InvalidInputException: Input path does not exist: file:/D:/Scala/README.md
.
.
.
Caused by: java.io.IOException: Input path does not exist: file:/D:/Scala/README.md
  at org.apache.hadoop.mapred.FileInputFormat.singleThreadedListStatus(FileInputFormat.java:278)

spark的理论知识已经基本讲解清晰,后续还有其他知识会继续更改,本文仅以自己理解写的,如有不对请各位批评指正

参考

  • HDFS 概念之 block 详解
  • RDD:五大特性
  • 如何理解Spark的数据本地性
  • MapReduce百度百科

更多推荐

学习Spark需要掌握的全部基础理论知识(穿插部分代码)——从Python角度看Spark