天天看點

大資料啟蒙-單機處理大資料問題

作者:Java機械師

前言

上次講了大資料啟蒙的分治思想,這次根據幾個場景需求,一起來讨論一下大資料單機處理大資料問題。

需求一

假設有一個需求:

有一個非常大的文本檔案,裡面有很多很多的行(上億),隻有兩行一樣,它們出現在未知的位置,需要查找到它們。單機處理這個問題,而且可用的記憶體很少,也就幾十兆。

假設I/O讀取速度是500MB每秒(固态硬碟更快,這邊隻是一個假設值),1T檔案讀取一遍需要約3分鐘,循環周遊需要I/O讀取N次資料,使用分治思想可以使實際為2次I/O讀取時間。記憶體尋址速度比I/O尋址快10萬倍。

方案一:循環對比每一行。第1行作為對比資料,和第2、3、4、n行資料對比,如果沒有重複,就将第2行作為對比資料再循環對比一次。這樣最壞的結果是最後兩行是一樣的,那麼就要讀取n - 1次資料(1T),需要耗時(n-1)*30分鐘。

I/O讀取速度是大多數場景性能的瓶頸。

一個程式員如果在I/O方面可以有很多優化方案,那他就已經進入進階開發的門檻了。那麼我們也來試試邁出這一步。

我們通過readLine()方法讀取檔案資料,每次讀取後,将讀取的資料的hashCode 取模 2000,然後放到對于位置的一個小檔案中,這樣我們周遊了一次整個檔案(30分鐘),将這個檔案分為2000個小檔案。因為hashCode值的算法是固定的,那麼相同行的hashCode值是一樣的,然後取模的值也是一樣的,那相同行就會在同一個小檔案裡面。然後我們再周遊2000個小檔案,就可以找到裡面的相同的行,這時候最大複雜度也是讀取2000個小檔案,一共1T,耗時30分鐘。這樣算起來,最大時間複雜度就是2*30分鐘。

大資料啟蒙-單機處理大資料問題

需求二

假設1T的檔案全部是亂序數字,現在要将這些數字全排序。

這時候使用hashCode就不合适了,因為取數字的hashCode反而增加了一些時間消耗,那麼可以換一種方式。

每次讀取一個數x,如果x大于0且小于等于100,就将這個數放到第一個小檔案中,以此類推,我們可以得到很多個小檔案,這個過程消耗了30分鐘。這些檔案是有大小順序的,但是檔案内部的值是亂序的。然後依次讀取每個小檔案,排序後追加寫入第一個小檔案,這樣消耗了30分鐘,得到了全排序的檔案,最大時間複雜度就是2*30分鐘。

當然,我們還有其他方案,每次先讀取50M資料進行排序,然後放到一個小檔案裡,重複操作後得到若幹個小檔案,這些檔案是沒有順序的,但是檔案内的資料是有順序的。敲重點了,當遇到外部是無序的,内部是有序的資料結構,我們可以使用歸并排序算法。 這裡就細說了。

大資料啟蒙-單機處理大資料問題

需求三

需求一如果想讓時間變為分鐘甚至秒要如何實作?

單機性能瓶頸是I/O速度,通過單機去實作想要達到幾分鐘,甚至幾十秒的難度很大。那麼我們就可以考慮多台機器實作了。假設有2000台機器,每台500M資料,并行讀取資料大概要消耗1秒鐘。然後使用需求一的方式,将500M資料分為2000個小檔案,這時候每台機器中都有2000個小檔案,因為資料是分開的,要判斷是否重複就要吧所有機器中的相同位置的檔案合并起來判斷。那麼我們可以讓第1台機器,拉取其他所有機器的第1個檔案到本機合并資料判斷,以此類推每個機器判斷一個位置的檔案,這是可以并行操作的,假設拉取其他檔案的耗時1分鐘,判斷檔案500M檔案消耗1秒鐘,那麼這個過程大概消耗了62秒。這隻是舉個例子說明解決方案思路,時間并不是很準确。這其實是以資源換取時間的方式。

大資料啟蒙-單機處理大資料問題

叢集分布式處理大資料的辯證

  • 2000台真的比一台速度快馬?
  • 如果考慮分發上傳時間呢?
  • 如果考慮每天都有1T資料産生呢?
  • 如果增量了一年,最後一天計算資料呢?

幾個問題大家可以一起思考辯證一下。

總結

  • 分而治之
  • 并行計算(并發)
  • 計算向資料移動
  • 資料本地化讀取

以上這些點是學習大資料技術時需要關心的重點。

繼續閱讀