Spark复习笔记

Spark概述

Spark是一个基于内存计算的大数据并行计算框架,是对MapReduce计算模型的扩展。

特点

  1. Spark可以基于内存也可以基于磁盘做迭代计算。
  2. 数据可以来自任何一种存储介质。如关系型数据库、本地文件系统、分布式存储等。
  3. 装载需要处理的数据至内存,并将这些数据集抽象为RDD(弹性分布式数据集)对象,然后采用一系列RDD操作处理RDD,并将处理好的结果以RDD的形式输出到内存,以数据流的方式持久化写入其他存储介质中。
  4. 使用Scala作为编程语言。它是一种面向对象、函数式编程语言,能够像操作本地集合对象一样轻松地操作分布式数据集。

优点

  1. 运行速度快
  2. 易用性好
  3. 通用性强
  4. 兼容性

Spark生态系统

在这里插入图片描述

应用层:Spark Streaming

数据处理引擎:Spark Core

资源管理层:YARN

数据存储层:HDFS

Spark Core是Spark生态系统的核心组件,是一个分布式大数据处理框架。Spark Core提供了多种资源调度管理

Spark应用执行的基本流程

  1. 当一个Spark应用程序被提交时,首先需要为这个应用程序构建运行环境,即由驱动程序创建一个SparkContext对象,SparkContext对象向集群资源管理器注册,之后SparkContext对象负责和集群资源管理器进行通信以及进行资源申请、任务的分配和运行监控等,此外还包括申请运行执行器进程的资源。
  2. 集群资源管理器根据预先设定的算法,在资源池里为执行器进程分配合适的运行资源,并启动执行器进程。再运行过程中,执行器运行情况将随着心跳信息发送到资源管理器上。
  3. SparkContext对象根据RDD之间的依赖关系构建DAG图,然后提交给有向无环图调度器进行解析,将DAG图分解成多个阶段(每个阶段就是一个任务集),并计算出各个Stage之间的依赖关系,然后把各个任务集提交给任务调度器进行处理。执行器进程向SparkContext对象申请任务,任务调度器将任务发放给执行器进程执行,同时SparkContext对象将应用程序代码发放给执行器进程,即将计算移到数据所在的节点上进行,移动计算比移动数据的网络开销要小得多。
  4. Task在执行器进程上运行,把执行结果反馈给Task Scheduler,然后再反馈给有向无环图调度器。运行完毕后写入数据,SparkContext对象向集群资源管理器注销并释放所有资源。

Scala编程

cd /usr/local/spark
./bin/spark-shell

Scala中使用Unit表示无返回值。

数组

定长数组长度不变,不能增删,只能修改某个位置的元素值,需要拥有相同的元素类型。下标从0开始。

var a:Array[String] = new Array[String](3)//所有元素初始化为null,int类型的数组初始化为0
var b = new Array[String](3)
var c = Array[String]("hello","scala")
c(1)
res1:String = scala//访问数组用(index),下标从0开始。

变长数组长度可变,可以增删

import scala.collection.mutable.ArrayBuffer
val arr1 = ArrayBuffer[Int]()//长度为0的变长数组
arr1 += 1
arr1 += (2,3,4,5)//变长数组添加元素

toBuffer和toArray方法可以转换数组为ArrayBuffer或Array。

遍历数组

val a = Array(1,2,3,4)
for(i <- 0 util (a.length,2))//从下标0开始隔一个遍历
for(i <- (0 util a.length).reverse)//尾部开始遍历
for(变量 <- 数组名)//不使用下标直接遍历

for(elem <- a if elem % 2 == 0) yield 2*elem//满足条件后创建新数组
a.filter(_%2==0)map{2 * _}//与上式效果一致
a.head//第一个元素
a.tail//除第一个以外的所有元素
a.sortBy(x => x)//升序
a.sortBy(x => -x)//降序

列表

不可变列表元素不可变,所有元素都有相同的数据类型。下标从0开始。

val L:List[Int]=(1,2,3,4)
val newList = 1::(3,5)
val 1::3::5::Nil

可变列表可以增删改元素

import scala.collection.mutable.ListBuffer
val LB1 = ListBuffer(1,2,3,4,5,6)
LB1 -= 6
LB1.remove(index)//删除index处的元素并返回删除的元素
LB1.remove(2,3)//从下标2开始删除3个元素

LB1 += 7
LB1.insert(0,6)//在0位置插入元素6
LB1 ++= Array('a','b')//和数组一样++=操作符可以追加任何集合

集合

集合是没有重复的元素合集,所有的元素都是唯一的。默认情况下,集合不可变,以哈希实现,即元素是根据hashCode进行组织的。

val a = Set("Scala","Python","Java")
val b = Set("C")
val c = a.++b//.++连接两个集合,或者使用 a.++(b)

val set = Set(1,2,3) 
set.forall(e => e>100)//判断集合中的每个元素是否满足条件,返回Boolean
set.foreach(e => e+2)//遍历做处理
set.+(4)//添加新元素并创建新集合

映射(Hash tables)

val s1 = Map("LiHua"->99,"XiaoMing"->98)
val s2 = Map(("XiaoHong",99),("XiaoFang",98))

s1("XiaoMing")//获取值
s1.for((k,v) <- s) //遍历

s1 + ("Xiaoli"->1,"XiaoWang"->2)//添加一个或多个
s1 -"Xiaoli"-"XiaoWang"//删除一个或多个
var s3 = s1 ++ s2//合并映射,会去除重复的键值对

元组

元组不可变,元素类型可不一致,下标从1开始

val person=(1,"XiaoMing","男",23)

persion.productIterator.foreach{i => print("元组元素:"+i)}//元组元素:1元组元素:XiaoMing元组元素:男元组元素:23

函数

标准函数体:

def 函数名(形参:形参类型,形参:形参类型):返回值类型={
	return
}
//有返回值时可以省略返回值类型和return
如 addInt(a:Int,b:Int)={
	a+b
}
//自动返回函数体中的最后一个表达式的值,但是赋值语句返回的是空值,所以赋值语句不能在最后。
addInt(a:Int,b:Int){
	a+b
}
//没有=时默认函数无返回值,等同于使用Unit

匿名函数

var x = (a:Int, b:Int)=>{a+b}(2,3)//匿名函数表达式的值就是函数的返回值,该处声明了一个匿名函数,并且调用然后赋值给一个变量

高阶函数

def f3(a:Int,b:Int,(a:Int,b:Int)=>Int)={f(a,b)}
f3(2,3, (a:Int,b:Int)=>{a+b}//返回值为5

模式匹配

//变量 match{case 值 =>代码}
val value = 1
value match{
	case 1 => print("1")
	case 2 => print("2")
	case_ => print("其他的数")
}

Scala类

默认是class类型,可以传参(称为类参数),类参数整个类中都可以访问

Scala实现水仙花数:
for(a<-100 until 1000){
 val b = a/100%10
 val s = a/10%10
 val g =a%10
 var sum=b*b*b + s*s*s + g*g*g
 if(sum==a){
 println("当前的⽔仙花数是:"+a)
 }
    
三维向量的加减向量和乘除标量
class Vector(xc:Int,yc:Int,zc:Int){
	var x:Int = xc
	var y:Int = yc
    var z:Int = zc
	def add(n:Vecter){
    	x = x + n.x
        y = y + n.y
        z = z + n.z
    }
    def sub(n:Vecter){
        x = x - n.x
        y = y - n.y
        z = z - n.z
    }
    def mul(elem:Int){
        x = x * elem
        y = y * elem
        z = z * elem
    }
    def div(elem:Int){
        x = x / elem
        y = y / elem
        z = z / elem
    }
}

vector2=Vector(4,4,6)
new Vector(1,2,7).add(vector2)
new Vector(1,2,7).sub(vector2)
new Vector(1,2,7).mul(3)
new Vector(1,2,7).div(2)

//给定一组键值对(“spark”,2),(“hadoop”,6),(“hadoop”,4),(“spark”,6),键值对的key表示图书名称,value表示某天图书销量,请计算每个键对应的平均值,也就是计算每种图书的每天平均销量。
scala> val rdd = sc.parallelize(Array(("spark",2),("hadoop",6),("hadoop",4),("spark",6)))
scala> rdd.mapValues(x => (x,1)).reduceByKey((x,y) => (x._1+y._1,x._2 + y._2)).mapValues(x => (x._1 / x._2)).collect()
res22: Array[(String, Int)] = Array((spark,4), (hadoop,5))

Spark编程

RDD弹性分布式数据集,是一个不可变的分布式对象集合,是一个只读的分区记录集合

val arr = Array(1,2,3,4,5,6)
val rdd1 = sc.parallelize(arr)//默认分区为系统分区,我的是8核所以分区为8
val rdd2 = sc.makeRDD(arr)//系统为对象创建最佳分区,此处为3

RDD持久化

RDD的持久化是缓存在内存中的,之后的反复计算都是直接调用内存缓存的partition。

Spark的持久化机制是自动容错的,如果持久化的RDD的任何partition丢失了,那么Spark会自动通过其源RDD,使用转换操作重新计算该partition,而不需要计算所有分区。

sbt打包命令

cd ~/sparkapp
/usr/local/sbt/sbt package

DataFrame

DataFrame是一个分布式的Row对象的数据集合。

创建

val dfUsers = sqlContext.read.load("/usr/local...")//parquest格式
val dfPerson = sqlContext.read.format("json").load()//json格式
val df = sc.parallelize().toDF("name:","age")

操作

df.show()//默认展示前20条数据,里面参数为int时展示前int条,参数为false时不进行缩略

RDD和DataFrame的联系与区别

区别:

  • RDD是分布式的java对象的集合,但是对象内部结构对于RDD而言却是不可知的。
    DataFrame是一种以RDD为基础的分布式数据集,提供了详细的结构信息,相当于关系数据库中的一张表

联系:

  1. 都是spark平台下的分布式弹性数据集,为处理超大型数据提供便利
  2. 都有惰性机制,在进行创建、转换,如map方法时,不会立即执行,只有在遇到Action才会运算
  3. 都会根据spark的内存情况自动缓存运算,这样即使数据量很大,也不用担心会内存溢出
  4. 三者都有partition的概念
  5. 三者有许多共同的函数,如filter,排序等

DataFrame的操作

df.count()//df的行数
df.distinct()//去重
df.dropDuplicates(seq("Java"))//根据指定字段(Java)去重
df.drop("Java")//去除指定字段,保留其余字段
df.sort()//和orderBy一样,默认升序
df.describe("Scala","Spark")//返回所传入字段的count、max、min、mean、stddev等值

Spark Streaming

Spark Streaming时Spark提供的用于处理流式数据的分布式大数据实时计算框架,具有可伸缩、高吞吐量、容错能力强等特点。

流数据时一组顺序、大量、快速、连续到达的数据序列,可被视为一个随时间延续二无限增长的动态数据集合。

特点:

  1. 数据实施到达
  2. 到达次序独立,不受系统控制
  3. 规模宏大且不被预知其最大值
  4. 不能再次取出处理

批处理和流处理的区别(静态和动态)

批处理的特点是有界、持久、⼤量,⾮常适合需要访问全套记录才能完成的计算⼯作,⼀般⽤于离线统计。

流处理的特点是⽆界、实时,⽆需针对整个数据集执⾏操作,⽽是对通过系统传输的每个数据项执⾏操作,⼀般⽤于实时统计。

操作

Dstream无状态转化操作

指每次对新的批次数据进行处理时,只会记录当前批次数据的状态,不会记录历史数据状态信息。

有状态转化操作

是跨时间区间跟踪数据的操作,包括滑动窗口转化操作和updateStateByKey()操作。

属性图

Spark GraphX是一个分布式图处理框架,它是基于Spark平台提供图计算和图挖掘的一个简洁易用的接口。GraphX的核心抽象(数据处理模型)是弹性分布式属性图。属性图是带有属性信息的顶点和边构成的图。

图存储模式

原则

  1. 提高子图内部的连通性,降低子图之间的连通性。
  2. 尽量保持各子图的数据规模均衡

分类

边分割存储指保持各个顶点在计算节点均匀分布,每个顶点都存储一次。

​ 优点:通过顶点复制策略减少跨节点的边数目。

​ 缺点:但不可避免地增加了邻接顶点和边的存储开销。

点分割存储指保持各个边在计算节点均匀分布。

​ 优点:能够减少跨节点之间的数据通信。

​ 缺点:但会增加各个边的邻接顶点的存储开销,同时也会引发数据同步问题。

Spark在机器学习上的优势

  1. Spark非常适合迭代计算,刚好适应机器学习对迭代计算的需要。
  2. 通信效率极高。
  3. MLlib基于RDD,可以和Spark SQL、GraphX、Spark Streaming无缝集成,并以RDD为基础进行联合数据计算。
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值