解释
下面是转载的一篇程序员给妻子讲解什么是MapReduce的对话,看完能大概明白
我问妻子:“你真的想要弄懂什么是MapReduce?” 她很坚定的回答说“是的”。 因此我问道:
我:你是如何准备洋葱辣椒酱的?(以下并非准确食谱,请勿在家尝试)
妻子:我会取一个洋葱,把它切碎,然后拌入盐和水,最后放进混合研磨机里研磨。这样就能得到洋葱辣椒酱了。
妻子:但这和MapReduce有什么关系?
我:你等一下。让我来编一个完整的情节,这样你肯定可以在15分钟内弄懂MapReduce.
妻子:好吧。
我:现在,假设你想用薄荷、洋葱、番茄、辣椒、大蒜弄一瓶混合辣椒酱。你会怎么做呢?
妻子:我会取薄荷叶一撮,洋葱一个,番茄一个,辣椒一根,大蒜一根,切碎后加入适量的盐和水,再放入混合研磨机里研磨,这样你就可以得到一瓶混合辣椒酱了。
我:没错,让我们把MapReduce的概念应用到食谱上。Map和Reduce其实是两种操作,我来给你详细讲解下。
Map(映射): 把洋葱、番茄、辣椒和大蒜切碎,是各自作用在这些物体上的一个Map操作。所以你给Map一个洋葱,Map就会把洋葱切碎。 同样的,你把辣椒,大蒜和番茄一一地拿给Map,你也会得到各种碎块。 所以,当你在切像洋葱这样的蔬菜时,你执行就是一个Map操作。 Map操作适用于每一种蔬菜,它会相应地生产出一种或多种碎块,在我们的例子中生产的是蔬菜块。在Map操作中可能会出现有个洋葱坏掉了的情况,你只要把坏洋葱丢了就行了。所以,如果出现坏洋葱了,Map操作就会过滤掉坏洋葱而不会生产出任何的坏洋葱块。
Reduce(化简):在这一阶段,你将各种蔬菜碎都放入研磨机里进行研磨,你就可以得到一瓶辣椒酱了。这意味要制成一瓶辣椒酱,你得研磨所有的原料。因此,研磨机通常将map操作的蔬菜碎聚集在了一起。
妻子:所以,这就是MapReduce?
我:你可以说是,也可以说不是。 其实这只是MapReduce的一部分,MapReduce的强大在于分布式计算。
妻子:分布式计算? 那是什么?请给我解释下吧。
我:没问题。
我:假设你参加了一个辣椒酱比赛并且你的食谱赢得了最佳辣椒酱奖。得奖之后,辣椒酱食谱大受欢迎,于是你想要开始出售自制品牌的辣椒酱。假设你每天需要生产10000瓶辣椒酱,你会怎么办呢?
妻子:我会找一个能为我大量提供原料的供应商。
我:是的..就是那样的。那你能否独自完成制作呢?也就是说,独自将原料都切碎? 仅仅一部研磨机又是否能满足需要?而且现在,我们还需要供应不同种类的辣椒酱,像洋葱辣椒酱、青椒辣椒酱、番茄辣椒酱等等。
妻子:当然不能了,我会雇佣更多的工人来切蔬菜。我还需要更多的研磨机,这样我就可以更快地生产辣椒酱了。
我:没错,所以现在你就不得不分配工作了,你将需要几个人一起切蔬菜。每个人都要处理满满一袋的蔬菜,而每一个人都相当于在执行一个简单的Map操作。每一个人都将不断的从袋子里拿出蔬菜来,并且每次只对一种蔬菜进行处理,也就是将它们切碎,直到袋子空了为止。
这样,当所有的工人都切完以后,工作台(每个人工作的地方)上就有了洋葱块、番茄块、和蒜蓉等等。
妻子:但是我怎么会制造出不同种类的番茄酱呢?
我:现在你会看到MapReduce遗漏的阶段—搅拌阶段。MapReduce将所有输出的蔬菜碎都搅拌在了一起,这些蔬菜碎都是在以key为基础的 map操作下产生的。搅拌将自动完成,你可以假设key是一种原料的名字,就像洋葱一样。 所以全部的洋葱keys都会搅拌在一起,并转移到研磨洋葱的研磨器里。这样,你就能得到洋葱辣椒酱了。同样地,所有的番茄也会被转移到标记着番茄的研磨器里,并制造出番茄辣椒酱。
作者:永远的冷冽 | 链接:https://www.jianshu.com/p/c2affdca8ed8 | 来源:简书
对应修饰符
理解了spark中map和reduce的含义,那么在pyspark代码中,哪些修饰符操作分别要进行map或reduce呢?
在 PySpark 中,map 和 reduce 操作的概念来自于函数式编程中的 MapReduce 模型。虽然 PySpark 提供了许多高级操作符,但它们本质上都可以归类为 map 或 reduce 操作。
Map 操作
map 操作是对每个元素应用一个函数,并返回一个新的 RDD。以下是一些常见的 map 操作:
• map(func):
• 对 RDD 中的每个元素应用 func 函数,并返回一个新的 RDD。
• 示例:
rdd = sc.parallelize([1, 2, 3, 4])
mapped_rdd = rdd.map(lambda x: x * 2)
print(mapped_rdd.collect()) # 输出: [2, 4, 6, 8]
• flatMap(func):
• 对 RDD 中的每个元素应用 func 函数,但 func 返回的是一个列表,然后将所有列表中的元素展平成一个 RDD。
• 示例:
rdd = sc.parallelize(["hello world", "hi there"])
flat_mapped_rdd = rdd.flatMap(lambda x: x.split())
print(flat_mapped_rdd.collect()) # 输出: ['hello', 'world', 'hi', 'there']
• filter(func):
• 对 RDD 中的每个元素应用 func 函数,返回一个只包含满足条件的元素的新 RDD。
• 示例:
rdd = sc.parallelize([1, 2, 3, 4, 5])
filtered_rdd = rdd.filter(lambda x: x % 2 == 0)
print(filtered_rdd.collect()) # 输出: [2, 4]
• union(other):
• 返回两个 RDD 的并集。
• 示例:
rdd1 = sc.parallelize([1, 2, 3])
rdd2 = sc.parallelize([3, 4, 5])
union_rdd = rdd1.union(rdd2)
print(union_rdd.collect()) # 输出: [1, 2, 3, 3, 4, 5]
Reduce 操作
reduce 操作是对 RDD 中的所有元素应用一个函数,最终返回一个单一的结果。以下是一些常见的 reduce 操作:
• reduce(func):
• 对 RDD 中的所有元素应用 func 函数,最终返回一个单一的结果。
• 示例:
rdd = sc.parallelize([1, 2, 3, 4])
result = rdd.reduce(lambda x, y: x + y)
print(result) # 输出: 10
• fold(zero_value, func):
• 类似于 reduce,但提供了一个初始值 zero_value。
• 示例:
rdd = sc.parallelize([1, 2, 3, 4])
result = rdd.fold(0, lambda x, y: x + y)
print(result) # 输出: 10
• aggregate(zero_value, seq_op, comb_op):
• 更通用的聚合操作,适用于更复杂的聚合逻辑。
• 示例:
rdd = sc.parallelize([1, 2, 3, 4])
result = rdd.aggregate(
(0, 0), # 初始值 (sum, count)
lambda acc, value: (acc[0] + value, acc[1] + 1), # 序列操作
lambda acc1, acc2: (acc1[0] + acc2[0], acc1[1] + acc2[1]) # 合并操作
)
print(result) # 输出: (10, 4)
• groupByKey():
• 对键值对 RDD 中的键进行分组,返回一个包含每个键及其对应值的迭代器的 RDD。
• 示例:
rdd = sc.parallelize([("a", 1), ("b", 2), ("a", 3)])
grouped_rdd = rdd.groupByKey().mapValues(list)
print(grouped_rdd.collect()) # 输出: [('a', [1, 3]), ('b', [2])]
• reduceByKey(func):
• 对键值对 RDD 中的每个键应用 func 函数,返回一个包含每个键及其聚合值的 RDD。
• 示例:
rdd = sc.parallelize([("a", 1), ("b", 2), ("a", 3)])
reduced_rdd = rdd.reduceByKey(lambda x, y: x + y)
print(reduced_rdd.collect()) # 输出: [('a', 4), ('b', 2)]
• join(other):
• 对两个键值对 RDD 进行内连接,返回一个包含共同键及其对应值的 RDD。
• 示例:
rdd1 = sc.parallelize([("a", 1), ("b", 2)])
rdd2 = sc.parallelize([("a", 3), ("c", 4)])
joined_rdd = rdd1.join(rdd2)
print(joined_rdd.collect()) # 输出: [('a', (1, 3))]
总结
• Map 操作:对每个元素应用一个函数,返回一个新的 RDD。常见的操作包括 map、flatMap、filter、union 等。
• Reduce 操作:对 RDD 中的所有元素应用一个函数,最终返回一个单一的结果。常见的操作包括 reduce、fold、aggregate、groupByKey、reduceByKey、join 等。