Flink SQL
Flink SQL
详细使用方式请参考:Flink 官方文档
Flink是常用的用来解决实时数据流处理的工具,但其本身对流式数据、批式数据都可以处理(流批一体,Flink1.11)
本文只聚焦于Flink处理流式数据。
常见使用:实时数仓、ETL、CEP(复杂数据流处理)、双流 Join(两个不同的数据流按照某种条件进行关联操作,以产生一个包含两个流中元素关联信息的新流)、维表 Join等。
Flink的使用可以归为三步:Source->Deal->Sink
- 规定原表Source(假设数据为水流,这就是一个水龙头)
- 数据的源头可能是:MQ、HIVE、MYSQL等
- 进行处理操作、聚合操作:对Source流来的数据流进行处理,
- 写入下游表Sink
- 写入的下游可能是:MQ、HTTP(每条数据触发一次服务调用)
Flink时间属性
Flink支持三个时间属性:
- **事件时间(Event Time)**:代表数据在产生时的时间,格式是TIMESTAMP、单位是ms(13位数字)
- 摄取时间(ingestion time): Flink 读取事件时记录的时间(一般不关心这个时间)
- **处理时间(processing time)**: Flink pipeline 中具体算子处理事件的时间
事件、处理时间想要正常工作,必须得在source标明,如下SQL:1
2
3
4
5
6
7
8
9
10CREATE TABLE test_stream(
a INT,
b BIGINT,
`TIMESTAMP` BIGINT, -- 数据源的时间戳字段
ts AS LONG_TO_TIMESTAMP(`TIMESTAMP`), -- 此处就标明了事件时间
WATERMARK FOR ts AS ts - INTERVAL '5' SECOND
) WITH (
type = 'kafka',
...
);
WATERMARK
上述的SQL,除了事件事件外,还有一个WATERMARK
WATERMARK是一个时间戳,含义是:当一个Event Time小于WATERMARK值的时候将不再出现
注意:
- 只有基于 event time 的处理需要用到 watermark。(只要使用了事件时间,就要加watermark)
- 基于 process time 的处理不存在乱的问题
为什么要有WARTERMAKR?
理想情况:每一个packet随时间依次到达,这种情况下,我们随便切一下,都是当前时间最早的一个packet。
实际情况:包是乱序到达的,这意味着,我们不能确定当前的包是不是最早的,因此我们只能在一段时间内,拿一个主意,认定某一个是最早的数据。(watermark的作用即定义了何时停止等待较早的时间)
1 | -- 数据乱序到达: |
比如,当”4”数据包到来的时候,4就是最早的数据吗?我们就要从4开始之后的计算处理吗?
从上帝视角看,2才是,但是2真的是最早吗?如果之后1出现了怎么办?
Flink是实时计算,我们必须在一定的时间内拿出一个主意进行计算,因此,watermark规定多长时间停止等待最早的数据出现。
滑动窗口
滑动窗口:一个算法概念,只透出窗口内的值,窗口在数据流上滑动。
滑动窗口有两个变量:
- 步长(window slide):每次窗口移动的距离
- 窗口大小(window size):窗口大小
1
2-- HOP(时间属性列, 滑动步长, 窗口大小)
hop(ts, INTERVAL '5' MINUTE, INTERVAL '5' MINUTE); --申明滑动窗口滚动窗口
类似于翻书,滚动窗口相当于滑动窗口步长=窗口大小
的特殊情况
1 | -- TUMBLE(时间属性字段, 窗口大小) |
滑动窗口和滚动窗口在工程上如何使用?
现在我们要实时统计24h内的某个商品的数量,并且当数量大于1w时进行一些通知操作:
我们可以结合滚动窗口和滑动窗口,使用滚动窗口减少计算量,滑动窗口完成状态判断
- 滚动窗口:我们可以定义一个5min的滚动窗口,每5min聚合一次计算这期间的数量。
- 滑动窗口:滑动窗口统计所有滑动窗口的聚合值,判断是否超过1w,进行对应操作
注意:滚动窗口或是滑动窗口必须是最后一步处理操作,之后必须写入sink,因此如果想结合使用,可以将滚动窗口的值写入sink,比如:
- source(源数据的mq)->滚动窗口->sink1
- source(sink的mq)->滑动窗口->sink2
sink1和sink2可以使用一个字段进行区别,这样我们就可以复用同一个mq来存储两个数据的sink