調優概述#
幾乎在很多場景,MapRdeuce或者說分布式架構,都會在IO受限,硬盤或者網絡讀取數據遇到瓶頸.處理數據瓶頸CPU受限.大量的硬盤讀寫數據是海量數據分析常見情況.
IO受限例子:
CPU受限例子:
我們需要從硬件規划和軟件規划等多方面結合實現性能和效率的提升。
硬件規划#
評估集群規模#
我們需要搭建多少節點的hadoop集群?回答這個問題考慮的因素比較多:預算?數據量?計算資源?
需要多少計算資源可能不是特別好評估,推薦橫向擴展,隨業務規模和應用發展再考慮擴展。開始可以就按照數據量來評估數據規模,估計一下每天的數據增量?保存數據的周期是多少?有沒有冷數據方案?
假設每天增長的數據為600G、3備份存儲,以一年規划為例,大概存儲為600G3360天=633T, 再考慮增加%20的預留,考慮未來數據增長的趨勢,考慮應用計算等空間需求。為節省空間可考慮壓縮存儲(大概可以節省70%空間)。
同時考慮一定冗余量,如果集群一部分節點不可用也要保證業務正常使用(根據集群規模評估冗余比例)。
然后結合節點硬件規划和預算,確定集群規模。假如我們需要650T存儲,可以采用30台12 x 2TB的存儲配置或者 60台6 x 2TB配置,但是節點數量翻翻,這樣同樣可以滿足存儲需求。需要注意的是,這種變化實際上增加了計算能力,但是,需要增加更多的電力、制冷、機架空間、網絡端口密度。所以這是一種權衡,根據實際的需求考慮。
節點硬件規划#
CPU要高配還是低配?內存,存儲,CPU什么配比?
一般原則:
-
CPU 選擇中等頻率,一般不超過兩路。一般平衡價格和功耗,使充分利用CPU性能。
-
內存 考慮CPU配比和成本,保證CPU高利用率運轉。48G也許是不錯的選擇,可以並行更多的進程,也可以增加緩存改善性能。
-
硬盤 考慮高容量的SATA硬盤(一般7200RPM),hadoop一般是存儲密集型,不要求太高性能硬盤。多盤可以平衡分散IO壓力,同時考慮容錯,大型集群硬盤壞損是非常常見的(如果單台存儲容量太高,如果節點宕機會造成內部數據復制產生抖動)。一般配置12塊4T硬盤(不絕對,可以根據情況調整)。
-
網絡 建議每個節點提供2 Gbps的網絡吞吐量(考慮平衡成本和需求),網絡拓撲不要太深,一般hadoop對橫向和縱向的網絡要求都比較高。
hadoop集群中各個組件對硬件需求也不同,下面根據組件特點描述硬件要求:
-
Namenode
Namenode負責協調整個集群上的數據存儲,Namenode需要RAM存儲集群內部數據的block原信息,一個比較靠譜的經驗是,Namenode上面1GB的RAM可以支撐1 million的block信息,64GB的RAM可以支撐100 million的block信息.
硬件方面主要根據存儲容量需求計算內存的需求(根據存儲容量/文件數/塊大小估計塊數量的需求),同時考慮hdfs元數據持久的安全(硬盤一般要做raid或結合外掛存儲)。CPU沒有太高要求。
-
ResourceManager
負載整個集群的資源調度,不太占用資源,一般和Namenode共用即可。 -
Standby
最好和Namenode一樣的配置。 -
JournalNode
資源要求不高 -
Zookeeper
資源要求不高,機器負載不要太高,一般需要3~5台 -
Datanode/NodeManger
主要的存儲和計算節點,根據上述原則結合預算成本規划單機硬件。
Datanode的內存預估:
如果是I/O類型的job,每個core分配2~4GB RAM
如果是CPU類型的job,每個core分配6~8GB RAM
除了以上的job消耗內存外,整個機型還需要額外的增加:
Datanode進程管理HDFS的block,需要2GB RAM
NodeManger 進程管理節點運行的task,需要2GB RAM
OS,需要4GB RAM
下面給出一個計算公式:
推薦單件配置:
NameNode/ResourceManager/Standby類型的機器:
DataNode/TaskTrackers類型的機器:
下面是一些針對不同負載任務類型的硬件建議:
-
輕量處理型 (1U/machine): 兩顆六核處理器,24-64GB內存,8塊硬盤(單盤2TB or 4TB)
-
均衡型配置 (1U/machine): 兩顆六核處理器,48-128GB內存,12 – 16塊硬盤(單盤4TB or 6TB) ,直接和主板控制器連接。如果這種節點發生故障,將會導致集群內部數據抖動,產生大量的流量
-
存儲密集型 (2U/machine): 兩顆六核處理器,48-96GB內存,16-24塊硬盤(單盤6TB or 8TB),如果這種節點發生故障,將會導致集群內部數據抖動,產生大量的流量
-
計算密集型(2U/machine): 兩顆六核處理器,64-512GB內存,4-8塊硬盤(單盤2TB or 4TB)
注:上面的CPU都是最小配置,建議使用的是 2×8,2×10,2×12 core的處理器配置(不包括超線程)。
如果新集群你還是無法預估你的最終工作量,我們建議還是使用均衡的硬件配置。
異構集群#
目前Hadoop發展為一個無所不包的數據平台,所以不僅僅是MapReudce使用,多種計算模型可插拔和Hadoop無縫結合,Hadoop2.x版本Yarn資源管理器,可以兼容多種技術模型;如:內存計算代表的saprk,impala,tez,drill,presto.磁盤計算代表的hive,mapreduce,pig. 對於一個異構集群,會同時存在多種計算模型!在硬件配置上面就需要高內存,大磁盤; Impala推薦最低配置128G內存,才能發揮優勢;spark典型的CPU密集型,需要更多CPU和內存。Hive,MR磁盤計算,多磁盤讀寫比較頻繁!當你在為集群硬件選型的時候,需要考慮的軟件組件包括Apache HBase、Cloudera Impala、Presto Or Drill、Apache Phoenix和Apache spark。
可以考慮引入了Yarn的資源池,Label based scheduling基於標簽的調度機制。基於標簽的調度策略是hadoop yarn新引入的feature,它能讓YARN更好地運行在異構集群中,進而更好地管理和調度混合類型的應用程序。
網絡拓撲#
Hadoop 是IO hungry 的,既是磁盤IO hungry,也是網絡IO hungry。雖然 Hadoop 在 Map 階段調度任務時,會盡量使任務本地化,但是對於 shuffle/sort 以及 Reducer 輸出來說,都會產生大量的IO。
雖然 Hadoop 不要求非要部署 10 Gb 網絡,但是更高的帶寬肯定會帶來更好的性能。一旦你感覺需要2個以上1Gb網卡綁定以增加帶寬的時候,就是考慮部署10Gb的時候了。
網絡拓撲結構對 Hadoop 在某種程度上是有影響的。由於 shuffle/sort 的階段會有大量的東西向/橫向網絡訪問,因此網絡的特點是任意節點間的帶寬需求都很高。這與傳統的Web服務形式的南北向/縱向帶寬需要很高截然不同。如果網絡拓撲設計時縱向深度很大(層級很多)就會降低網絡性能。
對於 Hadoop 而言,對橫向帶寬需求很高。 由於這種原因,傳統的樹形拓撲網絡就不是很適用與 Hadoop 的特性,更合適的是 spine fabric 拓撲結構。
典型部署案例#
2台 兩顆8核處理器/64G內存/6塊1T硬盤(os:1塊,fsp_w_picpath:2塊 raid1,RM:1塊,zookeeper:1塊 JN:1塊)
1台 兩顆6核處理器/24G內存/4塊1T硬盤(os:1塊,zookeeper:1塊 JN:1塊)
30台兩顆10核處理器,64GB內存/12塊4T硬盤
對於 Hadoop 而言,對橫向帶寬需求很高。 由於這種原因,傳統的樹形拓撲網絡就不是很適用與 Hadoop 的特性,更合適的是 spine fabric 拓撲結構。
軟件規划#
操作系統#
Hadoop 本身絕大多數使用的是 Java 寫的,但其中也有C/C++代碼。另外,由於撰寫的時候,基本以Linux為設計目標系統,因此其中充斥了大量的使用 Linux 構架的思想的代碼,因此一般來說會選擇在 Linux 上部署。
現行系統中,RedHat Enterprise Linux, CentOS, Ubuntu Server Edition, SuSE Enterprise Linux 以及 Debian 都可以在生產環境中很好的部署 Hadoop。因此選擇系統更多的是取決於你的管理工具所支持的系統、硬件支持能力、以及你們所使用的商業軟件所支持的系統,還有很重要的考量是哪個系統管理人員最熟悉。
配置系統是非常消耗時間,以及容易出錯的,建議采用軟件配置管理系統來進行維護,而不要手動去配置。現在比較流行的是 Puppet 和 Chef。
Hadoop版本#
Apache的Hadoop版本並不是唯一的版本,有很多的公司也在專注做自己的發行版,最流行的非Apache的Hadoop發行版是Cloudera公司的Hadoop版本,也就是CDH。
-
ClouderaHadoop發行版
Cloudera是一家為Hadoop提供商業支持,專業服務和高級工具的公司。他們的CDH發行版是開源免費的。遵循Apache2.0。CDH對於用戶來說沒有很多的分支版本,版本號是連續的,而且有較好的兼容性,當前CDH的版本是CDH5,具有Apache2.0和1.0的特點。包括NameNode HA和Federation,同時支持MRv1和MRv2。這是當前Apache版本不具備的。CDH的另一個特點是CDH集成了不同的Hadoop生態系統項目,HDFS和MapReduce曾是Hadoop的核心組件,而在此之上出現了越來越多的組件。這些組件使得Hadoop使用起來更加友好,縮短了開發周期。使得編寫MapReduce任務更加簡單。
這里要提及下CDH中的Impala項目,這個項目可以完全繞過MapReduce層,直接從HDFS上獲取數據,來對Hadoop進行實時的查詢,CDH解決了Hadoop生態系統中眾多組件的依賴。提供了大多數生態圈的組件。解決了組件之間的兼容性。這一點對用戶來說選擇CDH是一個很大的優勢,也使得CDH變得如此受歡迎,為了輔助CDH,Cloudera發布了一個基於web的管理工具Cloudera Manager,用於規划、配置和監控Hadoop集群,Cloudera Manager擁有免費版本和付費企業版本。
-
HortonworksHadoop發行版
另外一個流行的Hadoop版本是Horonworks出品的Horonworks Data Platform(HDP),和Cloudera類似,Horonworks提供了一個一體化安裝版本,並提供商業支持和服務。提供HDP1.2和2.0。其中HDP1.2提供了一些其它發行版不具備的特性,Horonworks在Hadoop1.0的基礎上實現了NameNode的HA(注:這種HA利用Linux HA技術,而不是使用JournalNode),HDP包含了HCatalog,用來提供Pig和Hive這樣項目的一個整合服務。為了吸引用戶,Horonworks很注意和傳統BI結合。HDP為Hive提供了ODBC驅動。使得可以喝大多數存在的BI工具做個適配。HDP的另外一個特點是可以運行在windows平台,不過這個穩定性還在測試中。HDP利用Ambari來做集群的管理和監控。Ambari是一個類似Cloudera Manager的Web端工具。不同的是100%完全免費和開源。 -
MapR發行版
除了Cloudera和Hortoworks外MapR也是一家提供基於Hadoop平台的公司。它們產品擁有不同的版本。M3是一個具有功能限制的免費版本,M5和M7是企業版。和Cloudera和Hortoworks不同MapR提供的軟件都是不是免費的。但是提供了一些企業級的特征,MapR和Apache Hadoop的主要區別在於MapR沒有使用HDFS而是使用MapR-FS文件系統。MapR-FS是用C++實現比起Java寫的HDFS提供低延時和高並發度。雖然在API方面兼容,但是完全是不同的實現。除此之外,MapR-FS提供了NFS卷、集群快照和集群監控等能力,這些能力都是基於MapR-FS實現的。
選擇建議:
根據團隊自身情況和業務情況來決定使用哪個版本,如果團隊沒有hadoop定制能力,業務上也沒有強烈需要,可以考慮CDH版本,相對來說會更穩定些,相關組件集成也方便,也要免費版本的CDH Manager來管理和監控集群;如果需要定制開發可以選擇社區版本,這樣可以方便社區交流開發,當然你也可以將CDH版本的patch更新到自己的分支,或者基於某個CDH版本開發。
Java版本#
最基本的,Hadoop 需要 JDK 方可運行。JDK 的版本是需要關注的,如果使用的是比較老的 Java 6,那么需要安裝 Oracle (Sun) 的 JDK;如果是 Java 7 則可以使用系統默認的 OpenJDK 7。具體的兼容性經過了官方一些用戶的測試后發布在:
http://wiki.apache.org/hadoop/HadoopJavaVersions
一般來說是選擇64位系統,因為一般所配置的內存都遠遠大於 4GB。
參數優化#
OS參數優化#
相關參數調整,可以根據實際情況優化
-
關閉selinux,清空iptables 在服務器配置完全成功后各項服務正常后,在開啟selinux
-
精簡開機自啟動服務
只保留crond,network,syslog,sshd服務即可,后面根據需求定制 -
調整文件描述符大小
-
刪除不必要的系統用戶和群組
-
同步系統時間
-
內核參數優化
-
文件系統
推薦使用ext3格式化hadoop磁盤,ext3經過大量測試(yahoo集群使用ext3),ext4和xfs都有丟數據風險。
禁用Linux邏輯管理卷(LVM)
掛載數據分區時禁用文件atime和目錄atime
格式化時可以增加-m 參數減少預留空間
-
關閉THP
可以加到開機啟動項中。
hadoop參數優化#
hadoop驗證版本為2.6.4,其它版本酌情參考
core-site.xml
| 參數名 | 默認值 | 說明 |
|---|---|---|
| hadoop.tmp.dir | /tmp/hadoop-${user.name} | hadoop中間臨時文件最好單獨指定目錄,比如mr split信息,stag信息 |
| io.file.buffer.size | 4096 | 設置IO操作緩沖區大小,較大的緩存都可以提供更高的數據傳輸,但這也就意味着更大的內存消耗和延遲。這個參數要設置為系統頁面大小的倍數,以byte為單位,默認值是4KB,一般情況下,可以設置為64KB(65536byte) |
| fs.trash.interval | 0 | 建議開啟回收站功能,此參數定義.Trash目錄下文件被永久刪除前保留的時間 |
| topology.script.file.name | -- | 集群節點比較多時,建議配置機架感知。腳本示例:rack_awareness |
hdfs-site.xml
| 參數名 | 默認值 | 說明 |
|---|---|---|
| dfs.namenode.handler.count | 10 | 服務線程個數,調大一些,一般原則是將其設置為集群大小的自然對數乘以20,即20logN,N為集群大小 |
| dfs.datanode.handler.count | 10 | 服務線程個數,根據CPU核數盒實際測試決定,一般是比核數多幾個 |
| dfs.datanode.max.transfer.threads | 4096 | datanode所允許同時執行的發送和接受任務的數量,類似於linux上的文件句柄限制 |
| dfs.namenode.name.dir | file://${hadoop.tmp.dir}/dfs/name | 多個位置冗余備份,一份在本地,另外一份NFS |
| dfs.datanode.data.dir | file://${hadoop.tmp.dir}/dfs/data | 多個位置分布式存儲,盡量多分布幾個分區目錄 |
| dfs.datanode.failed.volumes.tolerated | 0 | 定義整個DataNode聲明失敗前允許多少個硬盤出現故障。任何一個本地磁盤出故障時,它的默認行為認定整個DataNode失效。可以配成硬盤數量的30% |
| dfs.client.read.shortcircuit | false | 建議改為true開啟短路徑讀 |
| dfs.domain.socket.path | 設置短路徑讀的socket path,/var/run/hadoop-hdfs/dn._PORT 保證/var/run/hadoop-hdfs/組可寫,組為root | |
| dfs.blocksize | 134217728 | 新文件默認塊大小,默認128M,可以根據集群規模調整,mapper數基本由輸入文件的block數決定,block小引起很多小任務 |
| dfs.hosts | -- | 該文件中dfs.hosts的格式是用換行符來分割主機名或者IP地址,不在列表內的主機不允許加入集群。 |
| dfs.host.exclude | -- | 類似dfs.hosts,HDFS可以通過指定文件把相關節點排除在外,可以安全的卸載節點 |
| dfs.datanode.balance.bandwidthPerSec | 1048576 | balancer 在DataNode之間移動數據塊來保證負載均衡。如果不對平衡操作進行帶寬限制,那么它會很快就會搶占所有的網絡資源,影響Mapreduce作業和其它服務,太小則均衡太慢。通過此參數設置每秒最大占用帶寬,這個值的單位是byte,網絡帶寬一般都是用bit來描述的。在設置的時候,要先計算好。 |
| dfs.datanode.du.reserved | 0 | datanode會上報配置目錄的空間大小總和,默認都用於dfs存儲,可以預留一部分空間給別的服務,也可以減少一些無謂監控告警 |
mapred-site.xml
| 參數名 | 默認值 | 說明 |
|---|---|---|
| mapreduce.cluster.local.dir | ${hadoop.tmp.dir}/mapred/local | MR存儲中間數據,最好多分及格目錄,逗號隔開 |
| mapreduce.shuffle.readahead.bytes | 4194304 | 默認為4M,ShuffleHandler在發送文件時使用posix_fadvise管理操作系統cache,可以增加預取長度提高shuffle效率 |
| mapreduce.ifile.readahead.bytes | 4194304 | 默認為4M,ifile預取長度 |
| mapreduce.tasktracker.outofband.heartbeat | false | 建議設成ture,在完成任務時讓TaskTracker發送一個 out-of-band心跳來減少延遲 |
| mapreduce.jobtracker.heartbeat.interval.min | 300 | 增加TaskTracker-to-JobTracker 心跳間隔,對小集群可以增加MR性能,可以改成1000 |
| mapred.reduce.slowstart.completed.maps | 0.05 | 此屬性設置當map任務完成多少的時候啟動reduce任務,許多小任務可以設成0,大任務設成0.5 |
| mapreduce.map.speculative | true | map任務推測執行,如果計算資源緊張,任務執行本身很耗資源情況下可以考慮設置成false。需要時通過任務參數制定 。 |
| mapreduce.reduce.speculative | true | reduce任務推測執行,建議關閉,需要時通過任務參數制定 |
| mapreduce.task.io.sort.mb | 100 | 以MB為單位,默認100M,根據map輸出數據量的大小,可以適當的調整buffer的大小,注意是適當的調整,不是越大越好。 |
| mapreduce.map.sort.spill.percent | 0.8 | buffer中達到80%時,進行spill |
| mapreduce.map.output.compress | false | map輸出是否壓縮,建議開啟減少io和網絡消耗 |
| mapreduce.map.output.compress.codec | org.apache.hadoop.io.compress.DefaultCodec | 建議使用snappy壓縮 org.apache.hadoop.io.compress.SnappyCodec |
| mapreduce.output.fileoutputformat.compress.type | RECORD | 輸出SequenceFiles是的壓縮類型,建議改成BLOCK |
| mapreduce.map.java.opts | -- | 可以指定一些JVM參數用於調優 |
| mapreduce.jobtracker.handler.count | 10 | jobtracker rpc的線程數,一般推薦為tasktracker節點數的40% |
| mapreduce.tasktracker.http.threads | 40 | 獲取map輸出的工作線程數,可根據集群規模和硬件配置調整 |
| mapreduce.tasktracker.map.tasks.maximum | 2 | tasktracker同時運行map任務數,一般可配為CPU核數或1.5倍核數 |
| mapreduce.tasktracker.reduce.tasks.maximum | 2 | tasktracker同時運行reduce任務數,一般可配為CPU核數或1.5倍核數 |
| mapreduce.reduce.shuffle.input.buffer.percent | 0.7 | reduce用於接受map輸出buffer占堆大小的比例,類似於map端的mapreduce.task.io.sort.mb,shuffle最大使用的內存量。如果 map 輸出很大而且在 reduce 到排序階段本地磁盤 I/O 很頻繁,應該嘗試增加這個值。 |
| mapreduce.reduce.shuffle.parallel.copies | 5 | shuffle階段copy線程數,默認是5,一般可以設置為 4*logN N為集群大小 |
| mapreduce.job.jvm.num.tasks | 1 | 默認為1,設置為 -1,重用jvm |
yarn-site.xml
| 參數名 | 默認值 | 說明 |
|---|---|---|
| yarn.scheduler.minimum-allocation-mb | 1024 | 一次申請分配內存資源的最小數量 |
| yarn.scheduler.maximum-allocation-mb | 8192 | 一次申請分配內存資源的最大數量 |
| yarn.nodemanager.resource.memory-mb | 8192 | 默認值為8192M,節點所在物理主機的可用物理內存總量 |
| yarn.nodemanager.resource.cpu-vcores | 8 | NodeManager總的可用虛擬CPU個數,根據硬件配置設定,簡單可以配置為CPU超線程個數 |
如何調優#
一般系統調優的基本步驟
在集群安裝部署時應收集業務對系統的需求及特點(數據量,讀寫特點,計算量等),同時做好硬件的規划和初始測試(對服務器的IO/net/cpu做基本測試,保證加入集群服務器硬件沒有問題)。下面主要從硬件規划和軟件調優方面討論hadoop集群的調優。
設計基准測試用例#
怎么看你的調整有效果?怎么看你是否找到了瓶頸點?要有一個對比的基線,才能比較出你的調整能改善多少性能。Hadoop提供線程測試基線應用。比如用於 HDFS I/O 測試的 TestDFSIO 和 dfsthroughput(包含在 hadoop--test.jar 中)、用於總體硬件測試的 Sort(包含在 hadoop--examples.jar 中)。可以根據自己的測試需求選擇任何基准。
在所有這些基准中,當輸入數據很大時,Sort 可以同時反映 MapReduce 運行時性能(在 “執行排序” 過程中)和 HDFS I/O 性能(在 “把排序結果寫到 HDFS” 過程中)。另外,Sort 是 Apache 推薦的硬件基准。(http://wiki.apache.org/hadoop/Sort)
可以先測試HDFS的寫入和讀寫性能,然后通過Sort基線測試計算和整體性能。
IO測試,會在最后輸出相關統計數據
Sort基線測試
基線配置參數可以都使用默認的配置參數,然后一輪一輪修改參數,通過對比結果和服務器監控數據來做對比。
監控數據分析#
在做調優之前集群應該已經有基本的資源監控 比如 CPU、文件IO、網絡IO、內存。如果沒有則需要安裝監控工具或監控腳步完成主機性能參數收集,常用工具(nmon/nmonanalyser,dstat等等)。
性能瓶頸的表象:資源消耗過多、外部處理系統的性能不足、資源消耗不多但程序的響應速度卻仍達不到要求。
我們分析性能的主要來源數據就是主機監控數據和MR計算過程中的計數器數據等等,常見的分析點:
-
work節點的CPU資源是否有效利用,一般維持在70%左右,如果不到40%表面沒有充分利用CPU
-
觀察磁盤IO是否有壓力,CPU wa比例是不是很大
-
觀察網絡流量是否正常
-
MR性能主要看shuffle階段的計數器的表現,spill IO是否為瓶頸等
-
內存方面結合JVM優化進行調整
結合前面講的一些優化參數點,反復測試分析結果。解決高層次性能瓶頸后再考慮應用級別的優化,比如文件格式,序列化性能,這方向調優可以使用JVM/HotSpot原生profile能力。
