gpt4 book ai didi

hadoop - 持久化 Spark Streaming 输出

转载 作者:可可西里 更新时间:2023-11-01 14:15:35 34 4
gpt4 key购买 nike

我正在从一个消息传递应用程序收集数据,我目前正在使用 Flume,它每天发送大约 5000 万条记录

我想用卡夫卡,使用 Spark Streaming 从 Kafka 消费并将其持久化到 hadoop 并使用 impala 进行查询

我尝试过的每种方法都有问题..

方法 1 - 将 RDD 保存为 parquet,将外部 hive parquet 表指向 parquet 目录

// scala
val ssc = new StreamingContext(sparkConf, Seconds(bucketsize.toInt))
val lines = KafkaUtils.createStream(ssc, zkQuorum, group, topicMap).map(_._2)
lines.foreachRDD(rdd => {

// 1 - Create a SchemaRDD object from the rdd and specify the schema
val SchemaRDD1 = sqlContext.jsonRDD(rdd, schema)

// 2 - register it as a spark sql table
SchemaRDD1.registerTempTable("sparktable")

// 3 - qry sparktable to produce another SchemaRDD object of the data needed 'finalParquet'. and persist this as parquet files
val finalParquet = sqlContext.sql(sql)
finalParquet.saveAsParquetFile(dir)

问题是 finalParquet.saveAsParquetFile 输出大量文件,从 Kafka 接收的 Dstream 以 1 分钟的批量大小输出 200 多个文件。它输出许多文件的原因是因为计算是分布式的,如另一篇文章- how to make saveAsTextFile NOT split output into multiple file? 中所解释的那样。

但是,建议的解决方案对我来说似乎并不是最佳的,例如正如一位用户所说 - 如果数据很少,只有一个输出文件是个好主意。

方法 2 - 使用 HiveContext。直接向 Hive 表中插入 RDD 数据

# python
sqlContext = HiveContext(sc)
ssc = StreamingContext(sc, int(batch_interval))
kvs = KafkaUtils.createStream(ssc, zkQuorum, group, {topics: 1})
lines = kvs.map(lambda x: x[1]).persist(StorageLevel.MEMORY_AND_DISK_SER)
lines.foreachRDD(sendRecord)

def sendRecord(rdd):

sql = "INSERT INTO TABLE table select * from beacon_sparktable"

# 1 - Apply the schema to the RDD creating a data frame 'beaconDF'
beaconDF = sqlContext.jsonRDD(rdd,schema)

# 2- Register the DataFrame as a spark sql table.
beaconDF.registerTempTable("beacon_sparktable")

# 3 - insert to hive directly from a qry on the spark sql table
sqlContext.sql(sql);

这很好用,它直接插入 Parquet 表,但由于处理时间超过批处理间隔时间,批处理会出现调度延迟。消费者跟不上正在生产什么,要处理的批处理开始排队。

似乎写入配置单元很慢。我试过调整批处理间隔大小,运行更多消费者实例。

总结

考虑到存在多个文件问题和写入配置单元的潜在延迟,从 Spark Streaming 持久化大数据的最佳方法是什么?其他人在做什么?

这里也有人问过类似的问题,但他对目录有问题,而不是文件太多 How to make Spark Streaming write its output so that Impala can read it?

非常感谢您的帮助

最佳答案

在解决方案#2 中,创建的文件数量可以通过每个 RDD 的分区数量来控制。

看这个例子:

// create a Hive table (assume it's already existing)
sqlContext.sql("CREATE TABLE test (id int, txt string) STORED AS PARQUET")

// create a RDD with 2 records and only 1 partition
val rdd = sc.parallelize(List( List(1, "hello"), List(2, "world") ), 1)

// create a DataFrame from the RDD
val schema = StructType(Seq(
StructField("id", IntegerType, nullable = false),
StructField("txt", StringType, nullable = false)
))
val df = sqlContext.createDataFrame(rdd.map( Row(_:_*) ), schema)

// this creates a single file, because the RDD has 1 partition
df.write.mode("append").saveAsTable("test")

现在,我猜你可以玩玩从 Kafka 提取数据的频率,以及每个 RDD 的分区数(默认情况下,你的 Kafka 主题的分区,你可以通过重新分区来减少)。

我使用的是来自 CDH 5.5.1 的 Spark 1.5,我使用 df.write.mode("append").saveAsTable("test") 或您的 SQL 得到相同的结果字符串。

关于hadoop - 持久化 Spark Streaming 输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32885825/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com