【Spark】2、RDD

弹性分布式数据集(Resilient Distributed Dataset),是Spark的核心,属于一种分布式的内存系统数据集应用,能与其他系统兼容,导入外部存储系统的数据集,如HDFS、HBase等

RDD的特性

1、RDD的三种基本运算

在这里插入图片描述
在这里插入图片描述
Lineage机制具备容错的特性
RDD本身具有Linear机制。记录每个RDD与其父代RDD之间的关联,还会记录通过什么操作才由父代RDD得到该RDD的信息。
RDD本身的immutable(不可变)特性,再加上Linearage机制,使得Spark具备容错的特性。如果某节点的机器发生故障,那么存储于这个节点上的RDD损毁后就会重新执行一连串的**“转换”**命令,产生新的输出数据。

2、转换运算

进入pyspark

创建intRDD(转换运算,不会立即执行)
intRDD = sc.parallelize([3, 1, 2, 5, 5])
intRDD转换为List(动作运算,立即执行)
intRDD.collect()

在这里插入图片描述

创建stringRDD
stringRDD = sc.parallelize(["A","B","C","D","E"])
map运算

map运算可以通过传入的函数将每一个元素经过函数运算产生另外一个RDD,RDD通过传入的函数addOne将每一个元素加1,从而产生另一个RDD。
map运算中,可以使用两种语句:具名函数和匿名函数

使用具名函数
def addOne(x):
	return (x+1)

将addOne作为参数传入map函数

intRDD.map(addOne).collect()

在这里插入图片描述

使用匿名函数

此方法更为简洁

intRDD.map(lambda x : x + 1).collect()

在这里插入图片描述

字符串运算
stringRDD.map(lambda x : "letter:" + x).collect()

在这里插入图片描述

filter运算
数字运算
intRDD.filter(lambda x:x<3).collect()

在这里插入图片描述

字符串运算
stringRDD.filter(lambda x : "C" in x).collect()

在这里插入图片描述

distinct运算
intRDD.distinct().collect()

在这里插入图片描述

randomSplit运算

randomSplit运算可以将整个集合元素以随机数的方式按照比例分为多个RDD
以随机数的方式按照4:6的比例分割为两个RDD

sRDD = intRDD.randomSplit([0.4,0.6])

分开的两个RDD

sRDD[0].collect()
sRDD[1].collect()

在这里插入图片描述

groupBy运算

groupBy可以按照传入的函数规则将数据分为多个list
将集合分为奇数与偶数

gRDD = intRDD.groupBy(
	lambda x:"even" if x % 2 == 0 else "odd"
).collect()

在这里插入图片描述

3、多个RDD转换运算

i1 = sc.parallelize([3, 1, 2,  5, 5])
i2 = sc.parallelize([5, 6])
i3 = sc.parallelize([2, 7])
union并集运算
i1.union(i2).union(i3).collect()

在这里插入图片描述

intersection交集运算
i1.intersection(i2).collect()

在这里插入图片描述

subtract差集运算
i1.subtract(i2).collect()

在这里插入图片描述

cartesian笛卡尔乘积运算
i1.cartesian(i2).collect()

在这里插入图片描述

4、基本“动作”运算

读取元素
i1.first()
i1.take(2)
i1.takeOrdered(3) # 从小到大排序,取出前三项
i1.takeOrdered(3, key=lambda x:-x) # 从小到大排序,取出前三项

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

统计
i1.stats()

在这里插入图片描述

5、RDD Key-Value 基本“转换”运算

RDD支持Key-Value运算,Key-Value运算也是MapReduce的基础

kv1 = sc.parallelize([(3,4),(3,6),(5,6)])

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

使用filter筛选出key<5
kv1.filter(lambda keyValue:keyValue[0]<5).collect()

在这里插入图片描述
同理可筛选出value<5的元素

mapValues运算

mapValues运算可对RDD内每一组(Key,Value)进行运算,并产生另一个RDD

将Value的每一个值进行平方运算
kv1.mapValues(lambda x:x*x).collect()

在这里插入图片描述

sortByKey运算

按照key排序,默认参数为True,从小到大排序

kv1.sortByKey(ascending=True).collect()

在这里插入图片描述

reduceByKey

reduceByKey按照Key进行reduce运算

运算过程:

找到相同的key值,将他们的value按照规则合并,不同的key值的元素不进行操作

相同key值的相加
kv1.reduceByKey(lambda x,y:x+y).collect()

在这里插入图片描述

6、多个RDD Key-Value“转换运算”

kv1 = sc.parallelize([(3,4),(3,6),(5,6)])
kv2 = sc.parallelize([(3,8)])
join运算

将两个RDD按照相同的key值组合

kv1.join(kv2).collect()

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

leftOuterJoin运算

左连接

kv1.leftOuterJoin(kv2).collect()

在这里插入图片描述

rightOuterJoin运算

右连接

kv1.rightOuterJoin(kv2).collect()

在这里插入图片描述

subtractByKey运算

删除相同key值的数据

kv1.subtractByKey(kv2).collect()

在这里插入图片描述

Key-Value“动作”运算

读取元素
kv1.first()
kv1.take(2)
kvFirst=kv1.first()
kvFirst[0]

在这里插入图片描述

计算Key的项数
kv1.countByKey()

在这里插入图片描述

lookup运算,

查找对应Key值的Value

kv1.lookup(3)

在这里插入图片描述

collectAsMap创建字典
kv = kv1.collectAsMap()
kv
type(kv)

在这里插入图片描述

7、共享变量

共享变量可用于节省内存与运行时间,提升并行处理时的执行效率,共享变量包括广播变量和累加器

广播变量

在进行操作时,我们会发现有些操作会产生许多RDD,这样会耗费很多内存和时间,如以下例子
在这里插入图片描述
为解决这个问题,就必须使用Broadcast广播变量

广播变量使用规则

先创建好示例数据

kv = sc.parallelize([(1,"apple"),(2,"orange"),(3,"banana"),(4,"grape")])
kvMap = kv.collectAsMap()

1、使用SparkContext.broadcast([初始值])创建

bckvMap = sc.broadcast(kvMap)

2、使用.value方法读取广播变量的值

kvID = sc.parallelize([2,4,1,3])
values = kvID.map(lambda x:bckvMap.value[x]).collect()
values

3、Broadcast广播变量被创建后不能修改

执行结果:
在这里插入图片描述
在这里插入图片描述
在进行并行处理中,bckvMap广播变量会传送到Worker Node机器,并且储存到内存中,后续在此Work Node都可以使用bckvMap执行转换,这样可以节省很多内存与传送时间

accumulator累加器

计算总和是MapReduce常用的运算。为了方便并行处理,Spark提供了累加器共享变量

使用规则

1、accumulator累加器可以使用SparkContext.accumulator([初始值])创建
2、使用.add()进行累加
3、在task中,如foreach循环中,不能读取累加器的值
4、只有驱动程序,也就是循环外,才可以使用.value读取累加器的值

创建范例

i = sc.parallelize([3, 1, 2, 5, 5])

创建累加器t,初始值为0.0

t = sc.accumulator(0.0)

创建累加器n,初始值为0

n = sc.accumulator(0)

使用foreach传入参数i,针对每一项数据执行
t累加元素值,n累加元素个数

i.foreach(lambda x:[t.add(x), n.add(1)])

计算平均=求和/计数,并显示总和、数量

avg = t.value / n.value
avg
t.value
n.value

在这里插入图片描述

8、Persistence持久化

RDD持久化机制可以用于将需要重复运算的RDD存储在内存中,以便大幅提升运算效率
使用方法
1、RDD.persist(存储等级)——可以指定存储等级,默认是MEMORY_ONLY,也就是存储在内存中
2、RDD.unpersist()——取消持久化

MEMORY_ONLY
这是默认选项。存储RDD的方式是以Java对象反串行化在JVM内存中,如果RDD太大无法完全存储在内存中,多余的RDD partitions不会缓存在内存中,而是需要时再重新计算

MEMORY_AND_DISK
存储RDD的方式是以Java对象反串行化在JVM内存中,如果RDD太大无法完全存储在内存中,多余的RDD partitions存储在硬盘中,需要时,再从硬盘读取

MEMORY_ONLY_SER
存储RDD的以Java对象串行化。由于需要在进行反串行化才能使用,所以会多使用CPU计算资源,但比较省内存空间。多余的RDD partitions不会缓存在内存中,而是需要时再重新计算

MEMORY_AND_DISK_SER
MEMORY_ONLY_SER类似,多余的RDD partitions存储到硬盘,需要时再读取

DISK_ONLY
存储RDD在硬盘上

MEMORY_ONLY_2,MEMORY_AND_DISK_2,etc
与上列一样,但每个RDD partitions都复制到两个节点

使用过程

使用持久化

i = sc.parallelize([3,1,2,5,5])
i.persist()
i.is_cached

在这里插入图片描述
取消持久化

i.unpersist()
i.is_cached

在这里插入图片描述

设置存储等级范例

from pyspark.storagelevel import StorageLevel
i.persist(StorageLevel.MEMORY_AND_DISK)
i.is_cached

在这里插入图片描述

9、Spark创建WordCount

创建文件夹

mkdir /usr/sparktest

创建txt文件

vim /usr/sparktest/test.txt

进入pyspark

pyspark --master local[*]

执行以下操作

text = sc.textFile("/usr/sparktest/test.txt")
s = text.flatMap(lambda line:line.split(" ") )
count = s.map(lambda word:(word,1)).reduceByKey(lambda x,y:x+y)
count.saveAsTextFile("/usr/sparktest/output")

在这里插入图片描述
在这里插入图片描述
查看输出目录

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值