1.概述
其實,在從事過調優相關的工作後,會發現其實調優是一項較為複雜的工作。而對於Hadoop這樣複雜且龐大的系統來說,調優更是一項巨大的工作,由於Hadoop包含Common、HDFS、MapReduce、YARN等模組,每個模組都有可以根據自身業務進行優化的工作,本篇部落格也是針對某些模組進行調優剖析。
在進行Hadoop調優時,不僅僅只是針對其效能調優,還是涉及到更底層的硬體,OS以及JVM等的優化,如下圖所示:
針對以上內容進行優化,均有可能對Hadoop的效能進行提升。
2.OS調優
由於Hadoop的設計決定,其只能用於Linux作業系統作為生產環境。在實際應用場景之中,對Linux引數進行優化,可以在一定程度上提升作業的允許效率。
- 增大網路連線上限
在Hadoop叢集當中,其內部的一些通訊依賴網路,需調整Linux引數net.core.somaxconn,讓其處於一個足夠大的狀態。
- Swap
在Linux系統當中,如果一個程式的記憶體不足,其記憶體中的部分資料會暫時寫到磁碟上,在需要的時候,會再將磁碟中的資料動態的置換到記憶體當中,這樣一來,一些不必要的流程就會顯現出來。通常,這會導致程式的執行效率降低。再分散式環境當中,使用MapReduce這樣的計算模型時,可以通過控制每個Job的處理數量和每個Task執行過程使用的緩衝區的大小,避免我們去使用Swap分割槽。通過/etc/sysctl.conf檔案中的vm.swappiness引數來達到目的。
- 預讀取
磁碟IO效能沒有CPU和記憶體這樣發展迅猛,因而它成為OS當中一個主要的效能瓶頸。改進磁碟IO效能也是重要的優化手段之一。可以使用Linux的blockdev命令來設定預讀取的緩衝區大小,以便提高Hadoop的檔案讀取效能。
3.JVM
在YARN裡面,可以啟用JVM的重用機制來得到效能的提升。啟用該功能能夠讓一些Task的執行效率提高2~3倍。在Hadoop2.x中,YARN的結構不同於MRV1,因而其配置有些許變化。
YARN的預設配置會禁用該元件,即不允許重用JVM。首先,我們需要明白YARN是如何執行一個MapReduce的Job。其步驟如下所示:
- RM(Resource Manager)裡面的AM(Application Manager)會為每個Application(一個MR的Job)在NM(NodeManager)裡面申請一個Container
- 在申請到的Container裡面啟動一個Application Master,Container在YARN中分配資源的容器(記憶體、CPU、磁碟空間等),它啟動便會對應的啟動一個JVM
- Application Master會持續為Application包含的每一個Task(一個Map Task或者Reduce Task)向RM申請一個Container
- 每得到一個Container,該Container所屬的NM將此Container啟動
- 該Container執行對應的Task
- 對應的Task執行完畢,該Container被NM回收,而Container所擁有的JVM相應的推出
通過上述的流程可以看出,這種情況下,每一個JVM僅只執行了一個Task,JVM並未被重用。
因而,使用者可以通過啟用ubertask屬性來重用JVM,在同一個Container裡面一次執行多個Task,可以在mapred-site.xml中配置對應的引數即可,內容如下所示:
<property> <name>mapreduce.job.ubertask.enable</name> <value>true</value> </property>
如果啟用該功能,會將一個Application中的所有子Task在同一個JVM裡面執行,到達JVM重用的目的。該JVM負責Application中的Application Master中所用的JVM,即執行在Container當中。
最後,我們來看當ubertask功能被啟用的時候,YARN是如何執行一個application的。首先,RM裡的AM會為每一個Application在NM裡面申請一個Container,然後在該container裡面啟動一個Application Master。Containe啟動時便會相應啟動一個JVM。此時,如果ubertask功能被啟用,Application Master會在JVM中按照順序依次在Container中執行每一個Task,這樣Application Master便不用再為每一個Task向RM去申請一個單獨的Container,從而達到了重用JVM(資源重用)的目的。
4.Hadoop調優
在對Hadoop調優時,這是一個龐大的任務,這裡進行分解來看,按Hadoop的組成模組來分,比如:我們可以安裝HDFS、MapReduce、YARN等模組去優化對應的模組。若是在細分,我們可以優化其各個元件的相關配置檔案,其每個模組都有對應的XML檔案,在系統啟動時,會通過Configure載入到系統當中,而對應的XML檔案當中,配置的引數和屬性比較多,有些引數是根據業務本身去優化,如:心跳間隔、緩衝區大小、JVM子程式最大記憶體、小檔案的合併數、歸併map輸出資料佔比等等。
另外,在處理一些IO密集的應用,會在執行MapReduce時產生大量的中間輸出資料(Map Task執行階段),而產生的這些資料對於使用者來說是並不關心的(透明化)。這裡,可以思考一下,有木有一種辦法能夠集中處理這些輸出資料。答案是肯定的,在MapReduce中支援壓縮演算法,我們可以在執行這部分流程時,將中間輸出資料壓縮儲存,這樣在IO效能方面有會有明顯的提升。然而,萬物皆有因果,在選擇壓縮演算法時,需考慮壓縮比和壓縮效率,在一些壓縮演算法當中,有的壓縮比非常可觀,然而其壓縮效率卻非常低下;反之,有的壓縮比較差,然其壓縮效率非常理想。因為,我們需要在壓縮比和壓縮效率之間做一個平衡,選擇合適的演算法,去平衡二者的關係。
目前,存在許多的壓縮格式,如:GZIP,ZIP,LZO,Snappy等等,測試表明其中LZO和Snappy較為可觀(具體量化指標圖不方便給出)。當然,這個也不是絕對的,是當下業務去測試,然後選擇合適的壓縮格式。
上面提點過預讀取機制,可以通過預讀取機制來有效的提升磁碟IO的讀效能。通過改機制提高HDFS的讀效能以及MapReduce作業的執行效率。
當然,從應用程式也是有優化的空間的,處理應用程式當中配置必要的作業引數之外,其本身的編寫方式對效能也是有影響的。在執行一大批MapReduce作業時,若是設定一個Combiner,對於提供作業的效能大有裨益。在瞭解MapReduce(其分兩部分,其一為計算模型,其二為執行環境,儘管Hadoop版本升級到2.x,然其計算模型不變,變得只是其執行環境。其執行環境是基於YARN的資源管理)的計算模型時,在弄明白Combiner階段的好處後,會發現,我們在編寫相關作業時,新增Combiner可減少Map Task的中間輸出結果,從而減少各個Reduce Task的遠端Copy資料量,最終帶來的益處是縮短了Map和Reduce兩者的執行時間。
同樣,我們在選擇Hadoop的相關型別時,如Writeable。在MapReduce中,Map Task和Reduce Task的輸入和輸出的資料型別均為Writable的衍生型別,其包含IntWritable、LongWriteable、FloatWritable等。在編寫相關程式碼時,選擇合適的型別可以大大提升其效能。例如在處理整型資料之時,直接採用IntWritable比先以Text型別讀取在通過對應的方法轉化為整型來的高效。
5.總結
在對Hadoop的優化過程,是一個探索和實踐的過程,有一些優化的手段和技巧也是需要平時在工作的當中去總結的,以上給出的優化點,也是有限的,並未盡數述說,如我們也可以通過對任務的級別引數的調整,來達到有效的優化手段,對Map Task和Reduce Task階段的調優等。還有未言之知識點有待後續去發掘,以上只是起到點撥之效。
6.結束語
這篇部落格就和大家分享到這裡,如果大家在研究學習的過程當中有什麼問題,可以加群進行討論或傳送郵件給我,我會盡我所能為您解答,與君共勉!