Spark 中 RDD 的诞生:原理、操作与分区规则
Spark 的介绍与搭建:从理论到实践-CSDN博客
Spark 的Standalone集群环境安装与测试-CSDN博客
PySpark 本地开发环境搭建与实践-CSDN博客
Spark 程序开发与提交:本地与集群模式全解析-CSDN博客
Spark on YARN:Spark集群模式之Yarn模式的原理、搭建与实践-CSDN博客
目录
一、RDD 的诞生
(一)数据处理的需求与挑战
(二)RDD 的应运而生
二、RDD 的设计及定义
(一)解决的问题
(二)定义解读
三、理解 WordCount 中的 RDD 设计
(一)WordCount 示例与 RDD 的关系
(二)RDD 在 WordCount 中的优势体现
四、RDD 的五大特性
(一)每个RDD都由一系列的分区构成
(二)RDD的转换操作本质上是对RDD所有分区的并行转换
(三)每个RDD都会保存与其他RDD之间的依赖关系:血链机制或者血脉机制
(四)可选的,如果是二元组【KV】类型的RDD,在Shuffle过程中可以自定义分区器。
(五)可选的,Spark程序运行时,Task的分配可以指定实现本地优先计算:最优计算位置.
总结
五、RDD 的创建的两种方式
(一)方式一:并行化一个已存在的集合
parallelize 方法介绍
分区的意义和作用
(二)方式二:读取外部共享存储系统
textFile、wholeTextFile、newAPIHadoopRDD 等方法
与外部存储系统的交互优势
六、RDD 分区的设定规则
(一)分区数的决定因素
(二)分区的优化策略
七、总结
在大数据处理领域,Spark 已经成为了一个极具影响力的框架。而 RDD(Resilient Distributed Dataset)作为 Spark 的核心数据结构,是理解和高效使用 Spark 的关键。本文将深入探讨 RDD 的相关知识,包括它的诞生背景、设计与定义、在 WordCount 中的应用、五大特性、创建方式以及分区的设定规则等内容,希望能帮助读者更好地掌握 Spark 中 RDD 的使用。
一、RDD 的诞生
(一)数据处理的需求与挑战
当我们处理大规模数据时,传统的数据结构如列表(list)存在很大的局限性。例如,在读取数据的场景中,我们可能会有如下代码:
# step1:读取数据
input = sc.textFile("输入路径")
这里的input
需要一种特殊的数据类型来表示。它既要像集合一样能容纳数据,又要能够处理数据分布在不同服务器上的情况。如果使用list
,由于list
数据只能存储在一台服务器的内存中,无法利用多台服务器的内存来存储大规模分布式数据,所以无法满足需求。
(二)RDD 的应运而生
为了上述这个问题,RDD(弹性分布式数据集)诞生了。它是一种全新的数据类型,能够很好地满足既能表示集合,又能体现分布式存储和处理的要求。例如在后续的数据处理和保存过程中:
# step2:处理数据
result = input.具体的处理逻辑【map、flatMap、filter、reduceByKey等】
# step3:保存结果
result.saveAsTextFile("输出路径")
这里的result
也是分布在不同服务器上的数据,RDD 为这种分布式数据的处理和存储提供了合适的解决方案。
二、RDD 的设计及定义
(一)解决的问题
RDD 解决了在分布式环境下处理大规模数据的难题。它的全称 Resilient Distributed Dataset,从这个英文名称可以看出它的几个关键特性。
弹性 分布式 数据集
(二)定义解读
- 弹性(Resilient)
RDD 具有弹性,这意味着它能够在部分数据丢失或节点故障的情况下自动恢复。例如,在集群中某个节点出现故障时,Spark 可以根据 RDD 的依赖关系重新计算丢失的数据,保证数据处理的连续性和正确性。 - 分布式(Distributed)
数据分布在集群中的多个节点上。这使得 RDD 可以利用多台服务器的资源来存储和处理数据,大大提高了数据处理的规模和效率。与传统的单机数据结构相比,分布式的特性使得 RDD 能够处理海量的数据。 - 数据集(Dataset)
它本质上是一个数据集,可以包含各种类型的数据,如文本数据、数值数据等。用户可以对这个数据集进行各种操作,如转换、过滤、聚合等操作。
弹性分布式数据集,获取RDD有两种方式
1) 将一个现有的集合,丢进去,变为一个分布式的RDD
2) 读取外部数据,变为RDD
三、理解 WordCount 中的 RDD 设计
(一)WordCount 示例与 RDD 的关系
WordCount 是大数据处理中的一个经典案例。在 WordCount 程序中,RDD 的设计起着至关重要的作用。通过将文本数据转换为 RDD,我们可以利用 RDD 的分布式特性和丰富的操作方法来高效地统计单词的出现次数。
例如,首先将输入的文本文件读取为 RDD,然后通过一系列的转换操作(如flatMap
将每行文本拆分成单词、map
操作将单词转换为(单词, 1)
的键值对形式、reduceByKey
对相同单词的计数进行累加)来实现 WordCount 的功能。整个过程充分利用了 RDD 的分布式计算能力,使得 WordCount 可以在大规模文本数据上快速运行。
input_rdd:读取到的数据的RDD
filter_rdd:经过filter处理以后的数据的RDD
flatMap_rdd:经过flatMap处理以后的数据的RDD
map_rdd:经过map处理以后的数据的RDD
rs_rdd:经过reduceByKey处理以后的结果的RDD
(二)RDD 在 WordCount 中的优势体现
在 WordCount 中使用 RDD 的优势在于它能够并行处理数据。由于数据分布在不同的服务器上,多个节点可以同时对数据进行处理,大大缩短了处理时间。而且 RDD 的容错机制保证了在处理过程中即使出现节点故障等问题,也能正确地完成 WordCount 任务。
四、RDD 的五大特性
(一)每个RDD都由一系列的分区构成
RDD是逻辑,每个RDD在物理上都可以对应着多个分区的数据,每个分区的数据可以存储在不同的节点上
rdd1
||
part0: 1 2 3 4 -> bigdata01
part1: 5 6 7 8 -> bigdata02
(二)RDD的转换操作本质上是对RDD所有分区的并行转换
转换数据:rdd2 = rdd1.map(lambda x: x*2)
rdd1
||
part0: 1 2 3 4 -> bigdata01 -> Task0 -> x * 2 -> part0: 2 4 6 8
part1: 5 6 7 8 -> bigdata02 -> Task1 -> x * 2 -> part1: 10 12 14 16
||
rdd2
(三)每个RDD都会保存与其他RDD之间的依赖关系:血链机制或者血脉机制
第一个问题:软件在设计时是怎么保证数据的安全性?
方案一:副本机制:将数据存储多份,每一份存在不同的节点上【内存一般不建议使用副本,内存小,而且易丢失】 hdfs
方案二:操作日志:记录内存的所有变化追加到一个日志文件中,可以通过日志文件进行恢复【日志数据量太大,恢复部分数据性能特别差】 namenode、redis
方案三:依赖关系:记录所有数据的来源,当数据丢失的时候,基于数据来源重新构建一份 spark第二个问题:RDD的数据都是放在内存中,如果计算过程中RDD的数据在内存中丢失了,怎么解决,能够恢复内存中的数据?
RDD的算子实行Lazy模式,就是不到最后一个行为算子,整个算子的链条不执行。
在整个所有RDD构建过程中,Driver会记录每个RDD的来源【与其他RDD之间的关系:血脉】
其中任何一个RDD的数据如果丢失,都可以通过血脉重新构建这个RDD的数据
例如:如果rdd5在打印过程中内存中丢了一个分区的数据,会根据rdd5的血脉来恢复rdd5的数据第三个问题:血脉机制保证了RDD的安全性,RDD第一次构建或者RDD数据丢失,都会通过血脉构建RDD的数据,但是如果一个RDD被使用多次,这个RDD也会通过血脉构建多次,会影响程序的性能,怎么解决这个问题? checkpoint 等机制
(四)可选的,如果是二元组【KV】类型的RDD,在Shuffle过程中可以自定义分区器。
假如不是二元组的数据类型,自然就不会有什么shuffle了。
在MR程序中,有一个自定义分区器。
Spark中自带了两种分区器
HashPartition:根据Key的Hash值取模分区个数来决定进入哪个分区,大部分默认使用的
RangePartition:范围分区器,一般很少用到
分区规则选择
HashPartition:优点-只要Key相同,一定会进入同一个分区,缺点-容易导致数据倾斜
RangePartition随机分区:优点-随机的,相对均衡,不会倾斜,缺点-相同的Key不一定在同一个分区。
(五)可选的,Spark程序运行时,Task的分配可以指定实现本地优先计算:最优计算位置.
使用最优路径方案:如果说Task就在数据所在的机器运行,效率是最高的
Spark 是怎么做到这一点的,或者说如何做到这一点?
PROCESS_LOCAL:Task直接运行在数据所在的Executor中
NODE_LOCAL:Task分配在与数据同机器的其他Executor中
RACK_LOCAL:Task分配在于数据同机架的不同机器的Executor中
NO_PREF:不做最优配置
总结
RDD的五大特性分别是什么?
a. 每个RDD都可以由多个分区构成
b. 对RDD转换处理本质上是对RDD所有分区的并行转换处理
c. 对每个RDD都会保留与其他RDD之间的依赖关系:血脉机制
d. 可选的,对于KV结构的RDD,在经过Shuffle时,可以干预分区规则,默认是Hash分区
e. 可选的,Spark分配Task时会优先本地计算,尽量将Task分配到数据所在的节点
五、RDD 的创建的两种方式
(一)方式一:并行化一个已存在的集合
parallelize 方法介绍
在 Python 中,可以使用parallelize
方法将一个已存在的集合转换为 RDD。例如:
# 方式一:将一个已存在的集合转换为RDD
# 创建一个列表:会在Driver内存中构建
data = [1,2,3,4,5,6,7,8,9,10]
# 将列表转换为RDD:将在多个Executor内存中实现分布式存储, numSlices用于指定分区数,所谓的分区就是分为几份,每一份放在一台电脑上
list_rdd = sc.parallelize(data,numSlices=2)
# 打印这个RDD的内容
list_rdd.foreach(lambda x: print(x))
这里的parallelize
方法将本地的data
列表转换为了分布式的 RDD。numSlices
参数决定了分区的数量,合理设置分区数可以根据集群的资源情况优化数据处理效率。
分区的意义和作用
分区使得数据可以在多个 Executor 上并行处理。每个分区可以被看作是一个独立的数据子集,不同的分区可以在不同的节点上同时进行计算。这样可以充分利用集群的计算资源,提高数据处理速度。
(二)方式二:读取外部共享存储系统
textFile、wholeTextFile、newAPIHadoopRDD 等方法
通过textFile
、wholeTextFile
、newAPIHadoopRDD
等方法可以读取外部存储系统的数据并转换为 RDD。例如:
# 方式二:读取外部系统
# 读取文件的数据变成RDD,minPartitions用于指定最小分区数
file_rdd =sc.textFile("../datas/function_data/filter.txt", minPartitions=2)
# 输出文件的内容
file_rdd.foreach(lambda line: print(line))
这种方式可以直接从外部存储(如 HDFS、本地文件系统等)读取数据,并将其转换为 RDD。minPartitions
参数指定了最小分区数,Spark 会根据数据大小和这个参数来确定实际的分区情况。
与外部存储系统的交互优势
通过读取外部存储系统,Spark 可以处理存储在不同位置的大规模数据。这种方式使得 Spark 能够与现有的数据存储架构很好地集成,方便地处理各种来源的数据,如日志文件、数据库备份等。
六、RDD 分区的设定规则
(一)分区数的决定因素
- 读取数据时的参数设置
当读取数据创建 RDD 时,如file_rdd =sc.textFile(name="../datas/wordcount/word.txt",minPartitions=2)
,minPartitions
参数会影响分区数。Spark 会根据这个参数和数据的大小、特性等来确定分区的数量。如果数据量较大,适当增加minPartitions
的值可以提高并行度,加快数据处理速度。 - 其他影响因素
除了参数设置外,数据的分布情况、集群的资源(如节点数量、内存大小等)也会对分区数产生影响。例如,如果集群中有更多的节点和内存资源,可以增加分区数以充分利用这些资源。同时,如果数据在存储系统中本身有一定的分区结构,Spark 也可能会参考这种结构来确定 RDD 的分区。
(二)分区的优化策略
- 根据数据量调整分区数
对于大规模数据,增加分区数可以提高并行处理能力。但分区数也不是越多越好,过多的分区可能会导致任务调度开销增加。需要根据数据量和集群资源找到一个合适的平衡点。例如,可以通过一些实验和性能测试来确定最佳的分区数。 - 考虑数据本地性和计算资源平衡
在设置分区数时,要考虑数据本地性。尽量保证每个分区的数据在处理时能够在本地节点或者附近节点上进行计算,减少数据传输。同时,也要平衡各个节点的计算资源分配,避免某些节点负载过重而其他节点闲置的情况。
七、总结
本文详细介绍了 Spark 中 RDD 的诞生背景、设计定义、在 WordCount 中的应用、五大特性、创建方式以及分区设定规则等内容。RDD 作为 Spark 的核心数据结构,为分布式数据处理提供了强大的支持。通过合理地创建和使用 RDD,利用其特性和分区规则,可以在 Spark 平台上高效地处理大规模数据。在实际应用中,需要根据数据的特点和集群的资源情况来优化 RDD 的使用,以充分发挥 Spark 的优势,实现高效、可靠的数据处理任务。无论是处理文本数据、数值数据还是其他类型的大规模数据,深入理解 RDD 都是掌握 Spark 数据处理能力的关键所在。希望本文能为读者在学习和使用 Spark 中的 RDD 时提供有益的指导和帮助,让读者能够在大数据处理领域中更好地运用 Spark 框架来解决实际问题。