Kafka-Streaming

一、流计算定义

一般流式计算会与批量计算相比较。在流式计算模型中,输入是持续的,可以认为在时间上是无界的,也就意味着,永远拿不到全量数据去做计算。同时,计算结果是持续输出的,也即计算结果在时间上也是无界的。流式计算一般对实时性要求较高,同时一般是先定义目标计算,然后数据到来之后将计算逻辑应用于数据。同时为了提高计算效率,往往尽可能采用增量计算代替全量计算。批量处理模型中,一般先有全量数据集,然后定义计算逻辑,并将计算应用于全量数据。特点是全量计算,并且计算结果一次性全量输出。

二、Kafka Streams

2.1 概述

Kafka Stream是一个客户端库,用于处理和分析存储在kafka中的数据,它建立在重要的流处理概念之上。Kafka Streaming是基于Kafka的轻量级实时处理api,可以从一个topic中接收数据,进行简单处理后放入另一个topic。
从一个topic中读取数据,经过处理操作后,写入到另一个topic中
读取数据后,可以获得一个KStream对象,该对象包含了对数据集合的处理方法(类似与SparkRDD)

2.2 kafka streams的优点

简单、轻巧易部署、无缝对接Kafka、基于分区实现计算并行、基于幂等和事务特性实现精确计算、单个记录毫秒级延迟计算-实时性高、提供了两套不同风格的流处理API-(High level-Domain Specific Language|DSL开箱即用;low-level Processor API.)

2.3 Topology

Topology:表示一个流计算任务,等价于MapReduce中的job。不同的是MapReduce的job作业最终会停止,但是Topology会一直运行在内存中,除非人工关闭该Topology。

stream:它代表了一个无限的,不断更新的Record数据集。流是有序,可重放和容错的不可变数据记录序列,其中数据记录被定义为键值对。

所谓的流处理是通过Topology编织程序对stream中Record元素的处理的逻辑/流程。这种计算和早期MapReduce计算的最大差异是该计算的实时性比较高,可以满足绝大多数的实时计算场景。Kafka Stream以它的轻量级、容易部署、低延迟等特点在微服务领域相比较 专业的 Storm、spark streaming和Flink 而言有着不可替代的优势。有关Storm、SparkStreaming和Flink的内容随着课程的深入会在后续章节再展开讨论。

实例1:

导入maven项目,并导入依赖:

<dependencies>
    <dependency>
        <groupId>org.apache.kafka</groupId>
        <artifactId>kafka-clients</artifactId>
        <version>2.0.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.kafka</groupId>
        <artifactId>kafka_2.11</artifactId>
        <version>2.0.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.kafka</groupId>
        <artifactId>kafka-streams</artifactId>
        <version>2.0.0</version>
    </dependency>
</dependencies>

目的:将topic:in 中的数据导出到topic:out中:

import org.apache.kafka.common.serialization.Serdes;
import org.apache.kafka.streams.KafkaStreams;
import org.apache.kafka.streams.StreamsBuilder;
import org.apache.kafka.streams.StreamsConfig;
import org.apache.kafka.streams.Topology;

import java.util.Properties;
import java.util.concurrent.CountDownLatch;

public class MyStreamDemo {
    public static void main(String[] args) {
        //  创建Properties对象,配置Kafka Streaming配置项
        Properties prop = new Properties();
        prop.put(StreamsConfig.APPLICATION_ID_CONFIG, "demo");
        prop.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, "192.168.64.2:9092");
        prop.put(StreamsConfig.DEFAULT_KEY_SERDE_CLASS_CONFIG, Serdes.String().getClass());
        prop.put(StreamsConfig.DEFAULT_VALUE_SERDE_CLASS_CONFIG, Serdes.String().getClass());

        // 创建流构造器
        StreamsBuilder builder = new StreamsBuilder();

        // 用构造好的builder将mystreamin topic 数据写入到 mystreamout topic
        builder.stream("in").to("out");

        // 构建 Topology 结构
        Topology topology = builder.build();
        final KafkaStreams kafkaStreams = new KafkaStreams(topology, prop);

       // 固定的启动方式(这里就不介绍其他的启动方式了)
        CountDownLatch latch = new CountDownLatch(1);
        Runtime.getRuntime().addShutdownHook(new Thread("kafkaStreaming") {
            @Override
            public void run() {
                kafkaStreams.close();
                latch.countDown();
            }
        });

        kafkaStreams.start();
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.exit(0);
    }
}

实例2:

实现一个计算数字总和,从一个topic传入数值,从另一个topic得到累计的数值

import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.common.serialization.Serdes;
import org.apache.kafka.streams.*;

import java.util.Properties;
import java.util.concurrent.CountDownLatch;

public class SumStreamDemo {
    public static void main(String[] args) {
        Properties prop = new Properties();
        prop.put(StreamsConfig.APPLICATION_ID_CONFIG, "sum");
        prop.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, "num01:9092");
        prop.put(StreamsConfig.COMMIT_INTERVAL_MS_CONFIG, 3000);
        prop.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "false");
        prop.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
        prop.put(StreamsConfig.DEFAULT_KEY_SERDE_CLASS_CONFIG, Serdes.String().getClass());
        prop.put(StreamsConfig.DEFAULT_VALUE_SERDE_CLASS_CONFIG, Serdes.String().getClass());

        StreamsBuilder builder = new StreamsBuilder();
        builder.stream("sumIn") // 从sumin主题获取数据
                .map((key, value) -> new KeyValue<>("sum", value.toString()))	// 因为上面指定的是String类型的value值,所以将数值转为String类型
                .groupByKey()
                .reduce((value1, value2) -> {	// 数值相加功能,顺带输出下中间计算的结果,逻辑和spark的reduce功能完全相同
                    int sum = Integer.valueOf(value1) + Integer.valueOf(value2);
                    System.out.println(Integer.valueOf(value1) + "+" + Integer.valueOf(value2) + " = " + sum);
                    return Integer.toString(sum);
                })
                .toStream().to("sumOut");	// 重新转为stream后输出到sumout主题

        Topology topology = builder.build();
        final KafkaStreams kafkaStreams = new KafkaStreams(topology, prop);

        CountDownLatch latch = new CountDownLatch(1);
        Runtime.getRuntime().addShutdownHook(new Thread("stream") {
            @Override
            public void run() {
                kafkaStreams.close();
                latch.countDown();
            }
        });

        kafkaStreams.start();
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.exit(0);
    }
}

三、窗口

3.1 Hopping time window

跳跃时间窗口,这类窗口需要传入两个参数:size和advance interval,分别代表窗口的宽度和创建创建窗口的时间间隔。每经过一个advance interval就会自动创建一个新的窗口。
窗口遵循左闭右开的原则

3.1 Tumbling time window

滚动时间窗口,是跳跃时间窗口的一种特例,当跳跃时间窗口的size和advance iterval值相等时,它就变成了滚动时间窗口。

滚动时间窗口只有一个参数:size,表示窗口的尺寸,一个窗口的结束点会是下一个窗口的起始点。窗口之间没有间隙,也不重叠。

size = 5min的滚动时间窗口示意图:

在这里插入图片描述

3.1 Session window

该会话窗口只需要传入一个参数:gap(超时时间,即一个会话窗口超过这个时间间隔,该窗口就会关闭),按key分组,相同的key是一个会话,即使一个会话没有结束,重新获得了另一个key,就会开启另一个会话窗口。
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值