用法背景:

RDD(Resilient Distributed Dataset):

弹性分布式数据集,是Spark中最基本的数据处理模型;代码中是一个抽象类,它代表一个弹性的、不可变、可分区、里面的元素可并行 计算的集合。

弹性

  • 存储的弹性:内存与磁盘的自动切换;
  • 容错的弹性:数据丢失可以自动恢复;
  • 计算的弹性:计算出错重试机制;
  • 分片的弹性:可根据需要重新分片。

分布式:数据存储在大数据集群不同节点上

数据集:RDD 封装了计算逻辑,并不保存数据

数据抽象:RDD 是一个抽象类,需要子类具体实现

不可变:RDD 封装了计算逻辑,是不可以改变的,想要改变,只能产生新的 RDD,在 新的 RDD 里面封装计算逻辑

可分区、能够并行计算;

RDD 可以将数据(元素)通过分区函数 放在多个分区中,然后将这些分区 通过任务 交给不同的Exectuor去执行,从而达到并行计算的目的;

同样,多个分区 也可以在一个Executor中执行,只是无法并行执行,如下代码中的示例

aggregate/aggregateByKey 就是针对 分区内 和 分区之间 执行不同或相同函数的转换算子;

 

 

用法:

aggregate(默认值,分区内函数,分区间函数):

rdd分区内每个元素先进行聚合,然后分区间 再进行聚合;
注意: 初始值 会参与分区内和分区间的计算;

aggregateByKey(默认值,分区内函数,分区间函数):

rdd分区内 所有元素先根据key进行分组,对每组内部的值之间 先进行聚合,然后分区间 根据key 再进行聚合;
注意: 初始值 只参与分区内的计算,不参与分区间计算

 

初始值的作用: 在对rdd中的每个元素进行遍历操作时(类似for循环每个元素,并对每个元素执行一个函数操作) ,由于第一个元素在执行函数时 没有其他元素可以交互,只能给一个默认值; 如  add(第一个参数,默认值);

 

示例代码:

# -*- coding: utf-8 -*-
"""
(C) rgc
All rights reserved
create time '2021/5/26 19:37'

Usage:
aggregate 用法
aggregateByKey 用法
"""
# 构建spark
from pyspark.conf import SparkConf
from pyspark.context import SparkContext

conf = SparkConf()
# 使用本地模式;且 executor设置为1个方便debug
conf.setMaster('local[1]').setAppName('rgc')
sc = SparkContext(conf=conf)

rdd = sc.parallelize([2, 1, 3, 4, 4], 1)


def seq_func(x, y):
    """
    分区内的函数
    :param x: 指  zeroValue 参数 也就是(2,0)
    :param y: 指 具体的元素
    :return: 元素的值==> 元素的累加,元素的个数
    """
    return x[0] + y, x[1] + 1


def comb_func(x, y):
    """
    分区间的函数
    :param x: 第一个元素
    :param y: 第二个元素
    :return: 元素的值==> 分区间元素的累加结果,分区间元素的个数之和
    """
    return x[0] + y[0], x[1] + y[1]


# aggregate:rdd分区内每个元素先进行聚合,然后分区间 再进行聚合;
# 注意: 初始值 会参与分区内和分区间的计算;
# 所以 每个分区内的一次初始值(5) + 分区内的元素(2+1+3+4+4) + 分区间的一次初始值(5) = 24
rdd_res = rdd.aggregate((5, 0), seq_func, comb_func)
print(rdd_res)  # (24,5)

# aggregateByKey:rdd分区内 所有元素先根据key进行分组,对每组的值 先进行聚合,然后分区间 根据key 再进行聚合;
# 注意: 初始值 只参与分区内的计算,不参与分区间计算
rdd_res = rdd.map(lambda x: (x, 1)).aggregateByKey((1, 0), seq_func, comb_func)
print(rdd_res.collect())  # [(2, (2, 1)), (1, (2, 1)), (3, (2, 1)), (4, (3, 2))]

 

总结:

在一个RDD中,如果需要对 分区内和分区间 进行不同的操作,可以使用aggregate aggregateByKey 2种方法;

如果需要在聚合操作前根据key进行分组 则使用 aggregateByKey方法;否则使用aggregate方法;