spark sql中踩到的一个坑,自定义Udf会执行多次,即使在已经cache table的情况下
来源:互联网 发布:虚拟机上装linux 编辑:程序博客网 时间:2024/04/29 20:15
spark sql中踩到的一个坑,自定义Udf会执行多次,即使在已经cache table的情况下: https://issues.apache.org/jira/browse/SPARK-15282
以前也没发现这个问题,因为如果一个UDF是无状态的话,其实执行多次并不会导致结果的最终一致性被打破,说来也巧啊,最近写了一个UDF里面封装了redis的hsetnx操作
val hsetnx_expire = (key: String, field: String, value: String, expire: Int) => { if (field != null && field.trim.length > 0) { CommonRedisPool.withJedis(jedis => { try { val ret = jedis.hsetnx(key, field, StringUtils.defaultString(value, "")) if (expire > 0) { jedis.expire(key, expire) } if (ret == 1) true else false } catch { case e: Exception => throw new RuntimeException(s"===================${e.getMessage},key:$key,field:$field,value:$value") } }) } else { false } }
这个udf要是被执行了多次那就要了命了,会多次尝试往redis里插入数据,如果插入一个不存在的field,那么第一次返回为true,再执行返回的是false。
而我恰好要用到这个返回结果来判断是不是一个新设备ID。
举个例子:
cache table my_test as select *, hsetnx_expire_day(concat('sdk_stat_pay_dt.' , dt),pay_uid,channel) as is_pay_dt, hsetnx_expire_day(concat('sdk_stat_pay_dt.',dt,'.',hr),pay_uid,channel) as is_pay_hr from cache_xyzs_sdk_stat where type='order' and isnotnull(pay_uid)我这里讲每天的新增充值uid保存进redis,然后将执行结果做出来一个新的字段is_pay_dt(注意我上面已经是cache table my_test了),然后我再去执行查询这个字段的时候:
select * from my_test。我曹,返回的是is_pay_dt返回的是false。根据在udf中打日志追踪,发现UDF被执行了多次,虽然cache了,但是还是会重新计算。
这应该算是dataframe上的一个bug,因为执行dataframe.rdd.cache(),在将rdd重新注册成表,再去查询,是不会再重新计算新字段了。
目前我尝试了两种方式来绕过这个问题,
1:就是上面说的,把dataframe.rdd.cache(),在将rdd重新注册成表来进行查询,这种方式有个问题,没法uncache table。只能使用前面注册的rdd.unpersist
2: 简单粗暴一点,将结果collect回来,重新注册表,后面不用的时候可以uncache table。缺点就是collect到driver上如果数据量大的话其实有一些影响。
另外在使用有状态的UDF的时候要特别的谨慎小心,连嵌套子查询都不能有:
select * from
select hsetnx_expire_day(concat('sdk_stat_pay_dt.' , dt),pay_uid,channel) as is_pay_dt
from cache_xyzs_sdk_stat
) a
这种也会导致里面的hsetnx_expire_day被执行两次,然后最终的is_pay_dt也会返回个false。
所以要有状态, 一定保证一层查询,然后collect结果回来重新注册表,这也是我现在用的方法,虽然有点粗糙。
- spark sql中踩到的一个坑,自定义Udf会执行多次,即使在已经cache table的情况下
- 一个即使在init方法中调用,也会保证onEnter之后执行的小技巧
- jquery在某种情况下绑定click事件会触发多次click的解决方案
- spark sql cache table
- 自定义spark udf计算单词的长度
- Service 的 onRebind(Intent)方法在什么情况下会执行?
- 单片机中的ALE脚在执行什么指令的情况下会输出?
- 【PHP基础知识点】在if满足的情况下,else if会执行吗?
- 13.Spark SQL:UDF自定义函数实战
- 当case后有语句时,break不能省略,在没有default的情况下,最后一个case后即使没有语句,也要加上break。
- 由于原本的小弹框toast在极限操作的情况下会出现悬停不消失,所以我们自定义一个toast
- VB+SQL数据库管理系统中,如何在无数据源的情况下执行SQL
- VB+SQL管理系统中,如何在无数据源的情况下执行SQL
- VS2013在Release情况下使用vector有时候会崩溃的一个可能原因
- spark sql udf 解析json数据表的嵌套数组
- Spark(Hive) SQL中UDF的使用(Python)
- HOOK截获中文输入会出现响应多次的情况。
- HOOK截获中文输入会出现响应多次的情况
- 【bzoj2115】[Wc2011] Xor
- 【HDU3949】XOR
- 【bzoj1834】[ZJOI2010]network 网络扩容
- Lucene开发实例(一般企业搜索平台完全够用全程)
- 【bzoj1602】牧场行走 lca
- spark sql中踩到的一个坑,自定义Udf会执行多次,即使在已经cache table的情况下
- 【bzoj3670】动物园 kmp
- 【bzoj1030】文本生成器 AC自动机+树型dp
- 【leetcode】463. Island Perimeter【E】
- 曹冲养猪 中国剩余定理
- 【HDU1573】X问题 中国剩余定理
- 【bzoj2818】Gcd 欧拉函数
- java自带线程池和队列详细讲解
- git笔记:一篇搞懂git是个什么玩意