RDD Persistence持久化
spark RDD持久机制可以用于将需要重复运算的RDD存储在内存中,以便大幅提升运算效率
Spark RDD持久化使用方法如下:
- RDD.persist(存储等级) ——可以指定存储等级,默认是MEMORY_ONLY,也就是存储在内存中
- RDD.unpersist()——取消持久化
MEMORY_ONLY
这是默认选项,存储RDD的方式是以Java对象反串行化在JVM内存中,如果RDD太大无法完全存储在内存,多余的RDD partitions不会缓存在内存中,而是需要时重新计算
MEMORY_AND_DISK
存储RDD的方式是以Java对象反串行化在JVM内存中,如果RDD太大就无法完全存储在内存,会将多余的RDD partitions存储在硬盘中,需要时再从硬盘中读取。
MEMORY_ONLY_SER
与MEMORY_ONLY类似,但是存储RDD以Java对象串行化,因为需要再进行反串行化才能使用,所以会多使用CPU的计算资源,但是比较节省内存的存储空间。多余的RDD partitions不会缓存再内存中,而是需要时再重新计算。
MEMORY_AND_DISK_SER
与MEMORY_ONLY_SER类似,会将多余的RDD partitions存储在硬盘中,需要时再从硬盘读取
DISK_ONLY
存储在RDD硬盘上
MEMEORY_ONLY_2,MEMORY_AND_DISK_2,etc
与上列对应的存储选项一样,但是每一个RDD partitions都复制到两个节点
from pyspark import SparkContext
sc = SparkContext()
intRDDMemory = sc.parallelize([3,1,2,5,5]) # 创建intRDDMemory
intRDDMemory
ParallelCollectionRDD[0] at parallelize at PythonRDD.scala:194
intRDDMemory.persist() # 将intRDDMemory持久化
ParallelCollectionRDD[0] at parallelize at PythonRDD.scala:194
intRDDMemory.is_cached # 查看是否已经cached(缓存) True代表已经缓存
True
使用RDD.unpersist()取消持久化
intRDDMemory.unpersist() # 取消持久化
ParallelCollectionRDD[0] at parallelize at PythonRDD.scala:194
intRDDMemory.is_cached # 查看是否已经取消缓存 False表示已经取消缓存
False
RDD.persist设置存储等级范例
intRDDMemoryAndDisk = sc.parallelize([3,1,2,5,5]) # 创建RDD
intRDDMemoryAndDisk
ParallelCollectionRDD[1] at parallelize at PythonRDD.scala:194
使用Spark创建WordCount
创建测试文件
在“终端”程序中的提示符后输入下列命令:
创建WordCount的数据目录
mkdir -p ~/pythonwork/ipynotebook/data
切换至WordCount的数据目录
cd ~/pythonwork/ipynotebook/data
编辑test.txt
gedit test.txt
执行WordCount spark命令
在Spark运行WordCount就是如此简单,只需要4行命令。在pyspark输入下列命令,这些命令的详细用法
# 读取文本文件
textFile = sc.textFile('./test.txt')
# 使用flatMap空格符分隔单词,并读取每个单词
textFile
./test.txt MapPartitionsRDD[3] at textFile at NativeMethodAccessorImpl.java:0
stringRDD = textFile.flatMap(lambda line: line.split(" "))
countsRDD = stringRDD.map(lambda word:(word,1)).reduceByKey(lambda x,y:x+y)
countsRDD.saveAsTextFile('spark/output')
查看 %cat /spark/output/part-0000*
(‘Apple’, 2)
(‘Orange’, 1)
(‘Banana’, 1)
(‘Grape’, 2)
Spark WordCount详解
首先,读取本地文件。因为sc.textFile是一个转换运算,所以不会马上执行。
textFile = sc.textFile('./test.txt')
textFile.collect()
['Apple Apple Orange', 'Banana Grape Grape']
flatMap 读取每一个单词
文本以空格为分隔符,使用flatMap指令取出每一个文字,并编写stringRDD。因为之前的每一个指令是一个“转换”运算,不会马上执行,所以使用collect将结果转换为List,就会立即执行
stringRDD = textFile.flatMap(lambda line: line.split(' '))
stringRDD.collect()
['Apple', 'Apple', 'Orange', 'Banana', 'Grape', 'Grape']
**flatMap与map差异 **
需要注意的是,在上一步以空格符分隔单词创建stringRDD时,必须要使用flatMap,不能使用map,因为flatMap与map功能不同。
Map
map产生的List时分层的。第一层List是文本显示的每一行,第二层List是每一行内的英文单词。
flatMap
flatMap有平坦的意思,也就是说flatMap产生的List会将所有的分层去掉,结果为List。
stringRDD = textFile.map(lambda line: line.split(' '))
stringRDD.collect()
[['Apple', 'Apple', 'Orange'], ['Banana', 'Grape', 'Grape']]
stringRDD = textFile.flatMap(lambda line: line.split(' '))
stringRDD.collect()
['Apple', 'Apple', 'Orange', 'Banana', 'Grape', 'Grape']
map创建Key-Value Pair
使用map来创建Key-Value Pair。因为有了Key-Value Pair,就可以进行并行运算了
stringRDD.map(lambda word: (word,1)).collect()
[('Apple', 1),
('Apple', 1),
('Orange', 1),
('Banana', 1),
('Grape', 1),
('Grape', 1)]
1.使用map命令将stringRDD每一单词转为Key-Value
2.其中Key值是每一个英文单词,Value值都是1
3.因为map是“转换”运算,所有不会马上实际运行。为了立刻看到结果,可以加上“行动”运算.foreach(println)输出每一条数据
map加reduceByKey
使用map加上reduceByKey完成Map/Reduce功能
reduceByKey传入匿名函数(lambda x,y:x+y),此匿名函数将相同的key值相加。因为reduceByKey是“转换运算”,所以不会马上运行。加上“动作运算”.collect(),转换为List,就会马上执行
s = stringRDD.map(lambda word:(word,1))
s
PythonRDD[30] at RDD at PythonRDD.scala:52
S = s.reduceByKey(lambda x,y:x+y)
S.collect()