spark性能優化-數據傾斜

背景:

       計算同一品類兩兩商品的相似度,已有的數據結構:[(cid,int); (pid,int); (features,vector)],商品數4W,商品對8W,用時8h。分析是由於數據傾斜導致,例如cid1有100個商品,cid2有300個商品,cid3有1000個商品,由於根據分類id,計算商品相似度,cid3的商品對在一個task中,導致所有任務都等待這一個task運行結束。

 

優化方案:

       1、優化數據通信時間消耗

       商品特徵向量是1024維的向量,大約5K,4W商品共200M,可以將圖片的特徵向量進行廣播,在每個執行器executor中保存一份,減少數據通信開銷;否則按每個商品計算1000個商品對,總數據通信量爲4W*5M=200G,在實際計算中遠遠超過200G。

       2、優化數據傾斜

       對連接後的商品對,按照(pid1,pid2)對做repartition哈希分區,因爲商品對是唯一的,所以根據商品對做shuffle運算後,相似度計算均勻分佈到每個task中,消除數據傾斜的問題。

優化後運行時間爲1h30min。

 

代碼如下:

#對商品的特徵向量進行特徵向量,優化數據通信時間開銷
feature_broadcast = fn.broadcast(feature_vector)

#根據品類id,進行自連接,對商品對進行分區shuffle操作,優化數據傾斜
pid_pairs = cid_pid.join(cid_pid, "cid")\
            .toDF("cid", "pid1", "pid2")\
            .repartition(100, "pid1", "pid2").cache()

#獲取商品特徵信息,計算相似度
@fn.udf(returnType=FloatType())
def cos_sim(a, b):
    #將計算結果轉化爲float類型,因爲string類型佔有內存(char類型佔2B)
    return float(a.dot(b)/(a.norm(2) * b.norm(2)))

pid_pairs_feature = pid_pairs.join(feature_broadcast, feature_broadcast.products_id == pid_pairs.pid1)\
            .select("cid", "pid1", "pid2", feature_broadcast.features.alias("feature1"))\
            .join(feature_broadcast, feature_broadcast.products_id == pid_pairs.pid2)\
            .select("cid", "pid1", "pid2", "feature1", feature_broadcast.features.alias("feature2"))
pid_pairs_simscore = pid_pairs_feature.withColumn("simscore", cos_sim("feature1", "feature2"))\
            .select("pid1", "pid2", "simscore")

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章