流式数据处理的几个关键点重难点:
- exactly-once
- handle out-of-order data
- one-record-at-a-time processing
kafka Streams
是一个用于实时分析和处理在kafka
中数据的客户端库
它支持:
event time
processing time
windowing
- 实时
app state
管理和查询
kafka Streams
自身的一些亮点:
-
简单和轻量的客户端库,程序开发完成了,直接java jar就可以运行,这个相对
hadoop 、spark
这些集群运行的job来说部署和运行简单很多 - 除了apache kafka 之外,不需要依赖其他系统
- 支持容错的本地状态,比如
window join
和聚合操作 - 支持exactly-once语义
- 支持one-record-at-a-time processing这是真正意义的低延迟实时流(早期的spark是通过small batch实现实时的),支持 event-time based windowing operations
- 提供了high-level Streams DSL 和low-level Processor API的流式处理原语
流式处理拓扑
-
stream是
Kafka Streams
最重要的抽象:它代表了无界,源源不断的数据集。stream是有序,可重放,不可变data record
的序列,data record
被定义为kv
健值对(发给kakfa的数据本身就是kv
类型的,不过k
可以为空)。在拓扑图中这种有向数据流动逻辑上被抽象为边 -
stream processing application通过processor topologies定义计算逻辑。
processor topology
是由stream processor
(节点)和stream
(边)构成的图 -
stream processor
是processor topology
的节点,它代表了一个处理步骤,它每次从上游processors
读取一个输入记录,对它应用操作(算子),然后产生一条或者多条的数据发往下游的processors
在拓扑中有两种特别的processor
:
-
source processor 数据源节点,从
kafka topic
消费数据,没有上游processors
-
sink processor 数据最后存储节点,写到特定的
kafka topic
没有下游processors
Kafka Streams 提供了两种方式用于定义流式处理拓扑:
-
high-level Streams DSL:定义了一些最常用的转换算子
map、 filter、 join 、aggregations
-
low-level Processor API : 允许开发者定义和连接自定义的
processor
和与state stores
交互相关的操作
流式处理拓扑只是流式应用的逻辑抽象,在运行时,这个逻辑拓扑会被实例化,并且分发到应用内部用于并行处理。
Time
流处理的关键就是它的时间模型,比如window 操作就是基于时间边界的:
在流式处理中一般有如下与时间相关的概念:
- Event time 数据产生时间
- Ingestion time kafka 收到数据的时间
- Processing time 数据处理时间
举个例子理解以上时间的概览:
考虑如下场景,手机上的一款app将用户日志数据上报到服务端Kafka,然后app 公司的开发者开发了一个实时处理程序,实时的从kakfa中获取用户上报信息,统计dua。
我们分析一条日志在手机上产生,然后上报到kafka集群,最后由流式程序取出来用于统计这个过程,其中Event time
为app 日志在手机上产生的时间,Ingestion time
为数据上报到kafka的时间,流式程序取出这个日志数据并且进行处理的时间为Processing time
State
实现无状态流式应用比较简单,比如仅仅是从一个流中过滤数据然后发往下一个流
当需要对事件进行count
,avg
,或者多个时间join
时就需要维持状态了,一般流式程序有如下几种状态:
- Local or internal state(本地状态)本地状态直接使用本地内存,优点是快
- External state(外部状态)使用外部系统保存状态,通常是NoSQL
Duality of Streams and Tables
在high-level Streams DSL中提供了对流和表的抽象,分别对应KStream
和KTable
- 表可以看作是当前事件信息的一个快照
- 流则是事件的
changlog
Duality of Streams and Tables
这句话是说在kafka streams
中KStream
和KTable
是可以相互转化的
Windowing
在流上很多操作都是window
操作,也就是在一个时间片上的操作 比如:
-
moving average
各 - 一天发生事件的
top N
-
join
,对相同时间片的事件join
进行window
操作时,我们需要确定如下条件:
- 窗口的大小(
window size
): 每个窗口包含1s
还是1min
还是5min
的事件, - 窗口移动的频率(
advance interval
) : 窗口是每秒更新,还是每分钟更新,还是每到一个新的事件就更新,窗口大小和窗口移动频率一致称之为tumbling window
,每到一个新的事件就更新的窗口称之为sliding window
-
对延迟数据的更新策略:比如可以定义延迟一个小时的数据落在指定窗口视为有效数据,参与计算,大于一小时的数据可以直接丢弃(关于乱序数据的产生和影响,参考Out-of-Order Handling)