flink 有状态udf 引起血案一
场景
近期在做一个画像的任务,sql实现的,当中有一个udf,会做非常多事情,包含将从redis读出历史值加权,并将中间结果和加权后的结果更新到redis。
大家都知道,flink 是能够支持事件处理的。也就是能够没有时间的概念,那么在聚合,join等操作的时候,flink内部会维护一个状态,假如此时你也用redis维护了历史状态,也即是相似 result = currentState(flink)+lastState(redis)。且此时要针对计算的结果用where进行筛选.
SQL例如以下
CREATE VIEW view_count AS
select
`time`,
gid,
cid,
count(feed_id) * 1 as strength
FROM
view_cid
GROUP BY
gid,
cid,`time`;
CREATE VIEW view_strength AS select
`time`,
gid,
cid ,
Get_Strength_Weaken(gid, cid, cast(strength as double), `time`, 0.95) as `result`
FROM
view_count
;
insert into
hx_app_server_sink_common
SELECT
gid,
cid,
`result`
FROM
view_strength
where `result` <> '0.0'
GROUP BY
gid,
cid,
`result`;
业务分析
第一个sql视图完毕的是首先分组,然后统计某一个字段并乘以权重;
第二个sql视图。udf :Get_Strength_Weaken完毕当前值和历史值叠加工作,历史值存储在redis。同一时候将结果返回并更新redis,返回值作为result字段。
第三个sql在输出的时候,result字段作为了where的条件和group by里的字段。
这时候生成的flink概图例如以下:
观察中间的结构图能够发现。Get_Strength_Weaken被调用两次:
1. where条件。这个的生成是因为第三条sql
where `result` <> '0.0'
产生的运行计划,是不是看起来非常懵逼。。
。
2. select里面另一次调用Get_Strength_Weaken。这个非常明显。
当然。能够打印一下flink udf里eval函数的调用细节日志,非常easy发现反复调用的问题。浪院长这个也是通过分析日志。对照输出结果来得出的论。
综合上面分析和udf调用日志,结论就是udf被调用了两次。
对于这个flink的udf被多次调用引起的结果偏大。整整调试了一下午。
因为上面分析能够得出结论,flink将where条件下推了,where 条件推断会先运行,而select里后运行,那么能够调整SQL。例如以下:
CREATE VIEW view_count AS
select
`time`,
gid,
cid,
count(feed_id) * 1 as strength
FROM
view_cid
GROUP BY
gid,
cid,`time`;
CREATE VIEW view_strength AS select
`time`,
gid,
cid ,
getResult(gid,cid) as `result`
FROM
view_count
where Get_Strength_Weaken(gid, cid, cast(strength as double), `time`, 0.95) as `result` <> '0.0'
;
insert into
hx_app_server_sink_common
SELECT
gid,
cid,
`result`
FROM
view_strength
GROUP BY
gid,
cid,
`result`;
那么实际上。select里的udf主要目的是取出来计算结果。那么这个时候能够写个简单的udf--getResult,仅仅让他从redis获取 where条件里更新到redis里的结果,因为该udf是无状态的即使多次调用。也无所谓。
所以。总结一下,对于flink 来说,因为基于事件的处理,聚合、join等操作会有状态缓存,那么此时再用到含有外部存储状态的udf,一定要谨慎,结合运行计划,来合理放置udf的位置,避免出错。
当然。调试阶段最好是有具体的日志。便于分析和定位问题。
flink 状态删除
事实上。flink聚合等内部状态有配置能够使其自己主动删除的,具体配置使用例如以下:
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
StreamTableEnvironment tableEnv = TableEnvironment.getTableEnvironment(env);
// obtain query configuration from TableEnvironment
StreamQueryConfig qConfig = tableEnv.queryConfig();
// set query parameters
qConfig.withIdleStateRetentionTime(Time.hours(12));
// define query
Table result = ...
// create TableSink
TableSink<Row> sink = ...
// emit result Table via a TableSink
result.writeToSink(sink, qConfig);
// convert result Table into a DataStream<Row>
DataStream<Row> stream = tableEnv.toAppendStream(result, Row.class, qConfig);
[完]
推荐阅读:
flink 有状态udf 引起血案一的更多相关文章
- Flink的状态与容错
本文主要运行到Flink以下内容 检查点机制(CheckPoint) 状态管理器(StateBackend) 状态周期(StateTtlConfig) 关系 首先要将state和checkpoint概 ...
- Flink Streaming状态处理(Working with State)
参考来源: https://www.jianshu.com/p/6ed0ef5e2b74 https://blog.csdn.net/Fenggms/article/details/102855159 ...
- Flink之状态之savepoint
1.总览 savepoints是外部存储的自包含的checkpoints,可以用来stop and resume,或者程序升级.savepoints利用checkpointing机制来创建流式作业的状 ...
- Flink之状态之checkpointing
1.前言 在Flink中,函数和操作符都可以是有状态的.在处理每个消息或者元素时,有状态的函数都会储存信息,使得状态成为精密操作中关键的组成部分. 为了使状态能够容错,Flink会checkpoint ...
- Flink之状态之状态存储 state backends
流计算中可能有各种方式来保存状态: 窗口操作 使用 了KV操作的函数 继承了CheckpointedFunction的函数 当开始做checkpointing的时候,状态会被持久化到checkpoin ...
- Flink之状态之状态获取
1.什么是状态 对于任何一个操作,都可以被看成是一个函数,比如y=f(x),如果对于同一个x的任何一次输入,得到的y都是相同的,则可以认为这个函数是无状态,否则,这个函数就是有状态的.Flink的一大 ...
- flink checkpoint状态储存三种方式选择
Flink 提供了三种可用的状态后端:MemoryStateBackend,FsStateBackend,和RocksDBStateBackend. MemoryStateBackend Memory ...
- 「Flink」Flink的状态管理与容错
在Flink中的每个函数和运算符都是有状态的.在处理过程中可以用状态来存储数据,这样可以利用状态来构建复杂操作.为了让状态容错,Flink需要设置checkpoint状态.Flink程序是通过chec ...
- 9、flink的状态与容错
1.理解State(状态) 1.1.State 对象的状态 Flink中的状态:一般指一个具体的task/operator某时刻在内存中的状态(例如某属性的值) 注意:State和Checkpoint ...
随机推荐
- 51Nod1317 相似字符串对 容斥原理 动态规划
原文链接https://www.cnblogs.com/zhouzhendong/p/51Nod1317.html 题目传送门 - 51Nod1317 题意 称一对字符串(A,B)是相似的,当且仅当满 ...
- HDU2586How far away? LCA
去博客园看该题解 题意 给出一棵树,以及每条边的权值,给出一些询问,每个询问是2个节点,求每个询问对应的2个节点的距离. 算法 LCA_Tarjan 代码 #include <cstring&g ...
- P1012 拼数 字符串
题目描述 设有nn个正整数(n≤20)(n≤20),将它们联接成一排,组成一个最大的多位整数. 例如:n=3n=3时,33个整数1313,312312,343343联接成的最大整数为:34331213 ...
- 07. Matplotlib 3 |表格样式| 显示控制
1.表格样式创建 表格视觉样式:Dataframe.style → 返回pandas.Styler对象的属性,具有格式化和显示Dataframe的有用方法 样式创建:① Styler.applymap ...
- 【python】TCP/IP编程
No1: [TCP] 客户端 import socket s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.connect(('www.sina ...
- Dev-C++安装第三方库boost
Dev-C++安装第三方库boost 转 https://www.jianshu.com/p/111571e4d6f5?utm_source=oschina-app 之前鉴于codeblocks界面 ...
- Codeforces 633C Spy Syndrome 2 【Trie树】+【DFS】
<题目链接> 题目大意:给定一个只有小写字母组成的目标串和m个模式串(里面可能有大写字母),记目标串反过来后的串为S,让你从m个模式串中选出若干个组成S串(不区分大小写).输出任意一种方案 ...
- 003.Ceph扩展集群
一 基础准备 参考<002.Ceph安装部署>文档部署一个基础集群. 二 扩展集群 2.1 扩展架构 需求:添加Ceph元数据服务器node1.然后添加Ceph Monitor和Ceph ...
- css position相对定位与绝对定位彻底搞懂
定位position position本身就有给...定位的意思 position属性的值: static ---默认值 relative ---相对定位 absolute ---绝对定位 fixed ...
- SpringBoot使用事务
事务是很多项目中需要注意的东西,有些场景如果没有加事务控制就会导致一些脏数据进入数据库,本文简单介绍SpringBoot怎样使用事务. 本文使用的是之前整合JPA的文章,具体可以参考 传送门. 无论是 ...