Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache spark Spark聚合函数-aggregateByKey是如何工作的?_Apache Spark_Distributed Computing - Fatal编程技术网

Apache spark Spark聚合函数-aggregateByKey是如何工作的?

Apache spark Spark聚合函数-aggregateByKey是如何工作的?,apache-spark,distributed-computing,Apache Spark,Distributed Computing,假设我在3个节点上有一个分布式系统,我的数据分布在这些节点上。例如,我有一个test.csv文件,它存在于所有3个节点上,包含以下两列: **row | id, c.** --------------- row1 | k1 , c1 row2 | k1 , c2 row3 | k1 , c3 row4 | k2 , c4 row5 | k2 , c5 row6 | k2 , c6 row7 | k3 , c7 row8 | k3 , c8 r

假设我在3个节点上有一个分布式系统,我的数据分布在这些节点上。例如,我有一个test.csv文件,它存在于所有3个节点上,包含以下两列:

**row   | id,  c.**
---------------
row1  | k1 , c1  
row2  | k1 , c2  
row3  | k1 , c3  
row4  | k2 , c4  
row5  | k2 , c5  
row6  | k2 , c6  
row7  | k3 , c7  
row8  | k3 , c8  
row9  | k3 , c9  
row10 | k4 , c10   
row11 | k4 , c11  
row12 | k4 , c12 
然后我使用SparkContext.textFile将文件读取为rdd,依此类推。据我所知,每个spark worker节点都将从文件中读取a部分。现在让我们假设每个节点将存储:

  • 节点1:第1~4行
  • 节点2:第5~8行
  • 节点3:第9~12行
我的问题是,假设我想对这些数据进行计算,有一个步骤我需要将键分组在一起,因此键值对应该是
[k1[{k1 c1}{k1 c2}{k1 c3}]]..
等等

有一个名为
groupByKey()
的函数,使用成本非常高,建议使用
aggregateByKey()
。所以我想知道
groupByKey()
aggregateByKey()
在引擎盖下是如何工作的?有人能用我上面提供的例子来解释吗?洗牌后,每个节点上的行位于何处?

aggregateByKey()
reduceByKey()
几乎相同(都在幕后调用
combineByKey()
),除了您为
aggregateByKey()
提供一个起始值之外。大多数人都熟悉
reduceByKey()
,因此我将在解释中使用它

之所以
reduceByKey()
好得多,是因为它使用了称为组合器的MapReduce功能。任何像
+
*
这样的函数都可以以这种方式使用,因为调用它的元素的顺序并不重要。这允许Spark使用相同的键开始“减少”值,即使它们还不在同一分区中

另一方面,
groupByKey()
为您提供了更多的通用性,因为您编写了一个接受Iterable的函数,这意味着您甚至可以将所有元素拉入一个数组。但是,它的效率很低,因为要使它工作,全套
(K,V,)
对必须在一个分区中

在reduce类型操作中移动数据的步骤通常称为shuffle,在最简单的级别上,数据被分区到每个节点(通常使用散列分区器),然后在每个节点上排序。

aggregateByKey()与reduceByKey有很大不同。发生的事情是reduceByKey是aggregateByKey的一种特殊情况

aggregateByKey()将组合特定键的值,这种组合的结果可以是您指定的任何对象。您必须指定如何在一个分区(在同一节点中执行)内组合(“添加”)值,以及如何组合来自不同分区(可能在不同节点中)的结果。reduceByKey是一种特殊情况,因为组合的结果(例如总和)与值的类型相同,并且从不同分区组合时的操作也与在分区内组合值时的操作相同

例如: 假设您有一个配对列表。您可以将其并行化:

val pairs = sc.parallelize(Array(("a", 3), ("a", 1), ("b", 7), ("a", 5)))
现在您需要通过键生成一个和来“组合”它们。在这种情况下,reduceByKey和aggregateByKey是相同的:

val resReduce = pairs.reduceByKey(_ + _) //the same operation for everything
resReduce.collect
res3: Array[(String, Int)] = Array((b,7), (a,9))

//0 is initial value, _+_ inside partition, _+_ between partitions
val resAgg = pairs.aggregateByKey(0)(_+_,_+_)
resAgg.collect
res4: Array[(String, Int)] = Array((b,7), (a,9))
现在,假设您希望聚合是一组值,这是一种与值不同的类型,它们是整数(整数之和也是整数):


好的,让我们回到我的例子,如果节点1有第1行到第3行,节点2有第4行到第6行,节点3有第7行到第12行。当我使用groupByKey时,数据是否会四处移动,或者不会移动,因为具有相同键的rdd已经在同一节点上了?thanks@EdwinGuo不,数据仍然可以移动,假设您使用的是散列分区器,如果所有k1都在节点1上,但k1的散列分区器结果是3,它仍将转到第三个节点,但如果我不关心顺序,我只想返回一个包含所有值的数组,就像groupByKey一样。除了groupbykey之外,还有其他语法吗?@AdrianoalMeda如果你甚至不想将相同的键放入同一个数组中,你可以使用glomVery详细回答这两个键是如何工作的,非常感谢!你能不能也发一个java代码,scala很难理解
import scala.collection.mutable.HashSet
//the initial value is a void Set. Adding an element to a set is the first
//_+_ Join two sets is the  _++_
val sets = pairs.aggregateByKey(new HashSet[Int])(_+_, _++_)
sets.collect
res5: Array[(String, scala.collection.mutable.HashSet[Int])]  =Array((b,Set(7)), (a,Set(1, 5, 3)))