Spark Streaming连接kafka消费多个topic只消费其中一个topic一个分区的问题

代码:

import org.apache.kafka.common.serialization.StringDeserializer
import org.apache.spark.sql.SparkSession
import org.apache.spark.streaming.kafka010._
import org.apache.log4j.{Level, Logger}
import org.apache.spark.streaming.{Seconds, StreamingContext}

object KafkaTest {

  def main(args: Array[String]): Unit = {
    Logger.getLogger("org.apache.spark").setLevel(Level.ERROR)
    Logger.getLogger("org.eclipse.jetty.server").setLevel(Level.ERROR)
    Logger.getLogger("org.apache.kafka.clients.consumer").setLevel(Level.ERROR)
    val spark = SparkSession
      .builder()
      .appName("Spark Jason")
      .master("local[6]")
      .getOrCreate()
    val sc = spark.sparkContext
    val scc = new StreamingContext(sc, Seconds(2))
    val kafkaParams = Map[String, Object](
        "auto.offset.reset" -> "latest"
      , "value.deserializer" -> classOf[StringDeserializer]
      , "key.deserializer" -> classOf[StringDeserializer]
      , "bootstrap.servers" -> "xxx:9092"
      , "group.id" -> "aaaa"
      , "enable.auto.commit" -> (true: java.lang.Boolean)
    )
    val topics = Array( "fact","drools")
    val stream = KafkaUtils.createDirectStream[String, String](
      scc,
      LocationStrategies.PreferConsistent,
      ConsumerStrategies.Subscribe[String, String] (topics, kafkaParams)
    )
    stream.foreachRDD(rdd=>{
      rdd.foreach(
        line => println(line.value())
      )
    })

    scc.start()
    scc.awaitTermination()
  }

}

现象:

代码中监听了两个topic,但每次只消费到其中一个topic的一个分区的数据
查看消费者发现另一个topic一直堆积没消费:

解决方案:

查看pom依赖文件发现kafka依赖版本是0.10.1.0

        <dependency>
            <groupId>org.apache.kafka</groupId>
            <artifactId>kafka-clients</artifactId>
            <version>0.10.1.0</version>
            <scope>${mvn.scop.pro}</scope>
        </dependency>

更换版本后解决:(升级版本或者降级版本0.10.0.1都行)

        <dependency>
            <groupId>org.apache.kafka</groupId>
            <artifactId>kafka-clients</artifactId>
            <version>0.10.2.1</version>
            <scope>${mvn.scop.pro}</scope>
        </dependency>

查阅后发现不光是0.10.1.0版本有个问题,0.10.1.10.10.0.2也有这个问题。
而且是只能在local模式下才会出现这个问题,cluster和client模式正常消费。

参考链接:https://issues.apache.org/jira/browse/KAFKA-4547

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 使用Spark Streaming结合Kafka可以实现精确消费一次,将结果保存到Redis的步骤如下: 1. 创建Spark Streaming上下文,并设置批处理时间间隔。 2. 创建Kafka数据源,并设置消费者组和topic。 3. 使用KafkaUtils.createDirectStream()方法创建DStream,该方法可以实现精确消费一次。 4. 对DStream进行数据处理,例如使用map()方法对每条数据进行处理。 5. 将处理后的数据保存到Redis中,可以使用Redis的Java客户端Jedis实现。 6. 启动Spark Streaming应用程序,开始消费Kafka数据并将结果保存到Redis中。 示例代码如下: ```java import org.apache.spark.SparkConf; import org.apache.spark.streaming.Duration; import org.apache.spark.streaming.api.java.JavaDStream; import org.apache.spark.streaming.api.java.JavaStreamingContext; import org.apache.spark.streaming.kafka010.ConsumerStrategies; import org.apache.spark.streaming.kafka010.KafkaUtils; import org.apache.spark.streaming.kafka010.LocationStrategies; import redis.clients.jedis.Jedis; import java.util.Collections; import java.util.HashMap; import java.util.Map; public class SparkStreamingKafkaRedis { public static void main(String[] args) throws InterruptedException { // 创建Spark Streaming上下文 SparkConf conf = new SparkConf().setAppName("SparkStreamingKafkaRedis"); JavaStreamingContext jssc = new JavaStreamingContext(conf, new Duration(5000)); // 创建Kafka数据源 String brokers = "localhost:9092"; String groupId = "test-group"; String topic = "test-topic"; Map<String, Object> kafkaParams = new HashMap<>(); kafkaParams.put("bootstrap.servers", brokers); kafkaParams.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer"); kafkaParams.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer"); kafkaParams.put("group.id", groupId); kafkaParams.put("auto.offset.reset", "latest"); kafkaParams.put("enable.auto.commit", false); // 创建DStream JavaDStream<String> lines = KafkaUtils.createDirectStream( jssc, LocationStrategies.PreferConsistent(), ConsumerStrategies.<String, String>Subscribe(Collections.singleton(topic), kafkaParams) ).map(record -> record.value()); // 处理数据并保存到Redis lines.foreachRDD(rdd -> { rdd.foreachPartition(partition -> { Jedis jedis = new Jedis("localhost", 6379); while (partition.hasNext()) { String data = partition.next(); // 处理数据 String result = data.toUpperCase(); // 保存到Redis jedis.set("result", result); } jedis.close(); }); }); // 启动Spark Streaming应用程序 jssc.start(); jssc.awaitTermination(); } } ``` ### 回答2: Spark Streaming一个用于实时数据处理的框架,而Kafka则是一个高性能的分布式消息队列。结合这两个技术,可以快速搭建一个实时数据处理的系统,并将结果保存到Redis中。 首先需要在Spark Streaming应用程序中引入Kafka相关的依赖包,具体依赖包可以在Spark官网上找到。接着,需要创建一个Kafka DStream来读取消息队列中的数据。在读取数据之前,应当先通过Kafka的Offset管理功能来确定从何处开始读取数据。 在读取到数据之后,可以通过Spark Streaming提供的RDD转换算子来进行数据处理和分析操作。完成数据分析后,我们可以将结果保存到Redis中。为了确保数据的精确性,需要保证每条消息只被消费一次,可以通过Kafka的Offset的提交和管理来实现这一点。 在使用Redis保存数据时,在Spark Streaming应用程序中可以引入Redis的Java客户端(Jedis),连接Redis集群。然后,使用Jedis提供的API来向Redis中写入数据。此外,在保存数据到Redis之前,还需要对数据进行序列化处理。 总之,结合Spark StreamingKafka和Redis三个技术,可以实现一个高性能的实时数据处理和存储系统。同时,为了确保数据的精确性和完整性,还需要在处理过程中注意一些细节问题,如Offset的管理、数据的序列化与反序列化等。 ### 回答3: Spark Streaming是基于Apache Spark构建的流式处理库,它可以处理高速数据流,并支持丰富的数据处理操作。Kafka则是一个分布式的、可扩展的、高吞吐量的发布-订阅消息系统,可用于构建实时数据流处理系统。而Redis则是一种流行的、内存中的键值数据库,支持高速读写操作和数据分析,尤其适用于缓存、消息队列和分布式锁等场景。将Spark StreamingKafka和Redis结合使用,可以实现精确消费一次并将结果保存到Redis的流处理流程。 具体实现步骤如下: 1. 创建Kafka输入流以接收数据 使用KafkaUtils.createDirectStream()方法创建Kafka输入流来接收数据。该方法需要参数:Kafka参数、Topic集合、kafka分区偏移量。 2. 通过处理接收到的数据进行清洗和转换 在创建Kafka输入流后,可以通过转换操作对接收到的数据进行清洗和转换。这里可以使用Spark Streaming提供的丰富的转换操作进行处理。 3. 将转换后的数据保存到Redis中 在清洗和转换数据完成后,我们将数据保存到Redis中。这里可以使用Redis的Java客户端jedis来操作Redis。创建jedis实例,然后使用jedis.set()方法将数据保存到Redis中。 4. 设置执行计划并启动流处理作业 配置好输入流、清洗和转换流程以及将结果保存到Redis中,最后要设置执行计划并启动流处理作业。执行计划将交给Spark Streaming处理,我们只需要启动作业即可。 实现流处理过程后,我们可以使用Spark Streaming自带的数据监控可视化工具监控流数据处理情况。同时还可以使用Redis的客户端工具检查Redis中的数据是否已经成功保存。 以上就是将Spark Streaming结合Kafka精确消费一次并将结果保存到Redis的的流处理过程。该流程可以应用于实时数据分析和处理场景,特别适用于高速数据流处理和数据保存操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值