阿里实时任务计算blink调优技巧

watermark

实时计算可以基于时间属性对数据进行窗口聚合。基于的Event Time时间属性的窗口函数作业中,数据源表的声明中需要使用Watermark方法。

Watermark是一种衡量Event Time进展的机制,它是数据本身的一个隐藏属性,Watermark的定义是数据源表DDL定义的一部分。Flink提供了如下语法定义Watermark。

Watermark 是插入到数据流中的一种特殊的数据,watermark 上带了一个时间戳,其含义是:在这个之后不会收到小于或等于该时间戳的数据。假设数据的乱序程度是1分钟,也就是说等1分钟之后,绝大部分迟到的数据都到了,那么我们就可以定义 watermark 计算方式为偏移1分钟。

总结:
WaterMark的含义是所有时间 t’< t 的事件都已经发生。假如watermark t已经生效,那么后续eventTime小于t的记录都会被丢掉(暂时blink的做法是丢弃这些来的更晚的数据,以后会给用户配置,让更晚的数据也能继续update)。
针对乱序的的流,watermark 至关重要,这样即使一些事件延迟到达,也不至于过于影响window窗口的计算的正确性。
一个物理算子节点在运行时会有多条输入流,算子的watermark取所有流的watermark的最小值。
WATERMARK [watermarkName] FOR <rowtime_field> AS withOffset(<rowtime_field>, offset)
通常一条记录中的某个字段就代表了该记录的发生时间。例如,表中rowtime字段的类型为TIMESTAMP,1501750584000(2017-08-03 08:56:24.000)。定义一个基于该rowtime列,偏移4秒的Watermark的示例如下。

WATERMARK FOR rowtime AS withOffset(rowtime, 4000)
这条数据的Watermark时间为 1501750584000 - 4000 = 1501750580000(2017-08-03 08:56:20.000)。这条数据的Watermark时间含义:时间戳小于1501750580000(2017-08-03 08:56:20.000)的数据已经全部到达。

说明
在使用Event Time Watermark时的rowtime必须是TIMESTAMP类型。当前支持毫秒级别的、在Unix时间戳里是13位。如果是其他类型或是在Unix时间戳不是13位,建议使用计算列完成转换。
Event Time和Processing Time的只能在源表上声明。

Flink支持三种与流数据处理相关的时间概念:Processing Time、Event Time和Ingestion Time。
Flink SQL仅支持其中的两种时间类型Event Time和Processing Time:
Event Time:您提供的事件时间(通常是数据的最原始的创建时间)。Event Time必须是您提供在数据储存里的数据。
Processing Time:系统对事件进行处理的本地系统时间,单位为毫秒。

时间属性字段传递
目前,时间属性字段经过如下两类算子操作后会失去时间属性,此时再使用此字段进行开窗会出现类似“org.apache.flink.table.api.ValidationException: Window can only be defined over a time attribute column.”的错误:
什么情况下会导致WaterMark属性丢失
1.group by
2.双流join
3.CEP
4.over窗口的partition by

Event Time

Event Time也称为Row Time。EventTime时间属性必须在源表DDL中声明,可以将源表中的某一字段声明成Event Time。目前只支持将TIMESTAMP类型(将来会支持LONG类型)声明成Row Time字段。如果源表中需要声明为Event Time的列不是TIMESTAMP类型,需要借助计算列,基于现有列构造出一个TIMESTAMP类型的列。

由于数据本身的乱序、网络的抖动(网络堵塞导致的数据传输延迟的变化)或者其它原因,导致了数据到达的顺序和被处理的顺序,可能是不一致的(乱序)。因此定义一个Row Time字段,需要明文定义一个Watermark计算方法。

MiniBatch 的优势:

1.提升吞吐
2.减少 state 访问
3.减少序列化/反序列化的开销
4.减少输出,降低对下游压力

表示整个job允许的延迟

blink.miniBatch.allowLatencyMs=5000

单个batch的size

blink.miniBatch.size=1000
miniBatch设置: 该设置只能优化group by。
Stream SQL纯流模式下,每来一条数据都会去操
作state,io消耗较大,设置miniBatch后,同一个
key的一批数据只访问一次state,且只输出最新
的一条数据,即减少了state访问也减少了向下游
的数据更新

双流 Join – 优化技巧总结

优化解决问题备注
MiniBatch提升吞吐,降低对下游压力
–2.0 版本已经支持
blink.miniBatch.join.enabled=true
blink.miniBatch.allowLatencyMs=5000
blink.miniBatch.size=1000
构造更新流减少 state,state 访问更友好保证正确性前提下,可以对聚合之后的流进行 JOIN,
能减少减小 JOIN 节点的 state。需改造 SQL。
快慢流导致 NULL 热点问题改变 JOIN 先后顺序,避免 JOIN 节点出现大量 NULL
key。
Join Reorder# Blink 未来接入catalog,能做到自动优化,目前需手工调整
多级 JOIN 导致 state 数据放大先 JOIN 小流,后 JOIN 大流。或者说优先 JOIN 结果
数据量小的

维表 Join – 优化技巧总结

优化解决问题备注

启用 LRU 缓存策略

cache=‘LRU’
LRU缓存使用最近使用缓存策略。减少数据库# 缓存大小,1万条
的访问。cacheSize=‘10000’

缓存失效时间, 10分钟

cacheTTLMs=‘600000’
启用 LRU 缓存策略
LRU缓存+Async IO减少 IO 等待,提升 CPU 利用率cache=‘LRU’
开启异步请求
async=‘true’

启用 ALL 缓存策略

ALL 缓存减少数据库访问cache=‘ALL’

每10分钟重新加载一次全表

cacheTTLMs=‘600000’
最佳实践: 在使用维表 JOIN 时,如果维表数据不大,或者 miss key (维表中不存在的 key)非常多,则可
以使用 ALL cache,但是可能需要适当调大节点的内存,因为内存需要能同时容纳下两份维表拷贝。如果用
不了 ALL cache,则可以使用 Async + LRU 来提高节点的吞吐。

手动性能调优—拆分节点

如果在调优的过程中发现虽然调大了某个Group的资源配置但是并没有太大的效果,需要把其中的Operator节
点全部拆开,来判断到底是哪个子节点有异常。如果找到了该子节点只需调优该节点就好。 将Operator子节点
拆开的方法:点击需要修改的Operator,将其参数chainingStrategy修改为HEAD,若其已为HEAD,需要将其
后面的第一个Operator修改为HEAD。 chainingStrategy三个参数的解释如下:
lALWAYS:代表把单个的节点合并成一个大的GROUP里面。
lNEVER:保持不变
lHEAD :表示把在合并成一个GROUP里面单个节点查分出来

手动性能调优—可调参数

可调参数:
● parallelism(并发):
source
资源根据上游Partition数来。例如SOURCE的个数是16,那么source的并发可以配置为16,8,4等,不要超过16。≤上游shrad数
中间的处理节点
根据预估的QPS计算。对于小任务来说,和source一样的并发度就够了。QPS高的任务,可以配大点,例如 64,128 或者 256。
sink节点
并发度和下游存储的Partition数相关,一般是下游Partition个数的2~3倍。如果配置太大会导致写超时或失败。例如下游SINK的个数是
16,那么sink的并发最大可以配置48。
● core: CPU,默认 0.1,根据实际CPU使用配置(但最好能被1整除),一般建议0.25
● heap_memory: 堆内存,默认 256MB,根据实际内存使用配置点击GROUP就可以编辑以上参数。
● 如果有GROUP BY 的TASK节点可以配置以下参数:
state_size: state大小,默认0。如果operator有用state,需要把state_size配成1,表示该operator会用state,job在申请资源的时候会额
外为该operator申请内存,供state访问使用;如果不配成1,job可能被yarn kill。(state_size需要配成1的operator有:group by, join,
over, window) 虽然有这么多配置项,对普通用户来说,只需要关心:core,parallelism和heap_memory。整个job 建议
core:mem=1:4,即一个核对应4G内存。

Q:Vertex拓扑中看不到持续反压,但延迟却非常大,为什么?
A:可能性1:若延时直线上升,需考虑是否上游source中部分
partition中没有新的数据,因为目前delay统计的是所有partition
的延时最大值;
可能性2:Vertex拓扑中看不到持续反压,那么性能瓶颈点可
能出现在source节点,因为source节点没有输入缓存队列,即使有
性能问题,IN_Q也永远为0(同样,sink节点的OUT_Q也永远为
0)。
解决方案:通过手动配置调优,将source节点(GROUP)中的
operator中chainingStrategy修改为HEAD,将其从GROUP中拆
解出来。然后上线运行后再看具体是哪个节点是性能瓶颈节点,若
依然看不到性能瓶颈节点,则可能是因为上游source吞吐不够,需
考虑增加source的batchsize或增加上游source的shard数。

猜你喜欢

转载自blog.csdn.net/weixin_43975771/article/details/103185799