一、如何实现sparkstreaming从kafka中读取数据

1、在kafka0.10版本之前有两种方式,一种是基于receiver,一种是direct

   <1>、receiver:是采用kafka高级api,利用receiver接收器来接收kafka中topic的数据,从kafka接收来的数据会存储在spark的executor中,之后sparkstreaming提交的job会处理这些数据,kafka中的偏移量保存在zk中

使用:KafkaUtils.createStream()

注意:

1、这种方式,spark的partition和kafka的partition不相关

2、默认配置下会丢失数据,因为receiver一直接收数据,在从之zk的情况下,executor挂掉,但是数据接收了还没处理,缓存在其中的数据就会丢失,如果保证高可靠,让数据零丢失,启用WAL,通过该机制同步的将接收到kafka的数据写入hdfs,即使节点挂掉,也可以通过WAL的预写日志进行恢复,

<2>、direct:在spark 1.3后,引入direct方式,不同于receiver的方式,direct会周期性的获取kafka中每个topic的每个partition中最新的offsets,之后根据设定的maxRatePerPartition来处理每个batch,设置spark.streaming.kafka.maxRatePerPartition=10000,限制每秒钟从每个topic中最多消费的条数

 

二、对比这两种方式的优缺点

1、receiver方式,可以保证数据不丢失,但是无法保证数据只被处理一次,WAL实现的是至少处理一次,如果在写入到外部存储的数据还没将offset更新到zk中就挂掉,这些数据就会被重复消费。

2、direct方式,周期性的查找kafka数据,来获取每个topic+partition的最新的offset,从而定义每个batch的offset的范围,当处理数据的job启动时,就会使用kafka简单的consumer api来获取指定kafkaoffset的范围数据

direct方式的优点:

1、简化并行度

kafka的分区对应rdd的分区,一对一的映射关系

2、高性能

receiver通过WAL机制来保证数据零丢失,效率低

direct通过kafka的副本就可以恢复

3、一次且一次的事务机制

receiver 在zk中保存消费过的offset,配置WAL可以保证数据零丢失,但是不能保证只消费一次,可能两次,因为spark的zk之间不是不同步的。

direct方式sparkstreaming负责追踪到消费的offset,并保存在checkpoint中,spark自己一定是同步的,可以保证数据只消费一次,不过需要自己通过事务将数据写入zk中

message.foreachRDD(rdd=>{
     val message=rdd.map(x=>x._2)//对数据进行操作
    message.map()//更新zk上的offset(自己实现,写入reids或者mysql)
   updatezkoffset(rdd)
   })

sparkstreaming在消费完成后,自己主动更新zk上的偏移量,可以更新到redis或者mysql中,下次重启的时候读取mysql或者redis的偏移量,接上上次的读取