sparkstreaming消费kafka如何保证输出结果只会产生一次?(事务性)

最近开始使用sparkstreaming+kafka0.10,使用过程中碰到问题:

    steaming采用的direct方式 ,(这种方式和receiver方式的对比性能会好很多),spark计算完数据之后有一个结果入库操作,现在问题来了,采用自动提交的时候程序二次启动经常会出现重复消费的情况,并且怎么保证这个结果只生产一次呢?

首先介绍一下sparkstreaming内部是怎么做到消息只计算一次的  :

    1.topic的数据拉过来之后计算的时候出现的各种内存溢出等异常,这些spark自己会有重计算

    2.由于代码导致的异常,不会重复计算,结果就不会产生,这时你可以自己想办法重新计算


 再来了解一下spark是怎么消费kafka的,这个可能很多初学者不了解,下面是分析DirectKafkaInputStream:

启动时会进行start方法

override def start(): Unit = {
  val c = consumer
  paranoidPoll(c)
  if (currentOffsets.isEmpty) {//启动时肯定为空
    currentOffsets = c.assignment().asScala.map { tp =>
//根据 auto.offset.reset的配置 earliest为从最近提交的offset处开始 latest从该topic的最新消息的位置开始
    tp -> c.position(tp)
    }.toMap
  }

currentoffsets保存的是上次消费的partition以及offset等信息,

之后拉取数据就是compute方法了

 override def compute(validTime: Time): Option[KafkaRDD[K, V]] = {
    val untilOffsets = clamp(latestOffsets())
    ....
    currentOffsets = untilOffsets
    commitAll()
    ...
    }
 
 
latestOffsets会将新增的分区信息获取到 clamp 根据设置 spark.streaming.kafka.maxRatePerPartition * partitionsize 限制每个partition每次拉取的数据量

streaming只会在第一次启动时使用到kafka中保存的的offset,然后将消费的position保存在currentoffsets中,此后kafka中的offset值只供下一次启动
时用到。其中commitAll()就是提交offset,入伙enable.auto.commit为true则是根据 auto.commit.interval.ms 的值周期性的异步提交,false的话可以
手动提交:
val ds = KafkaUtils.createDirect.....
ds.foreachRDD(rdd=>{
val com =  ds.asInstanceOf[CanCOmmitOffsets]
val off  = rdd.asInstanceOf[HasOffsetRanges].offsetRanges
com.commitAsync(off ,new OffsetCommitCallback{
override def onComplete(.....
})
}
)

官方只提供了异步提交的方法,同步提交可自己使用KafkaConsumer.commitSync方法实现...

现在回到那个问题:采用自动提交的时候程序二次启动经常会出现重复消费的情况,并且怎么保证这个结果只生产一次呢?

因为默认是异步批量提交offset,commitAsync方法还没运行完程序就停止了,因为异步提交一般要等很久! 所有二次启动肯定会出现消息重复消费。

解决方案:

1.自己实现commitsync方法 ,这个方法运行时毫秒级

2.每次消费完之后将offset保存到hdfs或本地,启动的时候读这个文件并且加入新增的partition offset即可

但是!上面的方案还是会出现问题。。。

因为入库操作和commitc方法不是一个原子操作。

所以程序停止时可能出现commitsync方法未完成或hdfs文件未写完..虽然概率很小。。

为了真正的解决上述问题,唯一的最合适的方案:


将offset信息同结果数据一起入库,保证是一个原子操作,这样就万无一失了



 
 


猜你喜欢

转载自blog.csdn.net/u013314600/article/details/80929310