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<String, String> stream = builder.stream(Serdes.String(), Serdes.String(), topics);
stream.filter(new Predicate<String, String>() { (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<String, Object> configMap =
KafkaConfigBuilder.buildKafkaConfig(configuration, information, "PullUserFromService");
StreamsConfig config = new StreamsConfig(configMap);
streams = new KafkaStreams(builder, config);
流拓 & Task
问题:
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的作者明确不推荐这种流处理方式。对于设计高性能流处理系统,在内部去调用第三方接口可能严重影响流处理吞吐量,
最好是提前将数据同步到本地缓存中,推荐系统内调用。

Kafka Streams是一个Java类库,不同于传统的流处理框架。它强调流数据的有序性、不可变性和可重播性,拥有无外部依赖、低延迟、支持状态操作等优势。适合用于事件驱动的实时处理场景,并提供了丰富的处理原语和DSL。
976

被折叠的 条评论
为什么被折叠?



