RDD的处理方法(创建、转换、行动、分区)

spark生态系统:底层是spark core,在spark core的基础上开发了其他组件,可以支持不同的应用场景。spark sql支持sql 查询,spark streaming可以支持流计算,spark mLlib支持机器学习等。

rdd编程是指spark core(底层)的编程。为什么叫rdd编程?因为整个过程就是对rdd的一次又一次的转换。

 

rdd编程基础

1、rdd创建方法

现有两种方法创建rdd:通过文件系统中加载数据创建rdd,通过并行集合(数组)来创建rdd。

1、通过文件系统加载数据创建rdd

textfile()支持的数据类型:

分布式文件系统HDFS;本地文件系统;云端文件如Amazon S3等

假设现有文档word.txt有三行记录,经过sc.textfile()加载,就生成了上图右侧的RDD,RDD的名称为lines,该RDD包含了三个元素,每个元素对应了文本文件的一行,所以加载后的RDD每个元素是字符串类型。

参看RDD中元素,可使用高阶函数foreach方法,里面传递一个函数作为它的参数,此处传递的是print函数。

hdfs后面是两个斜杠,localhost是主机名,9000为安装hadoop的端口号

在linux系统中,有个主目录,若用hadoop用户名登录linux系统,那么linux系统会自动为hadoop用户创建一个主目录\home\hadoop,简约用~表示。同理在分布式文件系统hdfs中,也存在一个当前用户的用户主目录,该主目录为/user/hadoop.

 

2、并行集合(数组)创建rdd

 

2、RDD操作(转换操作filter、map、flatmap)

将健封装在用pyspark.resultiterable.ResultIterable对象中

reducebykey相当于先用groupbykey进行操作,得到结果后再执行lambda函数的操作。

 

3、RDD操作(行动操作)

 

4、持久化

对于迭代计算,经常需要多次重复使用同一组数据,持久化可以将多次访问的值保存在内存中,不消失,下次再重复使用的时候就需要从头到尾的计算了。

peisist()

persist(memory_only):将RDD作为反序列化对象存在JVM当中,如果内存不足,就按LRU(litte recently use)原则(最近最少使用原则)原则替换内存(仅存在内存当中)。

persist(memory_and_disk):同时保存在内存和磁盘。优先保存内存,若内存不足,再将多余的存入磁盘。

在实际工作中,我们都常使用保存在内存中,对于persist(memory_only)有一个简介的方法:.cache()方法

我们知道当内存中东西太多会降低电脑的速率的,所以当我们使用完并确保后续不在使用之前计算的RDD时,我们需要将该RDD从内存中删除。

 

5、RDD分区

RDD分区的好处:1、能够增加并行度,即并行计算;2、减少通信开销

userData表是一个非常庞大的表,有成百上千万的用户,每个用户均有一个userID和userInfo。events表是一个小表,包含两个字段,分别为userID和LinkInfo,记录了这些用户在过去的五分钟之内所访问的网站的链接信息,比如userID为1的用户,访问了新浪网,userID为2的用户,访问了阿里巴巴网,即events记录了每个用户访问的链接信息。

若我们希望找到用户的名字、单位、访问了什么网站,则需要将UserData与events连接起来。这两表的连接就关系到分区的问题。

假设没有分区去做连接,对于userData,数据非常大的时候,数据需要分块存储(注:不是分区),即数据在一台机器上存储不了,需要分块,分块保存在不同机器上,如上图所示的u1块、u2块、u3块等,每块都分布在不同的机器上。假设有一千万用户,这时候u1、u2、u3块等的userID均散布在0至一千万之间(因为不是分区,而是分块,每块的用户信息都是散布在0至一千万之间)。这时候连接采用了一个中间机器,让j1机器负责0至100万的连接,j2机器负责100万到200的连接,以此类推。此时将u1块中0-100万的userID呈给j1,100万-200万的userID呈给j2等,同理针对u2块......。如此这样就会发生如上图所示的大量数据的交叉传输,这就是涉及非常昂贵的通信开销。

                               

若采取分区处理,如上图所示,让u1只保存0-100万的userID信息,u2只保存100-200万的userID信息,以此类推。如此再与中间机器连接时,按分区后的表进行连接,从而节省了大量数据传输开销。

 

分区的原则:

分区的个数 尽量等于 集群中CPU核心数目,每个分区启动一个线程

对于不同的spark部署模式而言,可通过设置具体参数值,来配置默认的分区数目,参数名为spark.default.parallelism。

一般而言,local模式,默认为本地机器的CPU数目,若设置了local[N],则默认为N;

对于Apache Mesos模式,默认分区数目为8;

对于Standalone模式和YARN模式,是将集群中所有CPU核心数目总和与2之间取较大值作为分区的默认数目。

 

如何设置分区个数?

创建时手动指定分区个数:在调用textFile()和parallelize()方式时,可以人工的设定它的分区个数。

 

自定义分区

spark有哈希分区(HashPartitioner)、区域分区(RangePartitioner)以及自定义分区,自定义分区有时候可进一步减少通信开销,那如何自定义分区呢?

现有实例如下:

要实现如上的分区,需要自定义分区的函数:

.partitionBy是一个重分区的方法,其中参数10表示将要分区的分区个数,MyPartitioner是我们自定义的分区类。partitionBy只接受键值对类型,根据键值对中键进行分区。

 

6、综合案例(词频统计)

代码如下(单机):

代码运行过程:

    

多机并行执行

此时需要一个集群进行词频统计,将Hadoop和spark同时部署在同一个集群里面,我们将集群当中的某个节点既作为HDFS的存储节点,也作为Spark的worknode,工作节点,即Hadoop的存储组件和Spark的计算组件是放在了同一台机器上的,如上图所示。如此则可以让Spark对保存在HDFS当中的词频文件进行并行的词频统计,最终将结果进行汇总。

下图详细描述了分布式词频统计的过程。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值