@TOC
踩坑背景
流程如下所示:
1.使用SparkSQL获取到了一个DataFrame;
2.然后map这个DataFrame,调用GET接口,获得了IDs作为一个新的DatdaFrame;
3.最后再map这个DataFrame,在map中调用Post接口,将最终结果放到接口中。
踩坑原因
因为比较懒,所以在spark-submit的时候,脚本直接复制了另外一个Spark作业的提交脚本,但是万万没想到的是:这个脚本里,有一句设置:--conf "spark.speculation=true"
,当时没注意,直接提交上去了。
后来反馈最终的Post接口存在重复调用的问题,有的name会调用两次post接口,有的则只会调用一次。
解决
最后通过咨询大佬得知,在严格执行只能计算一次时,一定要把Spark的检测执行关掉!也就是说,不要在代码或者脚本里设置spark.speculation=true
,此配置Spark默认为false。
原因
当Spark开启检测执行时,它会根据数据片的执行时间来启动第二次执行。即当partition1里的数据在executor1上执行超过一定时间,但是仍然没有执行完毕时,此时executor2会起一个程序开始运行partition1里的数据,哪个先运行完,就把剩下那个没运行完的kill掉,返回最终结果。
因为我的代码中,获取Post连接的时间可能比较长,超出了检测执行的时间范围,于是部分超出检测执行范围的name被启动了executor2计算,虽然在最终的返回状态结果中只有一份数据,但是它实际上已经调用了两次,看到的返回状态结果已经不准了。
教训
别瞎cv,所有提交的东西都要搞清楚,细细思考过才可以。