来自官网的Spark Programming Guide,包括个人理解的东西。

  这里有一个疑惑点,pyspark是否支持Python内置函数(list、tuple、dictionary相关操作)?思考加搜索查询之后是这么考虑的:要想在多台机器上分布式处理数据,首先需要是spark支持的数据类型(要使用spark的文件I/O接口来读取数据),pyspark主要是Dataframe;然后需要用到spark的API。本来spark是支持Python的C语言开发的库包,那么Python的内置函数都是可以运行的,但是要想实现分布式处理,提高计算效率,在涉及到数据分发处理时要使用spark的transformation和action。潜台词是非分布式处理的操作可以用内置函数。是这样的吧?

  RDD是spark中最重要的抽象概念(数据结构),是集群中各节点上并行处理的分隔元素的集合(汇总),总会用到collect()方法。

  RDD可以从Hadoop文件系统中的文件创建,也可以从执行程序中的Scala集合中创建或转换。spark可以在内存中留存一份RDD,方便在并行运算中高效重用。

  还有个抽象概念,共享变量。spark在不同的节点并行执行任务集时,需要把每个变量的副本传送一份到每个任务中,有时候变量需要在任务中共享。

  共享变量有两种:广播变量(Broadcast Variables)和累加器(Accumulators)。前者缓存在所有节点的内存中,后者用来叠加计数或求和。

  Spark2.2.0可以使用标准的CPython接口,故C库如Numpy可以使用,Pandas亦可。

  1)spark程序的第一件事是创建一个spark上下文对象,其中,先要配置自己的应用信息。

  1. from pyspark import SparkContext, SparkConf
  2.  
  3. conf = SparkConf().setAppName('myFirstAPP').setMaster('local[*]')
  4. sc = SparkContext(conf=conf)

  1. data = [1, 2, 3, 4, 5]
  2. distData = sc.parallelize(data)
    #SparkContext.parallelize()用于将本地Python集合分布式处理为RDD格式,以便并行处理。可以设置分隔的数量,如
    sc.parallelize(data,6)
  1. #即,要想并行处理,数据必须要是RDD或DataSets或DataFrame格式。数据转换成这些格式后,就可以使用C库包来进行其他运算操作。

  2)外部文件,spark支持文本文件、序列文件及其他Hadoop输入格式。

  1. distFile = sc.textFile("data.txt") #文本文件,以行集合的格式读取
  2. distFile.map(lambda s: len(s)).reduce(lambda a, b: a + b) #textFile可使用DataSets的操作

  3)RDD操作:两种操作Transformation(从现存数据集中创建新的数据集DataSets)和Action(执行运算后将值返回给执行程序)。比如,map是transformation,reduce是action。

  所有的transformation都是‘懒的’,只记忆并不执行,只有当action需要返回值给执行程序时才执行计算,这样spark可以更高效。这样只会返回reduce结果,而没有庞大的map数据集。

  但是,如果有多个reduce,那么每次都要重新map,解决方法是:可以通过persist (or cache)方法将RDD留存在内存中。

  

  1. lines = sc.textFile("data.txt") #此处只创建一个指针
  2. lineLengths = lines.map(lambda s: len(s)) #此处未计算
  3. lineLengths.persist() #留存,以重用
  4. totalLength = lineLengths.reduce(lambda a, b: a + b) #此处开始计算,只返回计算结果。任务在多台机器上运行,每台机器只负责自己的map部分及本地reduce,并返回自己的值给执行程序。

  4)传递函数给spark:lambda表达式(不支持多语句,且要求有返回值),本地自定义def(适用于长代码),模块的Top-level函数。

  1. """MyScript.py"""
  2. if __name__ == "__main__":
  3. def myFunc(s):
  4. words = s.split(" ")
  5. return len(words) #分隔后返回长度。s是文件数据,下面的textFile是RDD
  6. #关于if __name__=="__main__"这种写法的用处,前面必然定义了一些函数,那么只在本程序中执行时运行该段代码,载入到其他程序时,就可以只用所定义的函数,而不会执行该段代码
  7.  
  8. sc = SparkContext(...)
  9. sc.textFile("file.txt").map(myFunc)

  注意:如果创建新的MyClass并调用doStuff()时,需要调用self.field,这样就需要把整个对象传送到集群中。把field复制到本地变量中可避免该情况。

  1. class MyClass(object):
  2. def __init__(self):
  3. self.field = "Hello"
  4. def doStuff(self, rdd):
  5. return rdd.map(lambda s: self.field + s)
  6. def doStuff(self, rdd): #复制field到本地变量
  7. field = self.field
  8. return rdd.map(lambda s: field + s)

  5)理解闭包:全局变量需要聚合时,建议使用Accumulator(累加器)。

  1. counter = 0
  2. rdd = sc.parallelize(data)
  3.  
  4. # Wrong: Don't do this!!
  5. def increment_counter(x):
  6. global counter
  7. counter += x
  8. rdd.foreach(increment_counter)
  9.  
  10. print("Counter value: ", counter)

  本地模式(使用相同的JVM)时可能可以执行,但集群模式就不会如预期般执行。执行之前,spark会计算任务的(序列化)闭包(对每个执行器都可见的变量或方法),但counter变量传递给执行器的是副本(copies),当foreach方法引用counter时,这已经不是执行节点的counter,而是工作节点的counter,那么最终counter可能还是0。

  执行节点(driver node)执行程序存在的地方,工作节点(work node)把任务分发到集群中的地方。

  此外,想要使用rdd.foreach(println) 或rdd.map(println)打印时,并不能实现预期效果。因为闭包模式中,stdout在工作节点的执行器中,并不在执行节点,故需要先使用collect()将所有元素汇总到执行节点。但把所有元素汇总到一台机器上可能会内存溢出,解决方法是take()rdd.take(100).foreach(println),只打印部分元素。

  6)用键值对进行操作:reduceByKey,sortByKey。键值对可使用Python內建的tuple轻松获得。

  1. lines = sc.textFile("data.txt")
  2. pairs = lines.map(lambda s: (s, 1))
  3. counts = pairs.reduceByKey(lambda a, b: a + b) #统计该文件每行的值出现几次,大概有重复的行
  4. counts.collect()

  7)常见transformation和action。列出常用操作,知道都能实现哪些功能。

  Transformation:

map(func) 经过func映射后,返回新的分布式数据集
filter(func) 返回新的数据集,由func为True时的元素的组成。过滤
flatMap(func) 类map,但每个输入项可映射到0或多个输出项,故func返回的是个序列
mapPartitions(func) 类map,在RDD的每个分区上分别执行,那么func的类型必须是迭代器Iterator<T> => Iterator<U>
mapPartitionsWithIndex(func) func提供整型值来表示分区的index,func的类型(Int, Iterator<T>) => Iterator<U>
sample(withReplacementfractionseed) 采样数据的fraction部分,可替换可不替换,随机数种子
union(otherDataset) 返回新的数据集,包括源数据和其他数据的元素,联合
intersection(otherDataset) 插入
distinct([numTasks])) 去重
groupByKey([numTasks]) 分组,note:若分组后要聚合,那么直接使用reduceByKey()或aggregateByKey()效率更高。任务数可选
reduceByKey(func, [numTasks]) 聚合
aggregateByKey(zeroValue)(seqOpcombOp, [numTasks]) 聚合
sortByKey([ascending], [numTasks]) 排序
join(otherDataset, [numTasks]) 连接, (K, V) and (K, W)->(K,(V,W))。外连接leftOuterJoinrightOuterJoin, and fullOuterJoin
cogroup(otherDataset, [numTasks])  (K, V) and (K, W)->(K, (Iterable<V>, Iterable<W>)) tuples
cartesian(otherDataset) 用于T和U类型RDD时,返回(T, U)对(类型键值对RDD)。笛卡尔的(笛卡尔乘积?)
pipe(command[envVars]) 通过shell命令管道处理每个RDD分片
coalesce(numPartitions)  减少分片数,适用于大的数据集过滤后
repartition(numPartitions)  重新分片,生成多的或少的分片数
repartitionAndSortWithinPartitions(partitioner)  重新分片并排序,如果重分片后需要排序,那么直接使用该函数

  Action:

reduce(func) 使用func聚合元素,(两个参数,然后返回一个结果),要求func是可交换、可组合的(加法交换律、结合律?),以便并行处理
collect() 返回数据集的所有元素,作为执行程序的数组
count() 返回数据集的元素数
first() 返回数据集的第一个元素
take(n) 返回前n个元素组成的数组
takeSample(withReplacementnum, [seed]) 返回随机采样的num个元素组成的数组
takeOrdered(n[ordering]) 返回排序后的前n个元素,自然顺序或自定义比较器
saveAsTextFile(path) 把数据集的元素作为TextFile写入到指定路径。spark会对每个元素调用toString,将其转换为文件中的一行文本
saveAsSequenceFile(path
(Java and Scala)
将数据集的元素保存到序列文件中
saveAsObjectFile(path
(Java and Scala)
将数据集的元素使用Java的序列化特性写到文件中
countByKey() 只适用于键值对RDD,返回哈希映射(key,int),对每个key计数
foreach(func) 对数据集的每个元素执行func。适用于带副作用的操作,如更新累加器或与外部存储系统交互

    8)洗牌(Shuffle)操作:包括重分片操作(repartition和coalesce),ByKey操作(reduceByKey、groupByKey、sortByKey,除去countByKey),连接操作(cogroup和join)

  比如reduceByKey(),需要按照某个可以去reduce时,同一个可以可能在不同的分片或者不同的机器上,那么每个分片执行之后,需要从每个分片读数据然后计算出最终的结果,这个过程就是洗牌。

    9)共享变量(broadcast变量 and accumulators)

  如果spark操作额函数是在远程集群节点上运行,那么函数所用到的所有变量都会分发一个副本到每台机器上,但是这些副本的修改(操作结果)并不能反馈回到执行程序(如果是原始变量的引用就可以修改原始变量)。那么多任务之间共享变量就是无效的。so,spark提供了两个限制类型的共享变量:广播变量和累加器。看具体用在什么场景:

  1、广播变量:允许在每台机器上缓存只读变量,比如给每个节点一个大型输入集的副本。显式地创建广播变量仅适用于跨多阶段需要相同数据的任务或者以非序列化的形式缓存数据。

  使用SparkContext.broadcast(v)创建广播变量。

  

  1. >>> broadcastVar = sc.broadcast([1, 2, 3])
  2. <pyspark.broadcast.Broadcast object at 0x102789f10>
  3.  
  4. >>> broadcastVar.value
  5. [1, 2, 3]

  2、累加器,只适用于在可交换、可结合的操作中去叠加。比如计数或是加和。spark天然支持数值类型,程序员也可以自行添加新的类型。

  使用SparkContext.accumulator(v)创建累加器。

  

  1. >>> accum = sc.accumulator(0)
  2. >>> accum
  3. Accumulator<id=0, value=0>
  4.  
  5. >>> sc.parallelize([1, 2, 3, 4]).foreach(lambda x: accum.add(x))
  6. ...
  7. 10/09/29 18:41:08 INFO SparkContext: Tasks finished in 0.317106 s
  8.  
  9. >>> accum.value
  10. 10

  

spark知识点_RDD的更多相关文章

  1. spark 学习_rdd常用操作

    [spark API 函数讲解 详细 ]https://www.iteblog.com/archives/1399#reduceByKey [重要API接口,全面 ] http://spark.apa ...

  2. Spark知识点

    1.Spark架构 分布式spark应用中的组件 在分布式环境下,Spark集群采用的是主/从结构.在一个Spark集群中,有一个节点负责中央协调,调度各个分布式工作节点.这个中央协调节点被称为驱动器 ...

  3. spark知识点_datasources

    来自官网DataFrames.DataSets.SQL,即sparkSQL模块. 通过dataframe接口,sparkSQL支持多种数据源的操作.可以把dataframe注册为临时视图,也可以通过关 ...

  4. Spark知识点小结

    函数在driver端定义.在executor端被调用执行

  5. 大数据核心知识点:Hbase、Spark、Hive、MapReduce概念理解,特点及机制

    今天,上海尚学堂大数据培训班毕业的一位学生去参加易普软件公司面试,应聘的职位是大数据开发.面试官问了他10个问题,主要集中在Hbase.Spark.Hive和MapReduce上,基础概念.特点.应用 ...

  6. Spark编程基础_RDD初级编程

    摘要:Spark编程基础_RDD初级编程 RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,是Spark中最基本的数据抽象,它代表一个不可变.可分区.里面的元素 ...

  7. 大数据学习day19-----spark02-------0 零碎知识点(分区,分区和分区器的区别) 1. RDD的使用(RDD的概念,特点,创建rdd的方式以及常见rdd的算子) 2.Spark中的一些重要概念

    0. 零碎概念 (1) 这个有点疑惑,有可能是错误的. (2) 此处就算地址写错了也不会报错,因为此操作只是读取数据的操作(元数据),表示从此地址读取数据但并没有进行读取数据的操作 (3)分区(有时间 ...

  8. Spark MLlib知识点学习整理

    MLlib的设计原理:把数据以RDD的形式表示,然后在分布式数据集上调用各种算法.MLlib就是RDD上一系列可供调用的函数的集合. 操作步骤: 1.用字符串RDD来表示信息. 2.运行MLlib中的 ...

  9. Spark Core知识点复习-1

    Day1111 Spark任务调度 Spark几个重要组件 Spark Core RDD的概念和特性 生成RDD的两种类型 RDD算子的两种类型 算子练习 分区 RDD的依赖关系 DAG:有向无环图 ...

随机推荐

  1. 超详细讲解mysql存储过程中的in/out/inout

    存储过程 大概定义:用一个别名来描述多个sql语句的执行过程. 最简单 delimiter // create PROCEDURE p1() begin select * from userinfo; ...

  2. Day2 Scrum 冲刺博客

    线上会议: 昨天已完成的工作与今天计划完成的工作及工作中遇到的困难: 成员姓名 昨天完成工作 今天计划完成的工作 工作中遇到的困难 纪昂学 总结会议内容,思考自己所分配到的任务 创建一个Cell类,用 ...

  3. CSP-S 2019 Solution

    Day1-T1 格雷码(code) 格雷码是一种特殊的 \(n\) 位二进制串排列法,要求相邻的两个二进制串恰好有一位不同,环状相邻. 生成方法: \(1\) 位格雷码由两个 \(1\) 位的二进制串 ...

  4. ACM里的期望和概率问题 从入门到精通

    起因:在2020年一场HDU多校赛上.有这么一题没做出来. 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6829 题目大意:有三个人,他们分别有X,Y ...

  5. Layui事件监听(表单和数据表格)

    一.表单的事件监听 先介绍一下几个属性的用法 1.lay-filter 事件过滤器 相当于选择器,layui的专属选择器 2.lay-verify 验证属性 属性值可以是 :required必填项, ...

  6. 抖音视频背景音乐提取工具v1.0

    使用方法:id就是你点那个音乐分享,复制链接,然后链接有个ID(userid=后面数字就是id),就是那个,输入ID之后得到链接,浏览器新建下载,复制你得到的链接就行了(结果空白多解析几次就行了)

  7. Day5 - 07 函数的参数-参数组合

    现在我们学完了位置参数.默认参数.可变参数.关键字参数.命名关键字参数五种参数类型.在Python中定义函数,可以使用这五种参数进行组合.但是参数定义的顺序必须是:必选参数.默认参数.可变参数.命名关 ...

  8. JavaSE05-数组

    1.概念 同一种类型数据的集合.其实数组就是一个容器. 2.优点 可以自动给数组中的元素从0开始编号,方便操作这些元素. 3.格式 1 元素类型[] 数组名 = new 元素类型[元素个数或数组长度] ...

  9. vue API 知识点(3) --- 实例 总结

    一.实例 property 1.vm.$data Vue 实例观察的数据对象,Vue 实例代理了对其 data 对象 property 的的访问 2.vm.$props 当前组件接收到的 props ...

  10. 一个小技巧助您减少if语句的状态判断

    作者:依乐祝 首发地址:https://www.cnblogs.com/yilezhu/p/14174990.html 在进行项目的开发的过程中, if 语句是少不了的,但我们始终要有一颗消灭 if  ...