这是我参与「第四届青训营 」笔记创作活动的的第4天
今天笔记主要分为四个部分:
实时计算分为处理时间和事件时间:
- 事件时间:数据产生的时间。
- 处理时间:数据在流式计算系统中真正处理时所在机器的当前时间。
实时计算的核心功能
Watermark机制
watermark就是系统认为当前真实的事件时间。
Watermark机制就是在数据流中插入一些真实时间,如果之后有比这个时间小的时间,那我们就可以认定这个时间戳对应的数据是延迟数据,不影响之前窗口的结束。
watermark的传递
watermark一对一传递时下游直接采用上游的watermark;watermark一对多传递时,下游选择多个上游传来的watermark里面最小的watermark作为自己的watermark
watermark的典型问题
- 生成策略的问题:
Per-subtask watermark生成造成的问题时如果一个source subtask消费多个partution,那么多个partition之间的数据读取可能会加剧乱序程度。
Per-subtask watermark生成策略基于每个partition单独的watermark生成机制,有效避免了上面的问题。
- 部分partition/subtask断流:
如果上游一个suntask的watermark不更新了,那么下游的watermark也不更新了。
解决方案:Idle source
当某个subtask断流超过配置的idle超时时间时,将当前subtask置为idle,并下发一个idle的状态给下游,下游在计算自身的watermark时,可以忽略当前是idle的那些subtask。使正常数据可以流通。"
- 迟到数据的处理
- window聚合,默认会丢弃迟到数据
- 双流join,如果是outer join,则可以认为它不能join到任何数据
- CEP,默认丢弃
Window机制
分类
- Tumble Window(滚动窗口)
- Sliding Window(滑动窗口)
- Session Window(会话窗口)
- .....
3大基本窗口类型的定义、使用以及核心原理
1. Tumble Window(滚动窗口)
- 窗口划分:
- 每个key单独划分
- 每条数据只会属于一个窗口
- 窗口触发:
Window结束时间到达的时候一次性触发。
2. Sliding Window(滑动窗口)
- 窗口划分:
- 每个key单独划分
- 每条数据可能会属于多个窗口
- 窗口触发:
Window结束时间到达的时候一次性触发。
3. Session Window(会话窗口)
- 窗口划分:
- 每个key单独划分
- 每条数据会单独划分为一个窗口,如果window之间有交集,则对窗口进行merge
- 窗口触发:
Window结束时间到达的时候一次性触发。
窗口机制中的最核心的优化以及原理
迟到数据处理
- 定义:一条数据到来后,会用WindowAssigner给他划分一个window,如果划分出来的窗口末尾比当前watermark值还小,则被认为是迟到数据。
- 只有事件时间下才会有迟到的数据
- 迟到数据的默认处理是丢弃
- 处理机制:
- Allow lateness
这种方式就是设置一个允许迟到的时间,设置之后,窗口正常计算。结束后,不会马上清理状态,而是多保留
Allow lateness这么长时间,如果期间有数据姗姗来迟,会继续之前的状态进行计算。适用于DataStream、SQL.
个人理解就是给数据一定时间的迟到缓冲区,就像上班迟到了,只要你没迟到太久,没有过了老板允许的时间就行。
- SideOutput(侧输出流)
这种方式是对迟到数据添加一个标签,然后在数据流上根据这个标签去获取迟到数据流,在业务层面自行选择进行处理。适用于DataStream。
个人的理解就是给迟到员工在考勤上打个记号,看后期老板咋处理。
增量VS全量计算
增量计算
每条数据到来,直接进行计算,window只存储计算结果,不需要保存每条数据。典型函数有reduce、aggregate。SQL的聚合只有增量计算。
全量计算
每条数据到来,会存储到window的state中,等到window触发计算时,将所有数据拿出来一起计算。典型函数有process.
EMIT触发
背景:当窗口比较大,那么计算结果输出延迟就比较高,失去了实时计算的意义。
定义:在window没有结束的时候,提前把window计算的部分结果输出出来。
实现:在DataStream中通过自定义Trigger来实现,Trigger结果有:
- CONTINUE
- FIRE(触发计算,但是不清理)
- PUREG
- FIRE_AND_PURGE
高级优化
mini-batch优化
缺点;输出量大,算子需要保留状态(内存,外部)。
那么就需要解决中间结果偏多, 状态访问较频繁这种缺点,所以引入了人mini-batch优化。
mini-batch就是让算子攒一小批数据,然后小批数据读一次状态,输出,写回数据。
倾斜优化 local-global
倾斜优化计算之前不需要对数据进行shuffle,但需要对数据进行预处理,把中间结果发到最终去处理。使热点问题得以缓解。
Distinct计算状态复用
当用户的sql语句写成如上代码所示时,那么就可以优化成下面图表所示。
Pane优化
当有窗口交叠的时候,如果我们计算所有交叠牵扯的窗口的话,如果窗口大小很大,但滑动时间太短,则产生的数据过于繁杂。那么我们可以并不在窗口到来的时候直接计算出最后的结果,而是把窗口划分成更小的粒度(pane),那么一条数据只属于一个pane,计算量和存储量就大大减少,但是在最终输出的时候需要合并pane。
案例分析
使用Flink SQL计算抖音的日活曲线
解决方案:滑动窗口+EMIT
方案一:
出现的问题:所有的数据都需要在一个subtask中完成窗口计算,无法并行。
方案二:
通过两阶段聚合来把数据打散,完成第一轮聚合,第二轮聚合只需要对每个分桶的结果求和即可。
使用Flink SQL计算大数据任务的资源使用
解决方案:会话窗口
通过会话窗口将数据划分到一个window中,然后将结果求和即可。