天天看點

頭條面試官問:100TB檔案上傳該怎麼優化性能?

作者:石杉的架構筆記

目錄

  • 一、寫在前面
  • 二、原始的檔案上傳方案
  • 三、HDFS對大檔案上傳的性能優化
  • (1)Chunk緩沖機制
  • (2)Packet資料包機制
  • (3)記憶體隊列異步發送機制
  • 四、總結

一、寫在前面

上一篇文章,我們聊了一下Hadoop中的NameNode裡的edits log寫機制。

主要分析了edits log寫入磁盤和網絡的時候,是如何通過分段加鎖以及雙緩沖的機制,大幅度提升了多線程并發寫edits log的吞吐量,進而支援高并發的通路。

如果沒看那篇文章的同學,可以回看一下:放幾十億資料的系統還能抗每秒上萬并發,牛不牛?

這篇文章,我們來看看,Hadoop的HDFS分布式檔案系統的檔案上傳的性能優化。

首先,我們還是通過一張圖來回顧一下檔案上傳的大概的原理。

頭條面試官問:100TB檔案上傳該怎麼優化性能?

由上圖所示,檔案上傳的原理,其實說出來也簡單。

比如有個TB級的大檔案,太大了,HDFS用戶端會給拆成很多block,一個block就是128MB。

這個HDFS用戶端你可以了解為是雲盤系統、日志采集系統之類的東西。

比如有人上傳一個1TB的大檔案到網盤,或者是上傳個1TB的大日志檔案。

然後,HDFS用戶端把一個一個的block上傳到第一個DataNode

第一個DataNode會把這個block複制一份,做一個副本發送給第二個DataNode。

第二個DataNode發送一個block副本到第三個DataNode。

是以你會發現,一個block有3個副本,分布在三台機器上。任何一台機器當機,資料是不會丢失的。

最後,一個TB級大檔案就被拆散成了N多個MB級的小檔案存放在很多台機器上了,這不就是分布式存儲麼?

二、原始的檔案上傳方案

今天要讨論的問題,就是那個HDFS用戶端上傳TB級大檔案的時候,到底是怎麼上傳呢?

我們先來考慮一下,如果用一個比較原始的方式來上傳,應該怎麼做?

大概能想到的是下面這個圖裡的樣子。

頭條面試官問:100TB檔案上傳該怎麼優化性能?

很多java的初學者,估計都知道這樣來上傳檔案,其實無非就是不停的從本地磁盤檔案用輸入流讀取資料,讀到一點,就立馬通過網絡的輸出流寫到DataNode裡去。

上面這種流程圖的代碼,估計剛畢業的同學都可以立馬寫出來。因為對檔案的輸入流最多就是個FileInputStream。

而對DataNode的輸出流,最多就是個Socket傳回的OutputStream。

然後中間找一個小的記憶體byte[]數組,進行流對拷就行了,從本地檔案讀一點資料,就給DataNode發一點資料。

但是如果你要這麼弄,那性能真是極其的低下了,網絡通信講究的是适當頻率,每次batch批量發送,你得讀一大批資料,通過網絡通信發一批資料。

不能說讀一點點資料,就立馬來一次網絡通信,就發出去這一點點的資料。

如果按照上面這種原始的方式,絕對會導緻網絡通信效率極其低下,大檔案上傳性能很差。

為什麼這麼說呢?

相當于你可能剛讀出來幾百個位元組的資料,立馬就寫網絡,卡頓個比如幾百毫秒。

然後再讀下一批幾百個位元組的資料,再寫網絡卡頓個幾百毫秒,這個性能很差,在工業級的大規模分布式系統中,是無法容忍的。

三、HDFS對大檔案上傳的性能優化

好,看完了原始的檔案上傳,那麼我們來看看,Hadoop中的大檔案上傳是如何優化性能的呢?一起來看看下面那張圖。

頭條面試官問:100TB檔案上傳該怎麼優化性能?

首先你需要自己建立一個針對本地TB級磁盤檔案的輸入流。

然後讀到資料之後立馬寫入HDFS提供的FSDataOutputStream輸出流。

這個FSDataOutputStream輸出流在幹啥?

大家覺得他會天真的立馬把資料通過網絡傳輸寫給DataNode嗎?

答案當然是否定的了!這麼幹的話,不就跟之前的那種方式一樣了!

1. Chunk緩沖機制

首先,資料會被寫入一個chunk緩沖數組,這個chunk是一個512位元組大小的資料片段,你可以這麼來了解。

然後這個緩沖數組可以容納多個chunk大小的資料在裡面緩沖。

光是這個緩沖,首先就可以讓用戶端快速的寫入資料了,不至于說幾百位元組就要進行一次網絡傳輸,想一想,是不是這樣?

2. Packet資料包機制

接着,當chunk緩沖數組都寫滿了之後,就會把這個chunk緩沖數組進行一下chunk切割,切割為一個一個的chunk,一個chunk是一個資料片段。

然後多個chunk會直接一次性寫入另外一個記憶體緩沖資料結構,就是Packet資料包。

一個Packet資料包,設計為可以容納127個chunk,大小大緻為64mb。是以說大量的chunk會不斷的寫入Packet資料包的記憶體緩沖中。

通過這個Packet資料包機制的設計,又可以在記憶體中容納大量的資料,進一步避免了頻繁的網絡傳輸影響性能。

3. 記憶體隊列異步發送機制

當一個Packet被塞滿了chunk之後,就會将這個Packet放入一個記憶體隊列來進行排隊。

然後有一個DataStreamer線程會不斷的擷取隊列中的Packet資料包,通過網絡傳輸直接寫一個Packet資料包給DataNode。

如果一個Block預設是128mb的話,那麼一個Block預設會對應兩個Packet資料包,每個Packet資料包是64MB。

也就是說,傳送兩個Packet資料包給DataNode之後,就會發一個通知說,一個Block的資料都傳輸完畢。

這樣DataNode就知道自己收到一個Block了,裡面包含了人家發送過來的兩個Packet資料包。

四、總結

OK,大家看完了上面的那個圖以及Hadoop采取的大檔案上傳機制,是不是感覺設計的很巧妙?

說白了,工業級的大規模分布式系統,都不會采取特别簡單的代碼和模式,那樣性能很低下。

這裡都有大量的并發優化、網絡IO優化、記憶體優化、磁盤讀寫優化的架構設計、生産方案在裡面。

是以大家觀察上面那個圖,HDFS用戶端可以快速的将tb級大檔案的資料讀出來,然後快速的交給HDFS的輸出流寫入記憶體。

基于記憶體裡的chunk緩沖機制、packet資料包機制、記憶體隊列異步發送機制。絕對不會有任何網絡傳輸的卡頓,導緻大檔案的上傳速度變慢。

反而通過上述幾種機制,可以上百倍的提升一個TB級大檔案的上傳性能。

------------- END -------------

頭條面試官問:100TB檔案上傳該怎麼優化性能?

另外推薦儒猿課堂的1元系列課程給您,歡迎加入一起學習~

網際網路Java工程師面試突擊課(1元專享)「連結」

SpringCloudAlibaba零基礎入門到項目實戰(1元專享)「連結」

億級流量下的電商詳情頁系統實戰項目(1元專享)「連結」

Kafka消息中間件核心源碼精講(1元專享)「連結」

12個實戰案例帶你玩轉Java并發程式設計(1元專享)「連結」

Elasticsearch零基礎入門到精通(1元專享)「連結」

基于Java手寫分布式中間件系統實戰(1元專享)「連結」

基于ShardingSphere的分庫分表實戰課(1元專享)「連結」

繼續閱讀