创建RDD
从文件系统加载
.textFile()
line=sc.textFile(’/Users/admin/Desktop/word.txt’)sc=SparkContext
line.foreach(print)
并行集合(数组)创建
parallelize
array=[1,2,3,4,5]
rdd=sc.parallelize(array)rdd.foreach(print)
rdd操作
转换操作
只记录轨迹,不进行计算
filter:过滤
lines=sc.textFile(’/Users/admin/Desktop/word.txt’)
linesWITHspark=lines.filter(lambda line:“spark” in line)
linesWITHspark.foreach(print)
map:一对一映射
data=[1,2,3,4,5]
rdd1=sc.parallelize(data)
rdd2=rdd1.map(lambda x:x+10)
rdd2.foreach(print)word=lines.map(lambda line:line.split(" "))
word.foreach(print)
[‘Hadoop’, ‘is’, ‘good’]
[‘spark’, ‘is’, ‘fast’]
[‘spark’, ‘is’, ‘better’]
flatmap:非一对一
words=lines.flatMap(lambda line:line.split(" "))
words.foreach(print)
Hadoop
is
good
spark
is
fast
spark
is
better
groupBykey:分组
words=sc.parallelize([(“Hadoop”,1),(“is”,1),(“good”,1),(“Spark”,1),(“is”,1),(“fast”,1),(“Spark”,1),(“is”,1),(“better”,1)])
words1=words.groupByKey()
reducebukey:分组聚合
- groupBykey基础上进行计算
words2=words.reduceByKey(lambda a,b:a+b)
words2.foreach(print)
(‘Hadoop’, 1)
(‘good’, 1)
(‘fast’, 1)
(‘better’, 1)
(‘is’, 3)
(‘Spark’, 2)
行动操作
action,真正计算
data=[1,2,3,4,5]
rdd1=sc.parallelize(data)count rdd1.count()
5
collect
rdd1.collect()
[1, 2, 3, 4, 5]
first rdd1.first()
1
take rdd1.take(3)
[1, 2, 3]
reduce rdd1.reduce(lambda a,b:a+b)
15
foreach
rdd1.foreach(lambda elem:print(elem))
- 惰性机制
转换阶段只进行记录不计算
lines=sc.textFile('/Users/admin/Desktop/word.txt')
lineLenght=lines.map(lambda s:len(s))
totalLength=lineLenght.reduce(lambda a,b:a+b)
print(totalLength)
>42
持久化
RDD采用惰性机制,每次遇到行动操作,都会从头开始执行。每次调用行动操作,都会触发一次从头开始的计算。对于迭代计算而言,代价是非常大的,迭代计算经常需要重复使用同一组数据。
list=["Hadoop","Spark","Hive"]
rdd=sc.parallelize(list)
print(rdd.count())
>3
遇到count,需要从头开始计算
print(’,’.join(rdd.collect()))
Hadoop,Spark,Hive
遇到collect,又需要从头开始计算
为了解决这个问题,出现了持久化,来避免这种重复计算的开销
可以使用persist对一个RDD标记为持久化
persist
persist只是标记持久化
,因为出现persist()语句的地方并不会马上计算生存RDD,并把它持久化,而是要等到第一个行动操作出发真正计算后,才会把计算结果进行持久化
持久化的RDD将会被保留在计算节点的内存中被后面是的行动操作重复执行
- persist(MEMORY_ONLY)表示将RDD作为反序列化的对象存储于JVM中,如果内存不足,就要按照LRU原则(先进先出)替换缓存中的内容
- persist(MEMORY_AND_DISK)表示将RDD作为反序列化的对象存储于JVM中,如果内存不足,超出的分区将会被存放在硬盘上
- 一般而言,使用cache()方法时,会调用persist(MEMORY_ONLY)
- 可以使用unpersist方法手动把持久化的RDD从缓存中移除
list=["Hadoop","Spark","Hive"]
rdd=sc.parallelize(list)
rdd.cache()
会调用persist(MEMORY_ONLY),但是语句执行到这里,并不会缓存RDD,因为这时RDD还没有被真正计算
print(rdd.count())
3
第一次行动操作,,触发一次真正的从头开始的计算,这时上面的rdd.cache()才会被执行,把这个RDD放在缓存中
print(’,’.join(rdd.collect()))
Hadoop,Spark,Hive
第二次行动操作,不需要从头开始计算,只需要重复使用上面缓存的RDD
分区
作用
增加并行度
减少通信开销
原则
分区个数=集群中CPU核心数目
设置方法
list=[1,2,3,4,5]
rdd=sc.parallelize(list,2)
lines=sc.textFile('/Users/admin/Desktop/word.txt',2)
reparition方法重新设置分区个数
data=sc.parallelize([1,2,3,4,5],2)
data.glom().collect()
>[[1, 2], [3, 4, 5]]
>
len(data.glom().collect())
>2
重置
rdd=data.repartition(1)
len(rdd.glom().collect())
>1
可以重复设置分区数目,所以时弹性分布式
分区方式
自带分区
- 哈希分区
- 区域分区
def MyPartitioner(key):
print("MyPartitioner is running")
print('The Key is %d'%key)
return Key%10
def main():
print("The main function is running")
conf=SparkConf().setMaster("local").setAppName("MyApp")
sc=SparkContext(conf=conf)
data=sc.parallelize(range(10),5)
data.map(lambda x:(x,1)).partitionBy(10,MyPartitioner).map(lambda x:x[0]).saveAsTextFile("file:///Users/admin/Desktop/model/Spark/list")
if __name__=='__main__':
main()
遇到:ValueError: Cannot run multiple SparkContexts at once; existing SparkContext(…)
sc.stop() // 关闭spark