使用Kafka进行Spark流式传输 - createDirectStream vs createStream

Sha*_*hay 15 apache-kafka apache-spark spark-streaming

我们已经使用kafka火花流一段时间,直到现在我们使用的createStream方法KafkaUtils.

我们刚开始探索createDirectStream和喜欢它有两个原因:

1)更好/更容易"完全一次"语义

2)更好地将kafka主题分区与rdd分区相关联

我注意到它createDirectStream被标记为实验性的.我的问题是(抱歉,如果这不是非常具体):

我们应该探索一下这种createDirectStream方法,如果一次对我们来说非常重要吗?如果你们可以分享你的经验,那将是非常棒的.我们是否有可能不得不处理可靠性等其他问题?

Yuv*_*kov 9

有一个巨大的,广泛的博客文章由直接的方法(科迪)的创作者在这里.

一般来说,阅读Kafka交付语义部分,最后一部分说:

因此,有效地Kafka保证默认情况下至少一次交付,并且允许用户通过禁用生产者的重试并在处理一批消息之前提交其偏移量来最多实施一次交付.完全一次交付需要与目标存储系统合作,但Kafka提供了偏移,这使得实现这一直接.

这基本上意味着"我们至少提供一次开箱即用,如果你只需要一次,那就在你身上".此外,博客文章讨论了使用两种方法从Spark获得的"一次性"语义的保证(直接和基于接收器,强调我的):

其次,要了解Spark并不保证输出操作的确切一次语义.当Spark流式传输指南只谈到一次时,它只是指RDD中的给定项目被包含在计算值中一次,纯粹是功能性的.任何副作用输出操作(即您在foreachRDD中为保存结果而执行的任何操作)都可能会重复,因为该过程的任何阶段都可能失败并重试.

此外,这是Spark文档中关于基于接收器的处理的内容:

第一种方法(基于Receiver)使用Kafka的高级API在Zookeeper中存储消耗的偏移量.传统上,这是从Kafka使用数据的方式.虽然这种方法(与预写日志结合使用)可以确保零数据丢失(即至少一次语义),但某些记录在某些故障下可能会被消耗两次.

这基本上意味着如果您使用基于Receiver的流与Spark,您可能仍然有重复的数据,以防输出转换失败,它至少是一次.

在我的项目中,我使用直接流方法,其中传递语义取决于您如何处理它们.这意味着如果您想确保一次语义,您可以将偏移量与数据一起存储在事务中,如果一个失败,另一个失败也是如此.

我建议阅读Kafka文档页面中的博客文章(上面的链接)和交付语义.总而言之,我绝对建议您研究直接流方法.