1. 程式人生 > >使用spark過程中遇到的技術問題及自身問題

使用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