我正在从事一个欺诈性交易检测项目,该项目利用了星火,主要使用基于规则的方法对传入交易进行风险评分。对于这种基于规则的方法,将从历史数据中创建几个地图以表示交易中的各种模式,然后在为交易评分时使用这些模式。由于数据大小的快速增长,我们现在正在修改代码以在每个帐户级别生成这些地图。
以前的代码用于 p>
createProfile(clientdata)
但现在变成了
accountList.map(account=>createProfile(clientData.filter(s"""account=${account}""")))
使用这种方法可以生成配置文件,但是由于此操作是顺序进行的,因此似乎不可行。
此外,createProfile函数本身正在利用数据帧,sparkContext / SparkSessions,因此,这导致无法将这些任务发送到工作节点的问题,因为根据我的理解,只有驱动程序才能访问数据帧和sparkSession / sparkContext。因此,以下代码不起作用
import sparkSession.implicit._
val accountListRdd=accountList.toSeq.toDF("accountNumber")
accountList.rdd.map(accountrow=>createProfile(clientData.filter(s"""account=${accountrow.get(0).toString}""")))
上面的代码不起作用,但是代表了所需输出行为的逻辑。
我正在研究的另一种方法是使用scala Future在驱动程序级别使用多线程。但是即使在这种情况下,在单个createProfile
函数调用中也会创建许多jvm对象,因此通过增加线程,甚至如果这种方法可行,则可能导致大量jvm对象,而这些对象本身可能导致垃圾回收和内存开销问题。
仅从时间角度来看,单个帐户的createProfile平均需要大约10分钟,而我们有3000个帐户,因此顺序需要花费很多天。使用多线程,即使我们达到10的倍数,也将需要很多天。因此,我们需要100s左右的并行度。
如果存在的话,可能有用的一件事是.let让我们说,如果在groupBY类型的操作中存在诸如spark groupBy之类的东西,那么在第一层,我们可以按“帐户”进行分组,然后执行其他操作 (当前的问题是UDF无法处理我们要执行的操作)
另一种可行的解决方案是SPark Streaming的工作方式-
它具有forEachRDD
方法和spark.streaming.concurrentjobs
参数,该参数允许并行处理多个RDD。我不确定它是如何工作的,但是也许这种实现可能会有所帮助。
上面是问题描述和我对它的当前看法。
请让我知道是否有人对此有任何想法!而且,我宁愿进行逻辑更改,也不愿提出其他技术建议