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.結束語
這篇博客就和大家分享到這里,如果大家在研究學習的過程當中有什么問題,可以加群進行討論或發送郵件給我,我會盡我所能為您解答,與君共勉!