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 多个分区的kafka流行为_Apache Spark_Spark Streaming - Fatal编程技术网

Apache spark 多个分区的kafka流行为

Apache spark 多个分区的kafka流行为,apache-spark,spark-streaming,Apache Spark,Spark Streaming,我是从卡夫卡主题消费。本主题有3个分区。 我使用foreachRDD处理每个批处理RDD(使用processData方法处理每个RDD,并最终从中创建一个数据集) 现在,您可以看到我有一个count变量,我在“processData”方法中递增这个count变量,以检查我处理了多少实际记录。(我知道,每个RDD都是卡夫卡主题记录的集合,数量取决于批处理间隔大小) 现在,输出是这样的: 1 1 2 3 2 4 3 5 这使我认为这是因为我可能有3个消费者(因为我有3个分区),并且每个消费者将分别调

我是从卡夫卡主题消费。本主题有3个分区。 我使用foreachRDD处理每个批处理RDD(使用processData方法处理每个RDD,并最终从中创建一个数据集)

现在,您可以看到我有一个count变量,我在“processData”方法中递增这个count变量,以检查我处理了多少实际记录。(我知道,每个RDD都是卡夫卡主题记录的集合,数量取决于批处理间隔大小)

现在,输出是这样的:

1 1 2 3 2 4 3 5

这使我认为这是因为我可能有3个消费者(因为我有3个分区),并且每个消费者将分别调用“foreachRDD”方法,因此同一个计数被打印多次,因为每个消费者可能缓存了其计数副本

但我得到的最终输出数据集拥有所有记录

那么,Spark内部是否合并了所有数据?它是如何决定什么是联盟的? 我试图理解这种行为,以便形成我的逻辑

整数计数=0

messages.foreachRDD(new VoidFunction<JavaRDD<ConsumerRecord<K, String>>>() {
            public void call(JavaRDD<ConsumerRecord<K, V>> rdd) {
                System.out.println("NUmber of elements in RDD : "+ rdd.count());

                List<Row> rows = rdd.map(record -> processData(record))
                        .reduce((rows1, rows2) -> {
                            rows1.addAll(rows2);
                            return rows1;
                        });

                StructType schema = DataTypes.createStructType(fields);
                Dataset ds = ss.createDataFrame(rows, schema);
                ds.createOrReplaceTempView("trades");                
                ds.show();
            }
        });
messages.foreachRDD(新的VoidFunction(){
公共无效调用(JavaRDD){
System.out.println(“RDD中的元素数:+RDD.count());
列表行=rdd.map(记录->处理数据(记录))
.减少((第1行,第2行)->{
第1行。添加全部(第2行);
返回行1;
});
StructType schema=DataTypes.createStructType(字段);
Dataset ds=ss.createDataFrame(行、模式);
ds.createOrReplaceTempView(“交易”);
ds.show();
}
});

这些假设并不完全准确。
foreachRDD
是Spark Streaming中所谓的
输出操作之一。
输出操作
的功能是按照
批次间隔
规定的间隔安排提供的关闭。该闭合中的代码在火花驱动器上的每个
批次间隔执行一次。未在群集中分布

特别是,
foreachRDD
是一种通用的
输出操作
,提供对数据流中底层RDD的访问。应用于该RDD的操作将在Spark群集上执行

因此,回到原始问题的代码,在
foreachRDD
闭包中编写代码,例如
System.out.println(“RDD中的元素数:+RDD.count())在驱动程序上执行。这也是为什么我们可以在控制台中看到输出的原因。请注意,此
print
中的
rdd.count()
将触发集群上rdd的
count
,因此
count
是一个分布式操作,它向驱动程序返回一个值,然后在驱动程序上执行
print
操作

现在是RDD的转换:

rdd.map(record -> processData(record))
如前所述,应用于
RDD
的操作将在集群上执行。执行将按照Spark执行模式进行;也就是说,转换被组装成多个阶段,并应用于底层数据集的每个分区。假设我们正在处理3个卡夫卡主题,那么Spark中将有3个相应的分区。因此,
processData
将对每个分区应用一次

那么,Spark内部是否合并了所有数据?它是如何决定什么是联盟的

正如我们有Spark流的输出操作一样,我们也有Spark的操作。操作可能会对数据应用操作,并将结果提供给驱动程序。最简单的操作是
collect
,它将完整的数据集带到驱动程序中,有可能无法放入内存中。其他常见操作,
count
汇总数据集中的记录数,并向驱动程序返回单个数字

在上面的代码中,我们使用了
reduce
,这也是一个应用提供的函数并将结果数据带给驱动程序的操作。正如在问题中所表达的那样,正是使用该操作“内部合并所有数据”。在reduce表达式中,我们实际上收集了分发到单个本地集合中的所有数据。这相当于这样做:
rdd.map(record->processData(record)).collect()

如果目的是创建数据集,我们应该避免首先将所有数据“移动”到驱动程序

更好的办法是:

val rows = rdd.map(record -> processData(record))
val df = ss.createDataFrame(rows, schema);
...
在这种情况下,所有分区的数据对于它们所在的执行器来说都是本地的


请注意,应避免将数据移动到驾驶员。它的速度很慢,在大数据集的情况下,可能会导致作业崩溃,因为驱动程序通常无法保存集群中的所有可用数据。

谢谢,解释得很好。我仍然有以下疑问:->即使我们在一个kafka主题中有3个分区,我们是否仍然会在批处理间隔中得到一个RDD,并且它拥有来自所有3个分区的数据。那么为什么您会说“因此,processData将对每个分区应用一次。”?我的意思是,spark知道的唯一一件事是它有一个RDD,它没有关于kafka分区的任何信息,对吗?->您说过“我们应该避免将所有数据移动到驱动程序”:所以让我们假设我使用“收集”,所以数据将保留在集群上。现在,如果我对这个数据集执行一些SQL操作。我会从所有分区得到一个组合结果吗?@amanpretkhurana re:partitions。分区是激发内部工作的关键。无论是批处理还是流式处理。对于kafka direct consumer,Spark将为正在使用的kafka主题的每个分区创建一个RDD分区。@Amanpretkhurana re:获取数据。“收集”将向驱动程序获取所有数据。除非严格要求,否则不要使用。回复:SQL:是-如果您