kafka对接SparkStreaming的方式详解

环境

kafka_2.11-0.10.0.1
hadoop-2.6.0-cdh5.7.0
spark-2.2.0-bin-2.6.0-cdh5.7.0

Receiver方式

  1. 环境不合适,只能简答描述特点
  2. 该方式只能为0-8版本到之后可以使用,到0-10版本就不好使了
  3. 构造函数中的numThreads参数,对应提高sparkstreaming的并行度并没有关系,提高只有kafka的分区数才能提高并行度,增加读写速度
  4. 这种情况可能会出现数据丢失问题,在driver端挂掉,Executor重启的时候必然会丢数据,在1.2时增加了一个Write Ahead Logs的机制(在写到Receiver时,写到一个日志中,通常为HDFS),这个机制可以避免数据丢失,但是写到HDFS或者文件系统必然会降低吞吐量。同时启动Write Ahead Logs时,存储结构设置为StorageLevel.MEMORY_AND_DISK_SER,不需要多副本,因为HDFS就是多副本机制
  5. 由于应用WAL,所以语义为至少一次

Direct Approach方式

1.没有Recevier,没有Recevier,没有Recevier,重要的事情说三遍
2.简化并行度:不需要指定numThreads的参数,RDD的分区直接与kafka的分区相等,提高并行度,加大分区。
3.零数据丢失,吞吐量更好,直接从kafka分区读取
4.当offset(偏移量)还没有写入kafka,driver就挂了,可能会导致重复写入,也就是会产生至少一次的语义。可以把偏移量交给sparkStreaming的checkpoint来维护,这样就会达到只有一次的效果。
5.缺点:在ssc中维护偏移量,那么kafka界面则无法显示,所以可以将偏移量重新写入到zk中,如下:

var offsetRanges = Array.empty[OffsetRange]

 directKafkaStream.transform { rdd =>
   offsetRanges = rdd.asInstanceOf[HasOffsetRanges].offsetRanges
   rdd
 }.map {
           ...
 }.foreachRDD { rdd =>
   for (o <- offsetRanges) {
     println(s"${o.topic} ${o.partition} ${o.fromOffset} ${o.untilOffset}")
   }
   ...
 }

代码实现Direct 方式对接SparkStreaming

环境准备:
1.启动ZK

zkServer.sh start

2.启动kafka

nohup kafka-server-start.sh config/server.properties &

3.创建kafka的blocker

kafka-topics.sh --create \
--zookeeper localhost:2181 \
--replication-factor 1 --partitions 1 --topic  topicD

4.启动生产者

kafka-console-producer.sh --broker-list localhost:9092 --topic onlinelogs

5.启动消费者

kafka-console-consumer.sh \
--zookeeper localhost:2181 \
--from-beginning --topic topicD

代码实现:

object DkafkatoStreaming {

  def main(args: Array[String]) {

    val sparkconf=new SparkConf().setAppName("project").setMaster("local")
    val ssc=new StreamingContext(sparkconf,Seconds(5))
    val kafkaParams = Map[String, Object](
      ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG ->"hadoop:9092",
      ConsumerConfig.GROUP_ID_CONFIG -> "test",
      ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG -> classOf[StringDeserializer],
      ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG -> classOf[StringDeserializer])
    ssc.checkpoint("hdfs://hadoop:9000/data")
    val topics = Array("topicD")
    val stream = KafkaUtils.createDirectStream[String, String](
      ssc,
      LocationStrategies.PreferConsistent,
      ConsumerStrategies.Subscribe[String, String](topics, kafkaParams))
    val lines=stream.map(_.value)
    val word=lines.flatMap(_.split(",")).map(x=>(x,1)).reduceByKey(_+_).print

    ssc.start()
    ssc.awaitTermination()
  }
}

查看测试结果:

kafka对接SparkStreaming的方式详解_第1张图片

你可能感兴趣的:(kafka对接SparkStreaming的方式详解)