如何使用Spark结构化流从Kafka读取JSON数据并将其存储到HDFS?

时间:2018-07-24 21:59:53

标签: apache-spark apache-kafka spark-structured-streaming

我正在尝试从Kafka中读取JSON消息,并将它们存储在具有Spark结构化流的HDFS中。

我遵循了示例here,并且当我的代码看起来像这样时:

                date3   tID
sID dID     
4321    5432    7/20    1234
5688    4567    9/15    7890

然后我在hdfs中获得带有二进制值的行。

df = spark \
  .read \
  .format("kafka") \
  .option("kafka.bootstrap.servers", "host1:port1,host2:port2") \
  .option("subscribe", "topic1") \
  .load()
df.selectExpr("CAST(key AS STRING)", "CAST(value AS STRING)")
df.writeStream.format("json").option("checkpointLocation", "some/hdfs/path").start(/data")

这些行将按预期连续写入,但采用二进制格式。

我发现了这篇文章:

https://databricks.com/blog/2017/04/26/processing-data-in-apache-kafka-with-structured-streaming-in-apache-spark-2-2.html

我正在尝试实现此示例:

{"value":"BINARY DATA","topic":"test_hdfs2","partition":0,"offset":3463075,"timestamp":"2018-07-24T20:51:33.655Z","timestampType":0}

但是在这里我有一个奇怪的行为。我有一个写到hdfs的小文件,其中有多个空的json行-{}

很快,作业失败,但出现以下异常:

schema = StructType().add("a", IntegerType()).add("b", StringType())
df.select( \
  col("key").cast("string"),
  from_json(col("value").cast("string"), schema))

有什么想法如何以正确的方式实现这一目标吗?

1 个答案:

答案 0 :(得分:0)

如果看到错误(在压缩批处理409(compactInterval:10)时不存在399.compact,则其明确的错误是由于找不到紧凑文件夹。基本上在spark结构化流中,每个批处理运行都会创建一个。 _spark_metadata下的compact文件夹,并且为了防止过去运行时产生大量紧凑文件的开销,它会定期尝试合并这些文件。

我认为默认值是它尝试压缩的每10个批次。因此在这里,当它运行409批次并尝试压缩其未找到前一个并失败时。一种选择是设置。这并不是真正的业务错误,仅会引发簿记错误,并防止您的应用终止将failOnDataLoss以下的内容添加为false。

spark.readStream
      .format("kafka")
      .option("kafka.bootstrap.servers", conf.servers)
      .option("subscribe", conf.topics)

      .option("failOnDataLoss",false)

使用以下属性增加压实间隔

spark.conf.set("spark.sql.streaming.fileSink.log.cleanupDelay", 60000)