创建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

rdd 调用外部函数 java_spark

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()

rdd 调用外部函数 java_rdd 调用外部函数 java_02

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)

rdd 调用外部函数 java_spark_03

行动操作

action,真正计算

rdd 调用外部函数 java_持久化_04

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

rdd 调用外部函数 java_rdd 调用外部函数 java_05

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()

rdd 调用外部函数 java_持久化_06

遇到:ValueError: Cannot run multiple SparkContexts at once; existing SparkContext(…)
 sc.stop() // 关闭spark