Spark Streaming + Kafka(Kafka broker version 0.10.0)

1 概述

本文对于Kafka对接Spark Streaming进行学习。
官方地址,但是需要注意的是:Kafka项目在版本0.8和0.10之间引入了新的消费者API,因此有两个独立的相应Spark Streaming软件包可用。所以使用的时候要注意版本的问题。如下图所示版本选择:
这里写图片描述

作者使用版本介绍(伪分布式):


kafka_2.11-0.10.0.1.tgz
scala-2.11.8.tgz
zookeeper-3.4.5-cdh5.7.0.tar.gz 

kafka下载地址
scala下载地址
zookeeper下载地址

2 安装部署

  • zookeeper-3.4.5-cdh5.7.0.tar.gz
1.下载解压zookeeper-3.4.5-cdh5.7.0.tar.gz 
tar -xzvf zookeeper-3.4.5-cdh5.7.0.tar.gz 

2.修改权限
chown -R hadoop;hadoop zookeeper-3.4.5-cdh5.7.0

3.修改配置
cp zoo_sample.cfg zoo.cfg
vi zoo.cfg 
修改目录
dataDir=/opt/software/zookeeper-3.4.5-cdh5.7.0/data
mkdir data

4.启动
./zkServer.sh start

5.查看状态
./zkServer.sh status
  • kafka_2.11-0.10.0.1.tgz
1.解压
tar -xzvf kafka_2.11-0.10.0.1.tgz
2.创建日志目录
cd kafka
mkdir logs
3.修改配置文件
vi server.properties
port=9092
host.name=192.168.137.141
log.dirs=/opt/software/kafka/logs
4.后台启动
./kafka-server-start.sh -daemon /opt/software/kafka_2.11-0.10.0.1/config/server.properties
  • 检验kafka是否安装成功
创建topic
./kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic streaming_topic

创建生产者
[hadoop@hadoop bin]$ ./kafka-console-producer.sh --broker-list localhost:9092 --topic streaming_topic                    

创建消费者
./kafka-console-consumer.sh --zookeeper localhost:2181 --topic streaming_topic 

在生产者端发送消息看看消费者能否接受到

3 Spark Streaming + Kafka

Kafka 0.10的Spark Streaming集成设计与0.8 Direct Stream方法类似。 它提供了简单的并行性,Kafka分区和Spark分区之间的1:1对应关系,以及对偏移量和元数据的访问。 但是,由于较新的集成使用新的Kafka消费者API而不是简单的API,因此在使用方面存在显着差异。 此版本的集成标记为实验性,因此API可能会发生变化。

  • maven中添加的gav
groupId = org.apache.spark
artifactId = spark-streaming-kafka-0-10_2.11
version = 2.3.0
  • 生产者
./kafka-console-producer.sh --broker-list 192.168.137.130:9092 --topic streaming_topic  
  • 消费者
./kafka-console-consumer.sh --zookeeper 192.168.137.130:2181 --topic streaming_topic
  • 代码
import org.apache.spark.streaming.{Seconds, StreamingContext}
import org.apache.kafka.common.serialization.StringDeserializer
import org.apache.spark.SparkConf
import org.apache.spark.streaming.kafka010.{ConsumerStrategies, KafkaUtils, LocationStrategies}


object KafkaStreaming {
  def main(args: Array[String]): Unit = {
    //创建StreamingContext
    val sparkConf=new SparkConf().setAppName("KafkaStreaming").setMaster("local[2]")
    val ssc=new StreamingContext(sparkConf,Seconds(10))

    //准备参数
    val kafkaParams = Map[String, Object](
      "bootstrap.servers" -> "192.168.137.130:9092",
      "key.deserializer" -> classOf[StringDeserializer],
      "value.deserializer" -> classOf[StringDeserializer],
      "group.id" -> "use_a_separate_group_id_for_each_stream",
      //Kafka提供的有api,可以将offset提交到指定的kafkatopic或者选择checkpoint的方式,下面会说
      "auto.offset.reset" -> "latest",
      "enable.auto.commit" -> (false: java.lang.Boolean)
    )
    //上面通过Kafka提供的有api设置过offset
   // ssc.checkpoint("/flume_streaming/data")

    //topics(注意这里是复数哦)
    val topics = Array("streaming_topic")
    //通过KafkaUtils放回一个DStream
    val stream = KafkaUtils.createDirectStream[String, String](
      ssc,
      LocationStrategies.PreferConsistent,
      ConsumerStrategies.Subscribe[String, String](topics, kafkaParams)
    )

    //stream.map(record => (record.key, record.value)).print()

    //wc
    val lines=stream.map(_.value)
    val word=lines.flatMap(_.split(",")).map(x=>(x,1)).reduceByKey(_+_).print


    ssc.start()
    ssc.awaitTermination()
  }

}
  • 实验
在生产者中输入:
a,a,a,b,b,b,c,c,c,d,d,e,e,r,f,g

结果:
(d,2)
(b,3)
(f,1)
(r,1)
(e,2)
(a,3)
(g,1)
(c,3)

**注意:***kafka的参数,请参考kafka官网。如果,你的spark批次时间超过了kafka的心跳时间(30s),需要增加heartbeat.interval.ms和session.timeout.ms。例如,批处理时间是5min,那么就需要调整group.max.session.timeout.ms。注意,例子中是将enable.auto.commit设置为了false,enable.auto.commit参数值是true,含义是当数据被消费完之后会,如果spark streaming的程序由于某种原因停止之后再启动,下次不会重复消费之前消费过的数据。

4 本地策略(LocationStrategies)

新版本的消费者API会预取消息入buffer。因此,为了提升性能,在Executor端缓存消费者(而不是每个批次重新创建)是非常有必要的,优先调度那些分区到已经有了合适消费者主机上。

在很多情况下,你需要像上文一样使用LocationStrategies.PreferConsistent,这个参数会将分区尽量均匀地分配到所有的可以Executor上去。如果,你的Executor和kafka broker在同一台机器上,可以用PreferBrokers,这将优先将分区调度到kafka分区leader所在的主机上。最后,分区间负荷有明显的倾斜,可以用PreferFixed。这个允许你指定一个明确的分区到主机的映射(没有指定的分区将会使用连续的地址)。

消费者缓存的数目默认最大值是64。如果你希望处理超过(64*excutor数目)kafka分区,spark.streaming.kafka.consumer.cache.maxCapacity这个参数可以帮助你修改这个值。

如果你想禁止kafka消费者缓存,可以将spark.streaming.kafka.consumer.cache.enabled修改为false。禁止缓存缓存可能需要解决SPARK-19185描述的问题。一旦这个bug解决,这个属性将会在后期的spark版本中移除。

Cache是按照topicpartition和groupid进行分组的,所以每次调用creaDirectStream的时候要单独设置group.id。

5 存储偏移

Kafka在有可能存在任务失败的情况下的从消息传输语义(至少一次,最多一次,恰好一次)是取决于何时存储offset。Spark输出操作是至少一次传输语义。所以,如果你想实现仅仅一次的消费语义,你必须要么在密等输出后存储offset,要么就是offset的存储和结果输出是一次事务。

1, Checkpoint

如果使能了Checkpoint,offset被存储到Checkpoint。这个虽然很容易做到,但是也有一些缺点。由于会多次输出结果,所以结果输出必须是满足幂等性。同时事务性不可选。另外,如果代码变更,你是不可以从Checkpoint恢复的。针对代码升级更新操作,你可以同时运行你的新任务和旧任务(因为你的输出结果是幂等性)。对于以外的故障,并且同时代码变更了,肯定会丢失数据的,除非另有方式来识别启动消费的偏移。

2, Kafka自身

Kafka提供的有api,可以将offset提交到指定的kafkatopic。默认情况下,新的消费者会周期性的自动提交offset到kafka。但是有些情况下,这也会有些问题,因为消息可能已经被消费者从kafka拉去出来,但是spark还没处理,这种情况下会导致一些错误。这也是为什么例子中stream将enable.auto.commit设置为了false。然而在已经提交spark输出结果之后,你可以手动提交偏移到kafka。相对于Checkpoint,offset存储到kafka的好处是:kafka既是一个容错的存储系统,也是可以避免代码变更带来的麻烦。提交offset到kafka和结果输出也不是一次事务,所以也要求你的输出结果是满足幂等性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
spark streaming 是基于 spark 引擎的实时数据处理框架,可以通过集成 kafka 来进行数据流的处理。然而,在使用 spark streaming 进行 kafka 数据流处理时,可能会遇到一些坑。 首先,要注意 spark streamingkafka 版本的兼容性。不同版本的 spark streamingkafka 可能存在一些不兼容的问题,所以在选择版本时要特别留意。建议使用相同版本的 spark streamingkafka,以避免兼容性问题。 其次,要注意 spark streaming 的并行度设置。默认情况下,spark streaming 的并行度是根据 kafka 分区数来决定的,可以通过设置 spark streaming 的参数来调整并行度。如果并行度设置得过高,可能会导致任务处理过慢,甚至出现 OOM 的情况;而设置得过低,则可能无法充分利用集群资源。因此,需要根据实际情况进行合理的并行度设置。 另外,要注意 spark streamingkafka 的性能调优。可以通过调整 spark streaming 缓冲区的大小、批处理时间间隔、kafka 的参数等来提高性能。同时,还可以使用 spark streaming 的 checkpoint 机制来保证数据的一致性和容错性。但是,使用 checkpoint 机制可能会对性能产生一定的影响,所以需要权衡利弊。 最后,要注意处理 kafka 的消息丢失和重复消费的问题。由于网络或其他原因,可能会导致 kafka 的消息丢失;而 spark streaming 在处理数据时可能会出现重试导致消息重复消费的情况。可以通过配置合适的参数来解决这些问题,例如设置 KafkaUtils.createDirectStream 方法的参数 enable.auto.commit,并设置适当的自动提交间隔。 总之,在使用 spark streaming 进行 kafka 数据流处理时,需要留意版本兼容性、并行度设置、性能调优和消息丢失重复消费等问题,以免踩坑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值