sparkStreaming kafka保证数据不丢失、不重复

sparkStreaming接收kafka数据的方式有两种:
1.利用Receiver接收数据;
2.直接从kafka读取数据(Direct 方式)

保证数据不丢失

(1)Receiver方式为确保零数据丢失,必须在Spark Streaming中另外启用预写日志(Write Ahead Logs)。这将同步保存所有收到的Kafka数据到分布式文件系统(例如HDFS)上,以便在发生故障时可以恢复所有数据。
(2)Direct方式依靠checkpoint机制来保证。每次streaming 消费了kafka的数据后,将消费的kafka offsets更新到checkpoint。当你的程序挂掉或者升级的时候,就可以接着上次的读取,实现数据的零丢失。
(Direct需要用户采用checkpoint或者第三方存储来维护offsets,而不像Receiver-based那样,通过ZooKeeper来维护Offsets,此提高了用户的开发成本)

kafka的acks参数有一个非常重要的作用。如果acks设置为0,表示Producer不会等待Broker的响应,Producer无法确定消息是否发送成功,可能会导致数据丢失,但acks值为0时,会得到最大的系统吞吐量。如果acks设置为1,表示Producer会在leader Partition收到消息并得到Broker的一个确认,这样会有更好的可靠性。如果设置为-1,Producer会在所有备份的Partition收到消息时得到Broker的确认,这个设置可以得到最高的可靠性保证。

保证数据不重复

这里业务场景被区分为两个:

  • 幂等操作
  • 业务代码需要自身添加事物操作

所谓幂等操作就是重复执行不会产生问题,如果是这种场景下,你不需要额外做任何工作。但如果你的应用场景是不允许数据被重复执行 的,那只能通过业务自身的逻辑代码来解决了。
这个spark给出了官方方案:

  dstream.foreachRDD {(rdd, time) =
              rdd.foreachPartition { partitionIterator =>
                val partitionId = TaskContext.get.partitionId()
                val uniqueId = generateUniqueId(time.milliseconds,partitionId)
                //use this uniqueId to transationally commit the data in partitionIterator
                 }
      }

就是说针对每个partition的数据,产生一个uniqueId,只有这个partition的所有数据被完全消费,则算成功,否则算失效,要回滚。下次重复执行这个uniqueId时,如果已经被执行成功,则skip掉。

你可能感兴趣的:(spark,kafka)