使用spark过程中遇到的技术问题及自身问题


最近的一个项目中使用了spark技术过程遇到的一些问题,下面就以问题来分析原因及解决过程

问题

1、创建sparkView没有加限制条件,导致创建几十上百万大数据量的view时,多库的情况下在driver创建了 大量的view,就把driver端的内存撑爆了,之前线上没有暴露出来的这个问题原因主要是每一个小时都会处理一次,每次数据量都不大,后面任务有停了几天,数据量突增了很多,这时就出现很多问题
* 如代码:

2、使用spark过程中只用于查询大数据量的源数据,其中数据运算过程都是在使用JAVA方式满1000条处理,运算过程是逐条进行运算,代码中产生过程多的对象,没有处理完数据一直驻留在内存,造成严重的FULL-GC,sparkUI上面也发现大量任务处于DEAD状态。
* 如代码:

3、运算过程使用大量的JDBC的方式查询关联的它表数据,每条数据每次查询它表几毫秒,一旦数据量放大时,消耗时间也是非常大的,而且运算过程中会按多个步骤顺序查询关联表数据(每个步骤都会做,并没有做缓存机制)。
* 如代码:8053749-c08ec8489fcb02c0.png

4、每条数据进行运算时,都打印出大量日志信息,有些日志信息可以不用输出的,打印日志也是导致性能问题之一。
* 如部分代码:

针对上述这些怀情况已经严重影响到处理速度问题,进行结构上改造,充分利用起spark的技术优势,如下:

  • 1、 重新创建源数据view,对数据按一定条件进行切分及分批并行拉取出来,即加快了拉取速度,也控制了一次加载数据量。如代码:

  • 2、 舍弃每条源数据都去数据库查询相关活动的数据及它表的数据来进行运算,创建相关的view,通过大sql来关联数据。如:

  • 3、 由逐条数据进行运算的方式,改进成通过大SQL中自定义函数来实现匹配运算过程,减少java查询方式运算时导致大量数据对象驻留内存没有释放,也改善并行运算的速度。
    如代码:

  • 4、 减少没有必要的日志输出,将日志输出信息级别调整为debug来减少IO输出。如代码:

  • 5、 解决上述问题后性能提高了几倍,但是也发现存在其它问题,后面发现有各别活动数据量超过一百万,创建view应该按源数据的条件先过滤出来有效数据来进行关联。如代码:

  • 6、 自定义累计器的问题,实现累加计的方法,必须实现几个方法,当时我只用到其中一个add方法,就只正确实现这个方法,其它的方法就随意写了下,如代码:
    结果在运算中调用累加器的时候就报出异常信息,说必须实现copy及reset方法,后面才知道调用累加器时候,它的实现方法中会逐个会被调用到,调用foreachPartition 的时候,会为每个Partition执行一次自定义累加器的copy-》reset-》isZero方法。

  • 7、 使用累加器来收集数据还有一个问题,它存储的数据对象字段非常多是一个很大的对象集,它又是一个共享的数据变量,分发到各个机器上进行操作,它达到一定的数据量才会入库及清空数据,这样导致driver端上经常FULL-GC,分片数据入库依赖于它。如代码:

    解决此问题,将累加器移除掉,任务分区的数据按一定规则进行排序,保证同源数据的id相同的数据在一个分区里,后面累加器修改成局部的Map集合收集数据,这样就将driver端入库操作移到excutor端。

  • 8、 在不断的优化过程中,发现自己的代码存在很多问题,每次review代码时,都会发现可以优化之处,如方法及变量命名不清晰,方法体的代码过长,存在冗余的代码,结构不够清晰,注释太少且不清晰等等。

  • 9、 SparkUI的重要性,有什么问题都可以在上面看到,从中也可以发现出潜在的问题,也能在上面实时观察出任务的运行情况;SparkUI上面虽然只有六个菜单,如何在其中找到我想要数据分析及技术分析的信息,还是值得我学习及研究的。

总结

经过一系列的改造后,从之前的每小时处理200百万数据提升到每小时处理上千万的数据量;在该过程中遇到很多的问题及困难,主要是自己对spark方面的知识了解不够深入,在代码结构及细节上处理上面还不够细致。通过同事们帮助下,顺利地解决了spark性能上的问题

作者:唯品会-蒋先辉
日期:2018.1.22

猜你喜欢

转载自blog.csdn.net/vipshop_fin_dev/article/details/79415140
今日推荐