Spark Streaming dropDuplicates

时间:2017-07-24 22:56:26

标签: scala hadoop apache-spark spark-streaming

Spark 2.1.1(scala api)从s3位置流式传输json文件。

我想根据每个记录在json中找到的ID列(“event_id”)对任何传入记录进行重复数据删除。我不关心保留哪条记录,即使记录的重复只是部分记录。我正在使用追加模式,因为数据仅通过spark.sql()方法进行丰富/过滤,没有按组/窗口聚合。然后我使用追加模式将镶木地板文件写入s3。

根据文档,我应该能够使用dropDuplicates而不进行水印以进行重复数据删除(显然这在长时间生产中无效)。但是,这会因错误而失败:

用户类抛出异常:org.apache.spark.sql.AnalysisException:当流式DataFrames / DataSet上有流式聚合时,不支持追加输出模式

这个错误看起来很奇怪,因为我没有进行聚合(除非dropDuplicates或sparkSQL计为聚合?)。

我知道重复项不会在3天之外发生,所以我再次尝试添加水印(在重复删除之前使用.withWatermark())。但是,在写入数据之前,它似乎要等到3天。 (即从今天到7月24日,只有7月21日同一时间的数据写入输出)。

由于没有聚合,我想在处理批处理后立即写入每一行,并简单地丢弃任何具有前3天发生的事件ID的行。有没有一种简单的方法来实现这一目标?

由于

2 个答案:

答案 0 :(得分:1)

就我而言,我曾经通过DStream以两种方式实现这一目标:

一种方式:

  1. 加载tmp_data(包含3天的唯一数据,见下文)
  2. 接收 batch_data 并使用 tmp_data
  3. 执行leftOuterJoin
  4. 在第2步执行filter并输出新的唯一数据
  5. 使用新的唯一数据通过step2的结果更新 tmp_data 并删除旧数据(超过3天)
  6. tmp_data保存在HDFS或其他任何
  7. 一遍又一遍地重复
  8. 另一种方式:

    1. 在mysql上创建一个表,并在 event_id
    2. 上设置UNIQUE INDEX
    3. 接收 batch_data ,只需将 event_id + event_time + 保存到mysql
    4. mysql将自动忽略重复

答案 1 :(得分:0)

我们使用的解决方案是org.apache.spark.sql.execution.streaming.Sink的自定义实现,它在批量删除重复项之后插入到hive表中,并对前几天的数据执行左反连接目标蜂巢表。