版本冲突,当前版本[2]与提供的版本[1]不同

时间:2019-01-31 14:24:37

标签: java apache-spark elasticsearch apache-kafka

我有一个Kafka主题和一个Spark应用程序。 Spark应用程序从Kafka主题获取数据,对其进行预聚合并将其存储在Elastic Search中。听起来很简单,对吧?

一切正常,但在我将“ spark.cores”属性设置为1之外的那一刻,我开始获得

version conflict, current version [2] is different than the one provided [1]

经过一些研究,我认为错误是因为多个内核可以同时具有相同的文档,因此,当一个内核完成聚合并尝试写回文档时,会收到此错误

TBH,我对此行为感到有些惊讶,因为我认为Spark和ES会自己处理。这使我相信,也许我的方法有问题。

我该如何解决?我需要遵循某种“同步”或“锁定”概念吗?

干杯!

2 个答案:

答案 0 :(得分:3)

听起来您队列中有几条消息都更新了同一ES文档,并且这些消息正在同时处理。有两种可能的解决方案:

首先,您可以使用Kafka分区来确保按顺序处理所有更新同一ES文档的消息。假设您的邮件中有一些属性,Kafka可以使用该属性来确定邮件如何映射到ES文档。

另一种方法是处理乐观并发冲突的标准方法:重试事务。如果您需要从Kafka消息中获取一些数据,并且需要将它们添加到ES文档中,并且ES中的当前文档为版本1,则可以尝试对其进行更新并保存回版本2。但是,如果其他人已经编写了版本2, ,您可以通过以版本2为起点重试,添加新数据并保存版本3。

如果这些方法都破坏了您期望从Kafka和Spark获得的并发性,那么您可能需要重新考虑您的方法。您可能必须引入一个新的处理阶段,该阶段虽然繁重但实际上并未写入ES,然后在单独的步骤中进行ES更新。

答案 1 :(得分:0)

我想回答我自己的问题。在我的用例中,我正在更新文档计数器。因此,只要发生冲突,我要做的就是重试,因为我只需要汇总计数器即可。

我的用例有点this

  

对于部分更新的许多用途,文档已更改无所谓。例如,如果两个进程都在增加浏览量计数器,则顺序是无关紧要的;如果发生冲突,我们唯一需要做的就是重新尝试更新。

     

这可以通过将 retry_on_conflict 参数设置为更新在失败之前应重试的次数来自动完成;默认为0。

感谢Willis和this博客,我能够配置Elastic Search设置,现在完全没有任何问题