spark 數據傾斜解決方案 (二)聚合源數據以及過濾導致傾斜的key

數據傾斜解決方案 聚合源數據以及過濾導致傾斜的key


數據傾斜的解決,跟之前講解的性能調優,有一點異曲同工之妙。
性能調優,跟大家講過一個道理,“重劍無鋒”。性能調優,調了半天,最有效,最直接,最簡單的方式,
就是加資源,加並行度,注意RDD架構(複用同一個RDD,加上cache緩存);shuffle、jvm等,次要的。


數據傾斜,解決方案,第一個方案和第二個方案,一起來講。最樸素、最簡譜、最直接、最有效、
最簡單的,解決數據傾斜問題的方案。


第一個方案:聚合源數據
第二個方案:過濾導致傾斜的key



重劍無鋒。後面的五個方案,尤其是最後4個方案,都是那種特別炫酷的方案。
雙重group聚合方案;sample抽樣分解聚合方案;如果碰到了數據傾斜的問題。
上來就先考慮考慮第一個和第二個方案,能不能做,如果能做的話,後面的5個方案,都不用去搞了。


有效。簡單。直接。效果是非常之好的。徹底根除了數據傾斜的問題。




第一個方案:聚合源數據



1,每個KEY在HIVE ETL中變成一條數據,徹底解決spark都不用做groupByKey
2,如果有好幾個粒度,儘量粗粒度的聚合一下,減輕症狀,spark聚合的時候減輕症狀


咱們現在,做一些聚合的操作,groupByKey、reduceByKey;groupByKey,說白了,
就是拿到每個key對應的values;reduceByKey,說白了,就是對每個key對應的values執行一定的計算。


現在這些操作,比如groupByKey和reduceByKey,包括之前說的join。都是在spark作業中執行的。


spark作業的數據來源,通常是哪裏呢?90%的情況下,數據來源都是hive表
(hdfs,大數據分佈式存儲系統)。hdfs上存儲的大數據。hive表,hive表中的數據,
通常是怎麼出來的呢?


有了spark以後,hive比較適合做什麼事情?hive就是適合做離線的,
晚上凌晨跑的,ETL(extract transform load,數據的採集、清洗、導入),hive sql,
去做這些事情,從而去形成一個完整的hive中的數據倉庫;說白了,數據倉庫,就是一堆表。


spark作業的源表,hive表,其實通常情況下來說,也是通過某些hive etl生成的。
hive etl可能是晚上凌晨在那兒跑。今天跑昨天的數據。


數據傾斜,某個key對應的80萬數據,某些key對應幾百條,某些key對應幾十條;現在,
咱們直接在生成hive表的hive etl中,對數據進行聚合。比如按key來分組,將key對應的所有的values,
全部用一種特殊的格式,拼接到一個字符串裏面去,
比如“key=sessionid, value: 
action_seq=1|user_id=1|search_keyword=火鍋|category_id=001;
action_seq=2|user_id=1|search_keyword=涮肉|category_id=001”。


對key進行group,在spark中,拿到key=sessionid,values<Iterable>;
hive etl中,直接對key進行了聚合。那麼也就意味着,每個key就只對應一條數據。
在spark中,就不需要再去執行groupByKey+map這種操作了。直接對每個key對應的values字符串,
map操作,進行你需要的操作即可。key,values串。


spark中,可能對這個操作,就不需要執行shffule操作了,也就根本不可能導致數據傾斜。
或者是,對每個key在hive etl中進行聚合,對所有values聚合一下,不一定是拼接起來,
可能是直接進行計算。reduceByKey,計算函數,應用在hive etl中,每個key的values。


聚合源數據方案,第二種做法


你可能沒有辦法對每個key,就聚合出來一條數據;
那麼也可以做一個妥協;對每個key對應的數據,10萬條;有好幾個粒度,比如10萬條裏面包含了
幾個城市、幾天、幾個地區的數據,現在放粗粒度;直接就按照城市粒度,做一下聚合,
幾個城市,幾天、幾個地區粒度的數據,都給聚合起來。比如說
city_id date area_id
select ... from ... group by city_id
儘量去聚合,減少每個key對應的數量,也許聚合到比較粗的粒度之後,原先有10萬數據量的key,
現在只有1萬數據量。減輕數據傾斜的現象和問題。


上面講的第一種方案,其實這裏沒法講的太具體和仔細;只能給一個思路。但是我覺得,
思路已經講的非常清晰了;一般來說,大家只要有一些大數據(hive)。經驗,我覺得都是可以理解的。


具體怎麼去在hive etl中聚合和操作,就得根據你碰到數據傾斜問題的時候,
你的spark作業的源hive表的具體情況,具體需求,具體功能,具體分析。


對於我們的程序來說,完全可以將aggregateBySession()這一步操作,放在一個hive etl中來做,
形成一個新的表。對每天的用戶訪問行爲數據,都按session粒度進行聚合,寫一個hive sql。


在spark程序中,就不要去做groupByKey+mapToPair這種算子了。直接從當天的session聚合表中,
用Spark SQL查詢出來對應的數據,即可。這個RDD在後面就可以使用了。




第二個方案:過濾導致傾斜的key


如果你能夠接受某些數據,在spark作業中直接就摒棄掉,不使用。比如說,總共有100萬個key。
只有2個key,是數據量達到10萬的。其他所有的key,對應的數量都是幾十。
這個時候,你自己可以去取捨,如果業務和需求可以理解和接受的話,在你從hive表查詢源數據的時候,
直接在sql中用where條件,過濾掉某幾個key。
那麼這幾個原先有大量數據,會導致數據傾斜的key,被過濾掉之後,那麼在你的spark作業中,
自然就不會發生數據傾斜了。因爲其它的量都很小當然就不會傾斜了。
and session_id not in ( , , )


如果你沒有什麼維度可以讓key去聚合,還有就是沒有什麼key可以去被過濾掉,那麼就是後面5種方案!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章