SparkStreaming从Kafka中读取数据,设置检查点,处理数据后,并将结果存到Redis中,并实现执行优化

本文介绍了如何使用SparkStreaming从Kafka直接读取数据,通过设置检查点实现故障恢复。数据经过处理后,利用updateStateByKey进行累加统计,最终将结果存储到Redis中。同时,针对代码进行了优化,只输出有数据更新的结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实现思路

1.第一步获取StreamingContext对象,因为要使用检查点恢复数据,所以不能使用new StreamingContext的方法获取对象,要使用StreamingContext.getOrCreate建立对象
2.创建StreamingContext对象,使用了贷出模式 ——贷出函数的方式来创建
3.从Kafka的生产者端读取数据进行分析
4.读取数据的方式采用Direct方式读取数据
5.处理读取到的数据,获取需要的值
6.调用updateStateByKey实时累加统计函数,进行累加统计
7.将结果打印到控制台,并将数据存放到Redis中

具体代码实现

import com.huadian.bigdata.jedis.JedisPoolUtil
import kafka.serializer.StringDecoder
import org.apache.spark.SparkConf
import org.apache.spark.streaming.dstream.DStream
import org.apache.spark.streaming.kafka.KafkaUtils
import org.apache.spark.streaming.{
   
   Seconds, StreamingContext}

object G_RedisOrderTotalStreaming {
   
   
  //检查点目录
  val CHECK_POINT_PATH = "file:///E:\\JavaWork\\20190811\\test5"
  //Redis使用Hash存放数据
  val REDIS_KEY_ORDER_TOTAL_PRICE = "orders:total:price"
  def main(args: Array[String]): Unit = {
   
   
    /**
      * 先去查看检查点,
      * createFunc:第一次运行SparkStreaming应用的时候才会执行,才会创建StreamingContext
      */
    val ssc: StreamingContext = StreamingContext.getOrCreate(
      CHECK_POINT_PATH,
      createFunc
    )
    //设置日志级别
    ssc.sparkContext.setLogLevel("WARN")
    ssc.start()
    ssc.awaitTermination()
    //stop(stopSparkContext: Boolean, stopGracefully: Boolean)
    ssc
好的,下面是一个简单的示例,展示了如何在 Flink 中实现一个支持状态检查点Kafka 消费者,将消费到的偏移量保存Redis 中: ```java public class KafkaConsumerFunction implements SourceFunction<String>, CheckpointedFunction { private transient KafkaConsumer<String, String> kafkaConsumer; private transient Jedis jedis; private final String kafkaTopic; private final String kafkaBootstrapServers; private final String redisHost; private final int redisPort; private long lastCommittedOffset = 0L; private transient ListState<Long> checkpointedOffset; public KafkaConsumerFunction(String kafkaTopic, String kafkaBootstrapServers, String redisHost, int redisPort) { this.kafkaTopic = kafkaTopic; this.kafkaBootstrapServers = kafkaBootstrapServers; this.redisHost = redisHost; this.redisPort = redisPort; } @Override public void run(SourceContext<String> ctx) throws Exception { kafkaConsumer = new KafkaConsumer<>(createConsumerProperties()); kafkaConsumer.subscribe(Collections.singletonList(kafkaTopic)); jedis = new Jedis(redisHost, redisPort); while (true) { ConsumerRecords<String, String> records = kafkaConsumer.poll(Duration.ofMillis(100)); for (ConsumerRecord<String, String> record : records) { ctx.collect(record.value()); lastCommittedOffset = record.offset(); } commitOffsetToRedis(); } } private Properties createConsumerProperties() { Properties props = new Properties(); props.put("bootstrap.servers", kafkaBootstrapServers); props.put("group.id", "flink-kafka-consumer"); props.put("auto.offset.reset", "earliest"); props.put("key.deserializer", StringDeserializer.class.getName()); props.put("value.deserializer", StringDeserializer.class.getName()); return props; } private void commitOffsetToRedis() { jedis.set("kafka-offset", String.valueOf(lastCommittedOffset)); } @Override public void cancel() { kafkaConsumer.close(); } @Override public void snapshotState(FunctionSnapshotContext context) throws Exception { checkpointedOffset.clear(); checkpointedOffset.add(lastCommittedOffset); } @Override public void initializeState(FunctionInitializationContext context) throws Exception { ListStateDescriptor<Long> descriptor = new ListStateDescriptor<>("kafka-offset", Long.class); checkpointedOffset = context.getOperatorStateStore().getListState(descriptor); if (context.isRestored()) { for (Long offset : checkpointedOffset.get()) { lastCommittedOffset = offset; } } } } ``` 在这个示例中,我们实现了一个 Kafka 消费者,每次从 Kafka 中消费一条消息时,将消息的偏移量保存到 `lastCommittedOffset` 变量中,将 `lastCommittedOffset` 变量的值保存Redis 中。在 `snapshotState()` 方法中,我们将 `lastCommittedOffset` 的值保存到 `ListState` 中,这个 `ListState` 会被 Flink 自动保存检查点中。在 `initializeState()` 方法中,我们从 `ListState` 中恢复之前保存的 `lastCommittedOffset` 的值,如果当前任务是从检查点中恢复的,则将 `lastCommittedOffset` 的值设置为之前保存的值。这样,在任务重新启动时,我们就可以从上一次保存的偏移量的位置开始消费 Kafka 中的消息了。需要注意的是,这个示例中的 Redis 客户端使用的是 Jedis,如果你使用的是 Redisson 或者其他的 Redis 客户端,需要根据具体的客户端文档来实现 Redis 的操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值