一、如何实现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的偏移量,接上上次的读取