如何使用Spark Streaming流式传输kafka时重复消息?

时间:2018-02-12 04:35:26

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

我有一个案例,Kafka制作人每天发送两次数据。这些生产者从数据库/文件中读取所有数据并发送给Kafka。所以每天发送的这些消息都是重复的。我需要对消息进行重复数据删除,并使用Spark Streaming在一些持久存储中写入。在这种情况下,删除重复邮件的最佳方法是什么?

发送的重复消息是一个json字符串,时间戳字段仅更新。

注意: 我无法更改Kafka Producer只发送新数据/消息,它已经安装在客户端中机器和其他人写的。

6 个答案:

答案 0 :(得分:1)

对于重复数据删除,您需要存储有关已处理内容的信息(例如,消息的唯一ID)。

存储可以使用的消息:

  1. 火花检查站。优点:开箱即用。缺点:如果您更新应用程序的源代码,则需要清理检查点。结果,您将丢失信息。如果重复数据删除的要求不严格,解决方案可以正常工作。

  2. 任何数据库。例如,如果您在hadoop env上运行,则可以使用Hbase。对于每条消息,您都会“获取”(检查之前是否已发送过),并在真正发送时发送的数据库中标记。

答案 1 :(得分:1)

您可以将主题配置更改为compact模式。通过压缩,具有相同密钥的记录将在Kafka日志中被覆盖/更新。你只能获得Kafka钥匙的最新价值。

您可以阅读有关压缩here的更多信息。

答案 2 :(得分:0)

您可以尝试使用mapWithState。检查我的answer

答案 3 :(得分:0)

一种更简单的方法是在kafka端解决此问题。看一下kafka的Log压缩功能。如果记录具有相同的唯一密钥,它将为您删除重复记录。

https://kafka.apache.org/documentation/#compaction

答案 4 :(得分:0)

您可以使用键值数据存储区,其中的键将是除timestamp字段之外的其他字段的组合,并为实际json赋值。

在轮询记录时,将密钥和值对写入到数据存储中,该数据存储处理UPSERT(Insert + Update)或检查数据存储中是否存在该密钥,然后删除消息

if(Datastore.get(key)){ 
     // then drop
 }else { 
    //write to the datastore
    Datastore.put(key)
}

我建议您检查HBase(用于处理UPSERTS)和Redis(用于查找的内存KV数据存储)

答案 5 :(得分:0)

您是否调查过以下内容: https://spark.apache.org/docs/latest/structured-streaming-programming-guide.html#streaming-deduplication

您可以尝试使用dropDuplicates()方法。 如果需要使用多个列来确定重复项,则可以使用dropDuplicates(String [] colNames)传递它们。