Using python multithreading in Pyspark to write data to table in parallel

Viewed 776

Original code is a bit huge and has lots of joins and aggregation so just attaching a small snippet

Sample code

from pyspark.sql import SparkSession
from pyspark.sql.functions import *
from multiprocessing.pool import ThreadPool
import pyspark
class do_multithreading:
    def run_multithreader (data):
         spark = data[0]
         df = data[1]
         filter_val = data[3]
         # I am repartitioning and clustering the data along with persist to achieve 
         # Bucket join effect when joining.
         
         df = df.filter(col('validation_Date') == filter_val)\
              .repartition(500,'validation_Date','col_x')
              .sortWithinPartitions( 'col_xx','col_yy' )\
              .persist( pyspark.StorageLevel.MEMORY_ONLY_2)
         
         df=df.groupBy( 'col_1','col_2','validation_Date' ).agg({'col3':'sum'})
         df=df.select( 'col_1','col_2',
                 col('sum(col_3)').alias('sum_of_col3'),'validation_Date')
         df2=spark.read.table('dim_db.some_dimesion')
         df = df.join(broadcast(df2),how='left',on=['validation_date','col1'])
         df.coalesce(10).write.mode('append')\
                 .option("spark.hadoop.mapreduce.fileoutputcommitter.algorithm.version", "2")\      
                 .partitionBy('validation_Date').saveAsTable('db.target_table')

def main():
    spark=SparkSession.builder.appName('Multithreading Pyspark')\
                      .enableHiveSupport().getOrCreate()
    obj=do_multithreading()
    df=spark.read.table('db.tb1')
    pools=[[spark,df,'2021-08-21'],[spark,df,'2021-08-22'],[spark,df,'2021-08-23']]
    tpool = ThreadPool(processes=len(pools))
    tpool.map(obj.run_multithreader,pools)

What this solved:

Using multithreading with spark along with FAIR pool schedular helped achieve job execution time reduction from 4 hrs to 1 hr but In spark I am seeing some issue with job failure due to concurrent write to same partitioned table.This issue occur's like once in 2 week or some time a month.

LOGS:

Caused by: org.apache.spark.SparkException: Job aborted due to stage failure: ShuffleMapStage 1866 (persist at :0) has failed the maximum allowable number of times: 4. Most recent failure reason: org.apache.spark.shuffle.MetadataFetchFailedException: Missing an output location for shuffle 1613 at org.apache.spark.MapOutputTracker$$anonfun$convertMapStatuses$2.apply(MapOutputTracker.scala:867) at org.apache.spark.MapOutputTracker$$anonfun$convertMapStatuses$2.apply(MapOutputTracker.scala:863) at scala.collection.TraversableLike$WithFilter$$anonfun$foreach$1.apply(TraversableLike.scala:733) at scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:33) at scala.collection.mutable.ArrayOps$ofRef.foreach(ArrayOps.scala:186) at scala.collection.TraversableLike$WithFilter.foreach(TraversableLike.scala:732) at org.apache.spark.MapOutputTracker$.convertMapStatuses(MapOutputTracker.scala:863) at org.apache.spark.MapOutputTrackerWorker.getMapSizesByExecutorId(MapOutputTracker.scala:677) at org.apache.spark.shuffle.BlockStoreShuffleReader.read(BlockStoreShuffleReader.scala:49) at org.apache.spark.sql.execution.ShuffledRowRDD.compute(ShuffledRowRDD.scala:165) at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:324) at org.apache.spark.rdd.RDD.iterator(RDD.scala:288) at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:49) at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:324) at org.apache.spark.rdd.RDD.iterator(RDD.scala:288) at org.apache.spark.rdd.UnionRDD.compute(UnionRDD.scala:105) at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:324) at org.apache.spark.rdd.RDD.iterator(RDD.scala:288) at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:49) at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:324) at org.apache.spark.rdd.RDD.iterator(RDD.scala:288) at org.apache.spark.scheduler.ShuffleMapTask.runTask(ShuffleMapTask.scala:96) at org.apache.spark.scheduler.ShuffleMapTask.runTask(ShuffleMapTask.scala:53) at org.apache.spark.scheduler.Task.run(Task.scala:109) at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:345) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748)

0 Answers
Related