摸鱼大数据——Spark Core——RDD的基本介绍和如何构建RDD

1、什么是RDD

RDD:英文全称Resilient Distributed Dataset,叫做弹性分布式数据集,代表一个不可变、可分区、里面的元素可并行计算的分布式的抽象的数据集合。

  • Resilient弹性:RDD的数据可以存储在内存或者磁盘当中,RDD的数据可以分区

  • Distributed分布式:RDD的数据可以分布式存储,可以进行并行计算

  • Dataset数据集:一个用于存放数据的集合

2、RDD的五大特性

1、(必须的)RDD是由一系列分区组成的
2、(必须的)对RDD做计算,相当于对RDD的每个分区做计算
3、(必须的)RDD之间存在着依赖关系(宽依赖和窄依赖)
4、(可选的)对于KV类型的RDD,默认操作的是k,当然我们可以进行自定义分区方案
5、(可选的)移动数据不如移动计算,让计算程序离数据越近越好

3、RDD的五大特点

1、分区:RDD逻辑上是分区的,仅仅是定义分区的规则,并不是直接对数据进行分区操作,因为RDD本身不存储数据。
2、只读:RDD是只读的,要想改变RDD中的数据,只能在现有的RDD基础上创建新的RDD。
3、依赖:RDD之间存在着依赖关系(宽依赖和窄依赖)
4、cache缓存:如果在应用程序中多次使用同一个RDD,可以将该RDD缓存起来,该RDD只有在第一次计算的时候会根据血缘关系得到分区的数据,后续每次直接从缓存获取即可
5、checkpoint检查点:与缓存类似的,都是可以将中间某一个RDD的结果保存起来,只不过checkpoint支持真正持久化保存

如何构建RDD

构建RDD对象的方式主要有两种:

1、通过 parallelize(data): 通过自定义列表的方式初始化RDD对象。(一般用于测试)
2、通过 textFile(data): 通过读取外部文件的方式来初始化RDD对象,实际工作中经常使用。

1、并行化本地集合方式

黑窗口中实现:

开发工具实现:

# 导包
import os
from pyspark import SparkConf, SparkContext
​
# 绑定指定的python解释器
os.environ['SPARK_HOME'] = '/export/server/spark'
os.environ['PYSPARK_PYTHON'] = '/root/anaconda3/bin/python3'
os.environ['PYSPARK_DRIVER_PYTHON'] = '/root/anaconda3/bin/python3'
​
# 创建main函数
if __name__ == '__main__':
    # 1.创建SparkContext对象
    conf = SparkConf().setAppName('pyspark_demo').setMaster('local[3]')
    sc = SparkContext(conf=conf)
​
    # 2.数据输入
    # 3.数据处理(切分,转换,分组聚合)
    d = [1, 2, 3, 4]
    rdd = sc.parallelize(d,numSlices=1)
    # 4.数据输出
    print(rdd.collect())
    # 6.分区演示
    # 获取分区数
    print(rdd.getNumPartitions())
    # 获取各个分区数据
    print(rdd.glom().collect())
​
    # 5.关闭资源
    sc.stop()
​

相关的API:

# parallelize(参数1,参数2)
使用本地数据构建RDD。参数1:本地数据列表;参数2:可选的,表示有多少个分区
​
# getNumPartitions
查看RDD的分区数量
​
# glom
查看每个分区的数据内容

修改分区数,效果:

1- 默认和setMaster('local[num]')中的num数量有关。如果是*,就是和机器的CPU核数相同。另外可以指定具体的数字,数字是多少,那么分区数就是多少
​
2- parallelize()中第二个参数numSlices可以手动指定RDD的分区数。如果同时设置了local和numSlices,numSlices的优先级高一些

2、读取外部数据源方式

TextFile API的方式实现:

# 导包
import os
from pyspark import SparkConf, SparkContext
​
# 绑定指定的python解释器
os.environ['SPARK_HOME'] = '/export/server/spark'
os.environ['PYSPARK_PYTHON'] = '/root/anaconda3/bin/python3'
os.environ['PYSPARK_DRIVER_PYTHON'] = '/root/anaconda3/bin/python3'
​
# 创建main函数
if __name__ == '__main__':
    # 1.创建SparkContext对象
    conf = SparkConf().setAppName('pyspark_demo').setMaster('local[3]')
    sc = SparkContext(conf=conf)
​
    # 2.数据输入
    # 3.数据处理(切分,转换,分组聚合)
    # 注意: 如果要提交到yarn,文件建议使用hdfs路径
    rdd = sc.textFile('hdfs://node1:8020/source/c1.txt',minPartitions=1)
    # 4.数据输出
    print(rdd.collect())
    # 6.分区演示
    # 获取分区数
    print(rdd.getNumPartitions())
    # 获取各个分区数据
    print(rdd.glom().collect())
​
    # 5.关闭资源
    sc.stop()
​

修改分区数,效果:

到底有多少个分区,一切以getNumPartitions结果为准
​
分区数据量,当调大local[num]中num的值时候,不生效;调小的时候生效
​
同时也受minPartitions影响

3、处理小文件的操作

wholeTextFiles: wholeTextFiles既能直接读取文件,也能读取一个目录下的所有小文件
# 导包
import os
from pyspark import SparkConf, SparkContext

# 绑定指定的python解释器
os.environ['SPARK_HOME'] = '/export/server/spark'
os.environ['PYSPARK_PYTHON'] = '/root/anaconda3/bin/python3'
os.environ['PYSPARK_DRIVER_PYTHON'] = '/root/anaconda3/bin/python3'

# 创建main函数
if __name__ == '__main__':
    # 1.创建SparkContext对象
    conf = SparkConf().setAppName('pyspark_demo').setMaster('local[10]')
    sc = SparkContext(conf=conf)

    # 2.数据输入
    # 3.数据处理(切分,转换,分组聚合)
    # 注意: 如果要提交到yarn,文件建议使用hdfs路径
    # 注意: wholeTextFiles既能直接读取文件,也能读取一个目录下的所有小文件
    rdd = sc.wholeTextFiles('hdfs://node1:8020/source/c1.txt')
    # 4.数据输出
    print(rdd.collect())

    # 6.分区演示
    # 获取分区数
    print(rdd.getNumPartitions())
    # 获取各个分区数据
    print(rdd.glom().collect())

    # 5.关闭资源
    sc.stop()

修改分区数,效果:

wholeTextFiles: 读取小文件。
    1-支持本地文件系统和HDFS文件系统。参数minPartitions指定最小的分区数。
    2-通过该方式读取文件,会尽可能使用少的分区数,可能会将多个小文件的数据放到同一个分区中进行处理。
    3-一个文件要完整的存放在一个元组中,也就是不能将一个文件分成多个进行读取。文件是不可分割的。
    4-RDD分区数量既受到minPartitions参数的影响,同时受到小文件个数的影响

4、RDD分区数量如何确定

1- RDD的分区数量,一般设置为机器CPU核数的2-3倍。为了充分利用服务器的硬件资源

2- RDD的分区数据量受到多个因素的影响,例如:机器CPU的核数、调用的算子、算子中参数的设置、集群的类型等。RDD具体有多少个分区,直接通过getNumPartitions查看

3- 当初始化SparkContext对象的时候,其实就确定了一个参数spark.default.parallelism,默认为CPU的核数。如果是本地集群,就取决于local[num]中设置的数字大小;如果是集群,默认至少有2个分区

4- 通过parallelize来构建RDD,如果没有指定分区数,默认就取spark.default.parallelism参数值;如果指定了分区数,也就是numSlices参数,那么numSlices的优先级会更高一些,最终RDD的分区数取该参数的值。

5- 通过textFile来构建RDD
    5.1- 首先确认defaultMinPartition参数的值。该参数的值,如果没有指定textFile的minPartition参数,那么就根据公式min(spark.default.parallelism,2);如果有指定textFile的minPartition参数,那么就取设置的值
    5.2- 再根据读取文件所在的文件系统的不同,来决定最终RDD的分区数:
        5.2.1- 本地文件系统: RDD分区数 = max(本地文件分片数,defaultMinPartition)
        5.2.2- HDFS文件系统: RDD分区数 = max(文件block块的数量,defaultMinPartition)

常规处理小文件的办法: 1- 大数据框架提供的现有的工具或者命令 1.1- 合并hdfs中多个小文件到linux本地: hadoop fs -getmerge 小文件路径 linux输出路径/文件名.后缀名

举例: [root@node1 ~]# hadoop fs -getmerge /data/*.txt /merged_file.txt

1.2- 归档hdfs中多个小文件到hdfs: hadoop archive -archiveName 归档名.har -p 小文件路径 hdfs输出路径

举例: [root@node1 ~]# hadoop archive -archiveName merged_file.har -p /data/ /

2- 可以通过编写自定义的代码,将小文件读取进来,在代码中输出的时候,输出形成大的文件

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

困了就倒头睡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值