Spark : 多线程提交优化多Job任务

介绍

在日常业务中,spark常见的就是通过路径通配符*,{}等方式一次读取多个文件,一次批处理将这些文件做一个大job写入Hive或者ODPS,笔者最近在用Spark读取Hudi的文件时候发现了一个诡异的文件丢失Bug:

一次读入所有文件夹会有部分文件夹丢失,一开始怀疑是这部分文件夹本身有损坏,但是用spark单独读取该文件夹的时候发现数据又不会丢失.

既然一次job会丢数据,那么不妨按文件夹拆分job,每个job执行单个任务,常见就是for循环去遍历所有文件夹挨个执行,但是效率过低需要

六个小时,在资源不变的情况下用多线程提交,成功把时间缩短到了一个小时.与全文件读取效率相当.

code

import java.util.concurrent.Executors
import scala.collection.JavaConverters.asScalaSetConverter
import scala.concurrent.duration.{Duration, HOURS}
import scala.concurrent.{Await, ExecutionContext, ExecutionContextExecutorService, Future}


def runJobDirByDir(conf:Config,prefix:String):Unit = {
	assert(prefix.startswith("oss://"),"a legal path should starts with [oss://]")
	//spark framework多个类要用到spark,所以用了ThreadLocal共享spark环境
	val spark = EnvUtils.take 
 	// 自己写的oss文件系统工具,作用是列举文件夹
	val ofs = new OssSystemUtil(conf)
	val projects = ofs.listDir(prefix)
	val pool = Executors.newFixedThreadPool(5)
	implicit val xc:ExecutionContextExecutorService = ExecutionContext.fromExecutorService(pool)
	//因为子线程的ThreadLocal里面没有sparkEnv,所以在这传进去
	val tasks = projects.map(x=> runFutureTask(spark,x)) 
	Await.result(Future.sequence(tasks.toSeq),Duration(5,MINUTE))
}

def runFutureTask(spark:SparkContext, dir:String)(implicit xc: ExecutionContext)
	:Future[Unit]= Future{
    //TODO run single dir 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值