Spark学习

一 spark设计与运行原理

1 Spark简介

Spark是由美国加州大学伯克利分校AMP实验室于2009年开发,是基于内存计算的大数据并行框架,可用于构建大型的、低延时的数据分析应用程序。2013年成为Apache下的开源项目。Apache Spark是一种快速通用的集群计算系统。它提供Java,Scala,Python和R中的高级API,以及支持通用执行图的优化引擎。它还支持一组丰富的更高级别的工具,包括Spark SQL用于SQL和结构化数据的处理,MLlib机器学习,GraphX用于图形处理和Spark Streaming。

2 Spark特点

  • 运行速度快:Spark主要使用先进的有向无环图DAG执行引擎,以支持循环数据流和内存计算,基于内存的执行速度比Hadoop MapReduce快上百倍,基于磁盘的执行速度也能快十倍。
  • 容易使用:Spark支持Scala、Java、R和Python等语言,简洁的API设计有助于用户轻松构建并行程序,并且可以通过Spark Shell进行交互式编程。
  • 通用性:Spark提供了完整而强大的技术栈,包括SQL查询、流式计算、机器学习和图算法等组件,这些组件可以无缝整合在同一个应用中,足以应对复杂的计算。
  • 运行模式多样:Spark可以运行在独立的集群模式中,也可以运行于Hadoop上,并且可以访问HDFS、HBase、Cassandra和Hive等数据源。

3 Spark生态

大数据处理类型

  • 复杂的批量数据处理:时间跨度通常在数十分钟到数小时之间(Hadoop MapReduce);
  • 基于历史数据的交互式查询:时间跨度通常在数十秒到数分钟之间(Impala,Hive);
  • 基于实时数据流的数据处理:时间跨度通常在数百毫秒到数秒之间(Storm,Spark stream)。

大数据框架存在的一些问题

  • 不同软件产生的数据格式不一样,因此无法做到数据无缝连接,需要进行格式转换;
  • 不同软件需要有不同的开发人员和维护人员,成本比较高;
  • 难以对同一个集群中各个系统进行统一资源调配。

Spark的设计遵循了“一个软件栈满足不同应用场景”的理念,逐渐形成了一套完整的既能提供内存计算框架,也可以支持SQL即席查询、实时流式计算、机器学习和图计算。Spark可以部署在Yarn之上,同时支持批处理、交互式查询和流数据处理。

Spark已经成为伯克利数据分析软件栈BDAS的重要组成部分。

                               图1 BDAS架构

Spark组件包含Spark Core、Spark SQL、Spark Streaming、MLlib和GraphX等。其功能具体如下:

  • Spark Core:它包含Spark最基础和最核心的功能,如内存计算、任务调度、部署模式和故障恢复、存储管理等,主要面向批数据处理。Spark Core建立在统一的抽象RDD之上,使其可以以一致的方式应对不同的大数据处理场景;需要注意的是,Spark Core通常被简称为Spark。
  • Spark SQL:Spark SQL是用于结构化数据处理的组件,允许开发人员直接处理RDD,同时也可查询Hive、Hbase等外部数据源。Spark SQL的一个重要特点是其能够统一处理关系表和RDD,使得开发人员不需要自己编写Spark应用程序,开发人员可以轻松地使用SQL命令进行查询,并进行复杂的数据分析。
  • Spark Streaming:Spark Streaming是一种流计算框架,可以支持高吞吐量,可容错处理的实时流数据处理,其核心思路就是将流数据分解成一系列短小的批处理作业,每个短小的批处理作业可以使用Spark Core进行快速处理。Spark Streaming支持多种数据输入源,如Kafka、Flume和Tcp套接字等。
  • MLlib(机器学习):MLlib提供了常用机器学习算法的实现,包括聚类、分类、回归、协同过滤等,降低了机器学习的门槛,开发人员只要具备一定的理论知识就能进行机器学习方面的工作。
  • GraphX(图计算):GraphX是Spark中用于图计算的API,可以认为是Pregel在Spark上的重写和优化,GraphX性能良好,拥有丰富的功能和运算符,能在海量数据上自如的运行复杂的图算法。

二 Spark的安装与运行

2 运行实例

Spark附带了几个示例程序。Scala,Java,Python和R示例都在 examples/src/main目录中。要运行其中一个Java或Scala示例程序,请 bin/run-example [params]在顶级Spark目录中使用。(在幕后,这将调用用于启动应用程序的更通用的 spark-submit脚本)。例如,


./bin/run-example SparkPi 10


您还可以通过Scala shell的修改版本以交互方式运行Spark。这是学习框架的好方法:


./bin/spark-shell --master local[2]


该–master选项指定分布式集群的URL,或者local使用一个线程local[N]在本地运行,或者使用N个线程在本地运行。您应该从使用local测试开始 。有关选项的完整列表,请使用该–help选项运行Spark shell 。


./bin/spark-shell --master spark://hostname:7077


–master参数指master-url,它表明的Spark的运行模式,值可以为如下所示:


local 使用一个Worker线程本地化运行Spark
local[*] 使用与逻辑CPU个数相同数量的线程来本地化运行Spark(逻辑Cpu个数等于物理Cpu个数乘以每个物理Cpu包含的核心数)
local[K] 使用K个Worker线程来本地化运行Spark(理想情况下,K应该根据运行机器的Cpu核心数来确定)
spark://host:port Spark采用独立集群模式,连接到指定的Spark集群,默认端口是7077
yarn-client Spark采用Yarn集群模式,以客户端模式连接Yarn集群,集群的位置可以再HADOOP_CONF_DIR环境变量中找到;当用户提交了作业后,不能关掉Client,Driver Program驻留在Client
< yarn-cluster Spark采用Yarn集群模式,以集群模式连接Yarn集群,集群的位置可以再HADOOP_CONF_DIR环境变量中找到;当用户提交了作业后,就可以关掉Client,作业会继续在Yarn上运行,该模式不适合运行交互类型的作业,常用于企业生产环境
< mesos://host:port Spark采用Mesos集群模式,连接到指定的Mesos集群,默认端口是5050


Spark的运行模式


local 单机模式,常用于本地开发\


Standalone模式:Spark自带的资源调度管理服务


Mesos模式:Mesos是另一种资源调度管理框架,可以为运行在它上面的Spark提供服务。


Yarn模式:yarn是Hadoop中用于资源调度管理的框架,它也可以为Spark提供资源调度服务。


Spark的交互式操作入门

基本操作

Scala版本
./bin/spark-shell 进入spark的交互界面
 1 val textFile = spark.read.textFile("D:/hadoop/spark/hello.txt") //读取DataSet数据集
 2 textFile.count() //返回数据集的元素数
 3 textFile.first() //返回数据集中第一个元素
 4 val linesWithSpark = textFile.filter(line => line.contains("Spark")) //使用过滤器选取满足要求的元素
 

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Python版本
./bin/pyspark 进入spark的交互界面
1 textFile = spark.read.text("D:/hadoop/spark/hello.txt") //读取数据集
2 textFile.count()  //返回数据集的元素数
3 textFile.first() //返回第一个元素
4 textFile.filter(textFile.value.contains("Spark")).count()  // How many lines contain "Spark"?

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二 RDD的设计与原理

1 RDD编程基础

1.1 创建RDD

textFile函数
spark通过textFile函数从文件系统加载数据到内存并创建RDD,该方法把文件的URI作为参数,这个参数可以是本地文件系统或分布式文件系统,从文件中读取到的每一行内容都成为RDD中的一个元素。
val lines = sc.textFile(“D:/out.txt”)
输出 lines: org.apache.spark.rdd.RDD[String] = D:/out.txt MapPartitionsRDD[1] at textFile at :24

parallelize函数
通过并行集合数组创建RDD
var array = Array(1,2,3,4,5)
输出array: Array[Int] = Array(1, 2, 3, 4, 5)
var rdd = sc.parallelize(array)
输出rdd: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[8] at parallelize at :26\

1.2 RDD操作

RDD的操作包括转换和行动操作
(1)转换操作
每一次转换都会生成不同的RDD,供给下一个操作使用,RDD的转换是惰性的,在转换过程中不会发生计算,只有当行动开始时,才会发生真正的计算。
常用的RDD转换API
操作 含义


filter(func) 筛选出满足函数func的元素,并返回一个新的数据集


map(func) 将每个元素传递到func中,并将结果返回成一个新的数据集


flatMap(func) 与map()相似,但每个输入元素都可以映射到0到多个输出结果


groupByKey() 应用于(K,V)键值对的数据集时,返回一个新的(K,Iterable)形式的数据集


reduceByKey(func) 应用于(K,V)键值对的数据集时,返回一个新的(K,V)形式的数据集,其中每个值是将每个key传递到函数func中进行聚合后的结果

filter函数
var file = sc.textFile(“D:/hadoop/spark/hello.txt”)
输出file: org.apache.spark.rdd.RDD[String] = D:/hadoop/spark/hello.txt MapPartitionsRDD[13] at textFile at :24
var rdd = file.filter(line=>line.contains(“spark”))
输出rdd: org.apache.spark.rdd.RDD[String] = MapPartitionsRDD[14] at filter at :25
rdd.foreach(println)
输出
spark
spark1
jhelewrwespark\

map函数
var file = sc.textFile(“D:/hadoop/spark/hello.txt”)
输出file: org.apache.spark.rdd.RDD[String] = D:/hadoop/spark/hello.txt MapPartitionsRDD[13] at textFile at :24
var rdd2 = file.map(line=>line+“123”)
输出rdd2: org.apache.spark.rdd.RDD[String] = MapPartitionsRDD[15] at map at :25
rdd2.foreach(println)
输出
sfuhfd sf123
sdfsiows123
spark1123
soar123
…\

但是file.map(line=>line.split(" “))中,line.split(” ")每行筛选出的元素会形成Array对象\

flatMap函数
flatMap函数经过----->map过程形成Array对象-------->flat过程将每个Array中的元素转换成RDD中的元素\

groupByKey函数
groupByKey函数应用于(K,v)键值对的数据集
如数据集
(“hadoop”,1),(“is”,1),(“hadoop”,1),(“is”,1)
生成的rdd数据
(“hadoop”,(1,1)),(“is”,(1,1))\

reduceByKey函数
它也是应用于(K,V)形式的数据集,并返回(K,V)形式的数据集。
reduceByKey((a,b)=>a+b)
原始数据(“hadoop”,1),(“is”,1),(“hadoop”,1),(“is”,1)—>归并为(“hadoop”,(1,1)),(“is”,(1,1))—>通过(a,b)=>a+b筛选形成新数据集(“hadoop”,2),(“is”,2)

1.3行动操作

行动操作是真正发生计算的地方。
常用的行动操作API\


count() 返回数据集中的元素个数


collect() 以数组的形式返回数据集中的所有元素


first() 返回数据集中的第一个元素


take(n) 以数组的方式返回数据集中的前n个元素


reduce(func) 通过函数func(输入两个参数)


foreach(func) 将数据集中的每个元素传递给func

1.4持久化

在spark中,RDD采用惰性求值的机制,每次遇到行动操作都会从头开始执行计算。每次调用行动操作,都会触发一次从头开始的计算,这对于迭代计算代价是很大的,因为迭代计算经常会多次重复使用同一组数据。解决方法就是通过持久化来避免重复计算的开销。


具体方法就是使用persist()方法,对RDD标记为持久化,出现persist()的地方,并不会马上计算生成RDD并把它持久化,而是要等到第一个行动操作触发真正计算以后,才会把计算结果持久化,持久化后的RDD会被保留在计算节点的内存中,被后续的行动操作重复使用。


persist持久化级别
persist(MEMORY_ONLY):表示将RDD作为反序列化的对象存储于JVM中,如果内存不足,就要按照LRU原则替换缓存中的内容。
persist(MEMORY_AND_DISK):表示将RDD作为反序列化的对象存储在JVM中,如果内存不足,超出的分区将会被存放在磁盘上>
一般使用cache()方法时,会调用persist(MEMORY_ONLY)方法。


1.5分区

分区的作用
RDD是弹性分布式数据集,通常RDD很大,会被分成很多个分区,分别保存在不同的节点上。对RDD进行分区,目的是增加并行度,让计算向数据靠拢,减少了网络开销。\


分区原则


RDD分区的一个原则就是使分区的个数尽量等于集群中的CPU核心数目。对于不同的Spark部署模式,都可以设置分区数目spark.default.parallelism这个参数的值,来配置默认的分区数。


Spark部署模式
Local模式:默认为本地机器的CPU数目,若设置了local[N],则默认为N;
Standalone或YARN模式:在集群中所有CPU核心数目总和和2取较大者为默认值;
Mesos模式:默认分区数为8\


手动设置分区数目
sc.textFile(url,partitionNum)
sc.parallelize(url,partitionNum) 这个函数若没有指定分区数时,会采用min(default,2)的算法设置分区
使用repartition()方法重新设置分区个数
data.repartition(partitionNum)


自定义分区方法
Spark提供了自带的哈希分区(HashPartitioner)与区域分区(RangePartitioner),能够满足大多说应用场景的需求。与此同时,Spark也支持自定义分区方式,即提供自定义的Partitioner对象来控制RDD的分区方式,从而利用领域知识进一步减少通信开销。其次,Spark的分区函数针对的是(key,value)类型的RDD,也就是说,RDD的每个元素都是(key,value)类型,分区函数根据key进行分区。因此对于非(key,value)类型的RDD进行分区,需要先把RDD转换为(key,value)类型,再进行分区。\


自定义分区类需要继承org.apache.spark.Partitioner类,实现下面三个方法
numPartitions:Int 返回创建出来的分区数
getPartition(key:Any):Int 返回给定键的分区编号(0~numPartitions-1)
equals():java判断相等性的标准方法\



WordCount实例图
WordCount实例

val file = "hdfs://mynode01:9000/opt/hello.txt"
var conf = new SparkConf().setAppName("WordCount").setMaster("local[4]")
conf.set("spark.testing.memory", "2147480000")
var sc = new SparkContext(conf)
var text = sc.textFile(file)
var wordcount = text.flatMap(line=>line.split(" ")).map(word=>(word,1)).reduceByKey((a,b)=>a+b)
wordcount.foreach(println)

1.6键值对RDD

1 键值对RDD的创建


键值对RDD的创建方式主要有两种:(1)从文件中加载生成RDD (2)通过并行集合(数组)创建RDD\


从文件中加载生成RDD

textFile().map()或textFile().flatMap()

通过并行集合生成RDD

parallelize().map或parallelize().flatMap()


1.7常用的键值对转换操作


reduceByKey(func)
使用func函数合并具有相同键的值。
reduceByKey与groupByKey不同,reduceByKey对每个key对应的值的聚合,而groupByKey生成的是(key,value-list)


groupByKey()
对相同的键进行分组
例(“hadoop”,1),(“spark”,2),(“hadoop”,3),(“spark”,1)分组后为(“hadoop”,(1,3)),(“spark”,(1,2))


keys
返回RDD中(K,v)格式数据集中的键


values
返回RDD中(K,v)格式数据集中的值


sortByKey()
返回提个根据key排序的RDD


sortBy(func)
返回按func排序后的RDD


mapValues(func)
对RDD中的(K,v)中的v进行func操作


join()
表示内连接,对于给定的两个输入数据集(K,V1)和(K,V2),只有两个数据集都存在的key才会被输出,得到(K,(V1,V2))的结果


combineByKey
combineByKey(createCombiner,mergeValue,mergeCombiners,partitioner,mapSideCombine)中的各个参数的含义如下:
createCombiner:在第一次遇到key时创建组合函数,将RDD数据集中的V类型值转换C类型值(V=>C);\

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值