目錄 一、寫(xiě)在前面 (1)Chunk緩沖機(jī)制 (2)Packet數(shù)據(jù)包機(jī)制 (3)內(nèi)存隊(duì)列異步發(fā)送機(jī)制 一,、寫(xiě)在前面 上一篇文章,,我們聊了一下Hadoop中的NameNode里的edits log寫(xiě)機(jī)制。 主要分析了edits log寫(xiě)入磁盤(pán)和網(wǎng)絡(luò)的時(shí)候,,是如何通過(guò)分段加鎖以及雙緩沖的機(jī)制,,大幅度提升了多線程并發(fā)寫(xiě)edits log的吞吐量,從而支持高并發(fā)的訪問(wèn),。
如果沒(méi)看那篇文章的同學(xué),,可以回看一下:《大規(guī)模集群下Hadoop NameNode如何承載高并發(fā)訪問(wèn)》。
這篇文章,,我們來(lái)看看,,Hadoop的HDFS分布式文件系統(tǒng)的文件上傳的性能優(yōu)化。
首先,,我們還是通過(guò)一張圖來(lái)回顧一下文件上傳的大概的原理,。 由上圖所示,文件上傳的原理,,其實(shí)說(shuō)出來(lái)也簡(jiǎn)單,。 比如有個(gè)TB級(jí)的大文件,太大了,,HDFS客戶(hù)端會(huì)給拆成很多block,,一個(gè)block就是128MB。 這個(gè)HDFS客戶(hù)端你可以理解為是云盤(pán)系統(tǒng),、日志采集系統(tǒng)之類(lèi)的東西,。 比如有人上傳一個(gè)1TB的大文件到網(wǎng)盤(pán),或者是上傳個(gè)1TB的大日志文件,。 然后,,HDFS客戶(hù)端把一個(gè)一個(gè)的block上傳到第一個(gè)DataNode 第一個(gè)DataNode會(huì)把這個(gè)block復(fù)制一份,做一個(gè)副本發(fā)送給第二個(gè)DataNode,。 第二個(gè)DataNode發(fā)送一個(gè)block副本到第三個(gè)DataNode,。 所以你會(huì)發(fā)現(xiàn),一個(gè)block有3個(gè)副本,分布在三臺(tái)機(jī)器上,。任何一臺(tái)機(jī)器宕機(jī),,數(shù)據(jù)是不會(huì)丟失的。
最后,,一個(gè)TB級(jí)大文件就被拆散成了N多個(gè)MB級(jí)的小文件存放在很多臺(tái)機(jī)器上了,,這不就是分布式存儲(chǔ)么?
二,、原始的文件上傳方案 今天要討論的問(wèn)題,,就是那個(gè)HDFS客戶(hù)端上傳TB級(jí)大文件的時(shí)候,到底是怎么上傳呢,?
我們先來(lái)考慮一下,,如果用一個(gè)比較原始的方式來(lái)上傳,應(yīng)該怎么做,? 大概能想到的是下面這個(gè)圖里的樣子,。 很多java的初學(xué)者,估計(jì)都知道這樣來(lái)上傳文件,,其實(shí)無(wú)非就是不停的從本地磁盤(pán)文件用輸入流讀取數(shù)據(jù),,讀到一點(diǎn),就立馬通過(guò)網(wǎng)絡(luò)的輸出流寫(xiě)到DataNode里去,。
上面這種流程圖的代碼,,估計(jì)剛畢業(yè)的同學(xué)都可以立馬寫(xiě)出來(lái)。因?yàn)閷?duì)文件的輸入流最多就是個(gè)FileInputStream,。 而對(duì)DataNode的輸出流,最多就是個(gè)Socket返回的OutputStream,。 然后中間找一個(gè)小的內(nèi)存byte[]數(shù)組,,進(jìn)行流對(duì)拷就行了,從本地文件讀一點(diǎn)數(shù)據(jù),,就給DataNode發(fā)一點(diǎn)數(shù)據(jù),。
但是如果你要這么弄,那性能真是極其的低下了,,網(wǎng)絡(luò)通信講究的是適當(dāng)頻率,,每次batch批量發(fā)送,你得讀一大批數(shù)據(jù),,通過(guò)網(wǎng)絡(luò)通信發(fā)一批數(shù)據(jù),。 不能說(shuō)讀一點(diǎn)點(diǎn)數(shù)據(jù),就立馬來(lái)一次網(wǎng)絡(luò)通信,,就發(fā)出去這一點(diǎn)點(diǎn)的數(shù)據(jù),。 如果按照上面這種原始的方式,絕對(duì)會(huì)導(dǎo)致網(wǎng)絡(luò)通信效率極其低下,大文件上傳性能很差,。
為什么這么說(shuō)呢,? 相當(dāng)于你可能剛讀出來(lái)幾百個(gè)字節(jié)的數(shù)據(jù),立馬就寫(xiě)網(wǎng)絡(luò),,卡頓個(gè)比如幾百毫秒,。 然后再讀下一批幾百個(gè)字節(jié)的數(shù)據(jù),再寫(xiě)網(wǎng)絡(luò)卡頓個(gè)幾百毫秒,,這個(gè)性能很差,,在工業(yè)級(jí)的大規(guī)模分布式系統(tǒng)中,是無(wú)法容忍的,。
三,、HDFS對(duì)大文件上傳的性能優(yōu)化 好,看完了原始的文件上傳,,那么我們來(lái)看看,,Hadoop中的大文件上傳是如何優(yōu)化性能的呢?一起來(lái)看看下面那張圖,。 首先你需要自己創(chuàng)建一個(gè)針對(duì)本地TB級(jí)磁盤(pán)文件的輸入流,。 然后讀到數(shù)據(jù)之后立馬寫(xiě)入HDFS提供的FSDataOutputStream輸出流。
這個(gè)FSDataOutputStream輸出流在干啥,? 大家覺(jué)得他會(huì)天真的立馬把數(shù)據(jù)通過(guò)網(wǎng)絡(luò)傳輸寫(xiě)給DataNode嗎,?
答案當(dāng)然是否定的了!這么干的話(huà),,不就跟之前的那種方式一樣了,! 1. Chunk緩沖機(jī)制 首先,數(shù)據(jù)會(huì)被寫(xiě)入一個(gè)chunk緩沖數(shù)組,,這個(gè)chunk是一個(gè)512字節(jié)大小的數(shù)據(jù)片段,,你可以這么來(lái)理解。 然后這個(gè)緩沖數(shù)組可以容納多個(gè)chunk大小的數(shù)據(jù)在里面緩沖,。 光是這個(gè)緩沖,,首先就可以讓客戶(hù)端快速的寫(xiě)入數(shù)據(jù)了,不至于說(shuō)幾百字節(jié)就要進(jìn)行一次網(wǎng)絡(luò)傳輸,,想一想,,是不是這樣? 2. Packet數(shù)據(jù)包機(jī)制 接著,,當(dāng)chunk緩沖數(shù)組都寫(xiě)滿(mǎn)了之后,,就會(huì)把這個(gè)chunk緩沖數(shù)組進(jìn)行一下chunk切割,切割為一個(gè)一個(gè)的chunk,,一個(gè)chunk是一個(gè)數(shù)據(jù)片段,。 然后多個(gè)chunk會(huì)直接一次性寫(xiě)入另外一個(gè)內(nèi)存緩沖數(shù)據(jù)結(jié)構(gòu),,就是Packet數(shù)據(jù)包。
一個(gè)Packet數(shù)據(jù)包,,設(shè)計(jì)為可以容納127個(gè)chunk,,大小大致為64mb。所以說(shuō)大量的chunk會(huì)不斷的寫(xiě)入Packet數(shù)據(jù)包的內(nèi)存緩沖中,。 通過(guò)這個(gè)Packet數(shù)據(jù)包機(jī)制的設(shè)計(jì),,又可以在內(nèi)存中容納大量的數(shù)據(jù),進(jìn)一步避免了頻繁的網(wǎng)絡(luò)傳輸影響性能,。 3. 內(nèi)存隊(duì)列異步發(fā)送機(jī)制 當(dāng)一個(gè)Packet被塞滿(mǎn)了chunk之后,,就會(huì)將這個(gè)Packet放入一個(gè)內(nèi)存隊(duì)列來(lái)進(jìn)行排隊(duì)。 然后有一個(gè)DataStreamer線程會(huì)不斷的獲取隊(duì)列中的Packet數(shù)據(jù)包,,通過(guò)網(wǎng)絡(luò)傳輸直接寫(xiě)一個(gè)Packet數(shù)據(jù)包給DataNode,。
如果一個(gè)Block默認(rèn)是128mb的話(huà),那么一個(gè)Block默認(rèn)會(huì)對(duì)應(yīng)兩個(gè)Packet數(shù)據(jù)包,,每個(gè)Packet數(shù)據(jù)包是64MB,。 也就是說(shuō),傳送兩個(gè)Packet數(shù)據(jù)包給DataNode之后,,就會(huì)發(fā)一個(gè)通知說(shuō),,一個(gè)Block的數(shù)據(jù)都傳輸完畢。 這樣DataNode就知道自己收到一個(gè)Block了,,里面包含了人家發(fā)送過(guò)來(lái)的兩個(gè)Packet數(shù)據(jù)包,。
四、總結(jié) OK,,大家看完了上面的那個(gè)圖以及Hadoop采取的大文件上傳機(jī)制,,是不是感覺(jué)設(shè)計(jì)的很巧妙? 說(shuō)白了,,工業(yè)級(jí)的大規(guī)模分布式系統(tǒng),,都不會(huì)采取特別簡(jiǎn)單的代碼和模式,那樣性能很低下,。 這里都有大量的并發(fā)優(yōu)化、網(wǎng)絡(luò)IO優(yōu)化,、內(nèi)存優(yōu)化,、磁盤(pán)讀寫(xiě)優(yōu)化的架構(gòu)設(shè)計(jì)、生產(chǎn)方案在里面,。
所以大家觀察上面那個(gè)圖,,HDFS客戶(hù)端可以快速的將tb級(jí)大文件的數(shù)據(jù)讀出來(lái),然后快速的交給HDFS的輸出流寫(xiě)入內(nèi)存,。 基于內(nèi)存里的chunk緩沖機(jī)制,、packet數(shù)據(jù)包機(jī)制,、內(nèi)存隊(duì)列異步發(fā)送機(jī)制。絕對(duì)不會(huì)有任何網(wǎng)絡(luò)傳輸?shù)目D,,導(dǎo)致大文件的上傳速度變慢,。
反而通過(guò)上述幾種機(jī)制,可以上百倍的提升一個(gè)TB級(jí)大文件的上傳性能,。 |
|
來(lái)自: airen89 > 《大數(shù)據(jù)》