使用Kafka的Spark流处理 - createDirectStream与createStream的区别

18
我们之前一直在使用Spark Streaming和Kafka,使用的是KafkaUtils中的createStream方法。最近开始尝试使用createDirectStream方法,并且喜欢它的两个优点:
1) 更好/更容易实现“确切一次”语义
2) 更好地将kafka主题分区与rdd分区相关联
我注意到createDirectStream被标记为实验性的。我的问题是(如果不太具体请见谅):
如果确切一次非常重要,我们应该尝试使用createDirectStream方法吗?如果你们能分享你们的经验,那就太棒了。我们是否会冒着处理其他问题(如可靠性等)的风险?
1个回答

8

这里有一篇由直接方式的创始人 Cody 撰写的广泛博客文章这里

通常来说,在阅读 Kafka 交付语义部分时,最后一部分如下:

因此,Kafka默认情况下保证至少一次传递,并允许用户通过禁用生产者重试并在处理一批消息之前提交其偏移量来实现最多一次传递。实现仅一次传递需要与目标存储系统协作,但Kafka提供了偏移量,使其实现变得简单明了。

这基本上意味着“我们为您提供至少一次的开箱即用体验,如果您想要确切地一次,那就由您自己完成”。此外,该博客文章还谈到了使用两种方法(直接和接收器)从 Spark 中获得“确切一次”语义的保证(强调是我的):

其次,需要明白的是Spark不能保证输出操作的精准一次性语义。当Spark流指南谈论精准一次性时,仅仅是指在一个RDD中给定的项被计算值包含一次,从纯函数意义上讲。任何具有副作用的输出操作(即在foreachRDD中保存结果的任何操作)都可能会重复,因为该过程的任何阶段都可能失败并进行重试。
此外,这就是Spark文档关于接收器处理的说法:
第一种方法(基于接收器)使用Kafka的高级API将已消耗的偏移量存储在Zookeeper中。传统上,这是从Kafka中消费数据的方式。虽然这种方法(与预写日志相结合)可以确保零数据丢失(即至少一次的语义),但在某些故障下某些记录可能会被消耗两次。 这基本上意味着,如果您正在使用带有Spark的接收器流,那么如果输出转换失败,您仍然可能具有重复数据,它是至少一次的。
在我的项目中,我使用直接流的方法,其中交付语义取决于您如何处理它们。这意味着,如果您想确保仅一次语义,可以以事务方式存储数据和偏移量,如果其中一个失败,则另一个也会失败。
我建议阅读博客文章(上面的链接)和Kafka文档页面中的传递语义Delivery Semantics。总之,我强烈建议您了解直接流方法。

你提到的第一个博客链接已经无法打开了,请尽可能更新它。 - nomadSK25
1
@Sukumaar 我已经更新了链接,指向一个大致相同内容的演示文稿。 - Yuval Itzchakov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接