kafka Streams学习

kafka Streams学习


牢记Kafka Streams是一个Java类库,不是一个流处理框架,这点和Strom等流处理框架有明显的不同

什么是流?

无边界(源源不断)数据集的抽象表示。

为什么要用流式处理:

面向数据流的响应式编程(RP Reactive Programming)已经越来越普及,响应式编程对于无边界数据处理更有优势。 

流的特性:

  • 事件流是有序的。
    • 流数据是自带时序的,无需人工排序。
  • 事件流是不可变的数据记录。
    • 现对于数据库行记录看到的只是最终的结果,流记录了每次变更,是不可变的。
  • 事件流是可以重播的。
    • 如果系统异常或者原有业务处理逻辑优化,可以重复使用流数据,验证、优化业务。

kafka 流的优势:

  • 除了Kafka外,无任何外部依赖
  • 它只是一个类库,它可以非常方便地嵌入任意Java应用中,也可以任意方式打包和部署
  • 支持单事件处理、基于时间窗口连接和聚合处理。
  • 充分利用Kafka分区机制实现水平扩展和顺序性保证
  • 支持正好一次处理语义。
  • 提供记录级的处理能力,从而实现毫秒级的低延迟
  • 通过可容错的state store实现高效的状态操作(如windowed join和aggregation)
  • 支持基于事件时间的窗口操作,并且可处理晚到的数据(late arrival of records)
  • 同时提供底层的处理原语Processor(类似于Storm的spout和bolt),以及高层抽象的DSL(类似于Spark的map/group/reduce)
  • 重放数据能力,便于代码优化,系统恢复。

流式处理场景:

如果追求低延时,高效率,推荐使用请求应答方式的应用。
如果追求的只是消息的消费,那么Kafka Connect【1】可能是一个更好的选择。
流式处理特别适用于数据量较大实时性要求较高的计算类应用,例如实时报表,机器学习,推荐算法等。

示例:

    KStreamBuilder builder = new KStreamBuilder();
    KStream stream = builder.stream(Serdes.String(), Serdes.String(), topics);
    stream.filter(new Predicate() { (1)
        @Override
        public boolean test(String key, String value) {
            return true;
        }
    }).map(new KeyValueMapper() { (2)
        @Override
        public Object apply(Object key, Object value) {
            String userJson = service.getByOtherId((String) value, "", "", "", "", 1, 0);【2】
            JSONObject jo = JSON.parseObject(userJson);

            if (GlobalRespCodes.SUCCESS.equals(jo.get("respCode"))) {

            } else {
                LOGGER.error("getByOtherId error:");
            }

            return new KeyValue(value, JSON.toJSONString(jo));
        }
    }).to("output"); (3)

    Map configMap =
            KafkaConfigBuilder.buildKafkaConfig(configuration, information, "PullUserFromService");
    StreamsConfig config = new StreamsConfig(configMap);
    streams = new KafkaStreams(builder, config);    

流拓 & Task

kafka Streams学习_第1张图片
kafka Streams学习_第2张图片

问题:

1. 默认情况下流业务异常,是否会重复消费消息。
    不会,自动提交模式下,会持续处理,最后提交偏移量。
2. 流内调用其它系统超时是否会影响流的处理【2】。
    会重新分配消费,系统判断Consumer异常,发起rebalance。超时的Consumer提交消费消息报CommitFailedException,
    应为该partition已经重新分配给其它Consumer提交失败。 
3. 流处理并发性。
    流处理是多线程运行,默认情况下只启动一个线程,启动线程个数可以配置(num.stream.threads)。
4.  broker如何判定consumer已经停止工作。
    心跳和poll()都不再工作,broker会在session到期后删掉相应的consumer。
5.  Topic,Partition,Task,WorkerThread关系。
    假定Stream的输入Topic有两个(1个Partition数为4,另一个Partition数为3),则总的Task数等于Partition数最多的那个
    Topic的Partition数(max(4,3)=4)。这是因为Kafka Stream使用了Consumer的Rebalance机制,每个Partition对应一
    个Task。系统默认只启动一个WorkerThread,我们可以修改num.stream.threads启动多个线程,线程对应consumer处理对应
    的Task。
    for (TopicPartition partition : records.partitions()) {
        StreamTask task = activeTasksByPartition.get(partition);//初始化Task
        numAddedRecords += task.addRecords(partition, records.records(partition));
    }
6. 流中每个分区的offSet是什么时候提交的。
    poll()获取分区数转为streams对应的task,当task都执行完,一起提交offSet。

关键参数:

auto.offset.reset ,没有偏移量或者偏移量无效的情况下处理方式(latest,earliest)。
heartbeat.interval.ms,向协调器发送心跳的频率,证明该线程还活着(默认:3000ms)。
max.poll.interval.ms ,poll()间隔最长时间,该时间范围内未poll请求,认为该线程已经挂断,重新rebalance。(0.10.2.*开始     
  默认值 300000 改为 Integer.MAX_VALUE.)
session.tomeout.ms ,消费者可以多久不发送心跳,判断整个进程是否还活着(默认:10000ms)。
num.stream.threads 流工作线程个数。

常用命令(0.10.2.*)

显示消费者群组
    kafka-consumer-groups  --bootstrap-server 127.0.0.1:9092 --list
查看指定消费者群组详细信息 
    kafka-consumer-groups  --bootstrap-server 127.0.0.1:9092 --group TSyncer.PullUserService --describe

备注:

【1】 Kafka Connect 主要服务于外部数据存储系统之间(例如:MongoDB同步数据到MySQL)可靠,可伸缩的连接器。
【2】 kafka的作者明确不推荐这种流处理方式。对于设计高性能流处理系统,在内部去调用第三方接口可能严重影响流处理吞吐量,
     最好是提前将数据同步到本地缓存中,推荐系统内调用。

你可能感兴趣的:(JAVA,kafka,IT)