Hadoop學習之路(一)理論基礎和邏輯思惟

三個題目

第一題

問題描述

統計出當前這個一行一個IP的文件中,到底哪一個IP出現的次數最多數組

解決思路

//必需要能讀取這個內容  

        BufferedReader br = new BuffedReader(new FileInputStream(new File("c:/big.txt")));
          // 每次讀取一行
        String line = null;
        while( (line=br.readLine()) != null){
            // 處理這讀取到的一行內容的代碼
        }

        //最簡單的一種思路:  初始化一個hashmap

        //hashmap中存儲的鍵值對的  key : IP      value : 次數

        int count = 0;  // 就是用來進行存儲當前出現次數最多的那個IP的次數
        String maxip = null;
        Set<String> ips = hashmap.keySet();
        for(String ip :  ips){
            int ipcount = hashmap.get(ip)
            if(ipcount > count){
                count = ipcount
                maxip = ip;
            }
        }
        System.out.println(maxip + " : " +count);

 

問題難點

一、當讀取的文件的大小超過內存的大小時,以上的解決方案是不可行的。服務器

二、假如說你的內存足夠大,能裝下這個文件中的全部ip,整個任務的執行效率會很是低,消耗的時間會很是的長。網絡

  1GB -- 5分數據結構

  1TB --- 1024 * 5 分函數

三、最終整個任務就使用一臺機器,那麼最終整個任務執行完成所消耗的時間是和數據的大小成正比。提高服務器的執行性能來提升數據的處理速度。性能

    當前這一臺機器的執行性能:          5分鐘/GB大數據

    提高服務器的執行性能: CPU :i3 ---> i7 1分鐘/GBurl

在最開始的服務器領域:提高服務器對外提供服務的效率手段就是縱向提高服務器性能。理想是豐滿的,現實是骨感的,可是服務器性能提高有瓶頸。spa

摩爾定律:每隔18-24個月,服務器的性能提高一倍。code

若是說數據的增加是每隔18-24個月就增加一倍,工做量增長了一倍。工做效率也增長了一倍,那麼最終完成同一個任務所花費的時間是同樣的。

可是數據的增加速度是遠遠超過服務器性能的提高。在數據不斷增加的狀況下,單位時間內,服務器所須要處理的數據量是愈來愈大。

假如:

服務器的性能提高 速率 和 數據的增加速率同樣: 在18-24個月
10GB --- 性能: 1分鐘/GB --- 10分鐘
20GB --- 性能: 1分鐘/2GB --- 10分鐘

假如:

服務器的性能提高 速率 和 數據的增加速率不同: 在18-24個月
10GB --- 性能: 1分鐘/GB --- 10分鐘
100GB --- 性能: 1分鐘/2GB --- 50分鐘

最終的結論: 靠 縱向提高服務器性能的手段 在理論上有 瓶頸的。

最終解決方案:縱向不可取,因此採起橫向擴展。

所謂的橫向擴展:就是增長服務器的數量。

一個龐大的複雜任務就應該 平均分配給全部的服務器作處理

10GB 一臺服務器 10分鐘

100GB 一臺服務器 100分鐘

100GB 10臺服務器 10分鐘

10000GB 1000臺 10分鐘

在理論上 有上限麼??沒有

 

兩種狀況下:
一、在數據量比較小的狀況下,單臺服務器就能夠再用戶可接受的時限範圍內完成任務。
二、當數據量變大時,若是用戶也想在可接受的時限範圍內完成任務,那麼可行的方案就是進行服務器的橫向擴展。

核心思想: 大事化小 分而治之
終極解決方案:
一、先把文件切碎成不少的小文件。
二、每個服務器節點去處理一個小文件。
三、再把全部服務器的處理結果彙總到一塊兒。
四、再把全部的數據合併到一塊兒求出出現次數最多的那個ip。

只要是經過網絡傳輸數據,就必定存在丟失數據的可能。

第二題

問題描述

在兩個龐大文件中,文件也都是存儲的URL地址(每行一個),好比文件名叫作file1和file2, 找出這兩個文件中的交集(相同的URL)?

以上問題等同於SQL:select url from file1 a join file2 b on a.url = b.url

問題分析

概念:出如今在file1中的元素也出如今file2中。這些元素的集合就是交集

需求:求2個文件的交集

文件中的元素:URL

解決方案

1.當2個文件都比較小的時候

  步驟:

    1. 編寫一個程序能夠去讀文件的內容,把文件中的全部元素都放置在一個set1中

        編寫一個流處理取讀取文件內容,逐行讀取,每次讀取到的一行放入set1中

    2. 運行相同的程序處理另一個文件的內容,把文件中的全部元素都放置在一個set2中

    3. 先遍歷一個集合,每次遍歷出來的元素都去另一個集合中判斷存在不存在。若是存在,就是共同元素,這個共同元素就存儲在某個集合中resultSet;若是不存在,就不是共同元素。

    4. 結果集:集合resultSet

2.當2個文件都比較大的時候

  第一種思路:採起跟第一個題目同樣的大事化小的策略

  第二種思路:改良第一種思路。避免第一種思路中的不少無效匹配 a1 * a2

        必須作到合理的數據分區,數據分區的兩種最基本的思路:

          1.先排序,而後分段==分區

          2.hash散列  --  求hash值,而後利用hash值求和分區個數的餘數,若是餘數相同,就證實這些元素在同一個分區中

        改良了實現思路以後,可讓原來應該執行16個小任務的大任務。只須要執行4個小任務便可。

終極解決方案:

1.先指定一個分區策略:hash散列

2.預估預估一下數據要被切分紅多少個塊,必定要保證兩個文件切分出來的小文件個數成倍數

3.根據hash散列的策略,對兩份文件分別進行操做

4.根據原來指定的策略,尋找對應的兩個大文件中的對應小文件進行求交集操做

5.全部的結果,根本就不用再進行去重了。直接進行拼接便可。

學到的東西:

  整個大數據生態系統中的不少技術軟件的底層處理數據的分區時,默認的策略都是hash散列。

第三題

問題描述

如今有一個很是龐大的URL庫(10000E),而後如今還有一個URL,(迅速)判斷這個URL是否在這個URL庫中?

問題分析

需求:判斷一個元素在不在某個集合中

解決方案

一、計數排序

一、初始化一個數組 數組的長度 就是 集合中元素的區間長度

二、遍歷集合,把每一個元素放入數組中 尋找對應的下標位置,找出值,而後從新設置成+1的值

三、按序遍歷便可

array[0] = 1, array[1] = 2, array[2] = 0, array[3] = 3,

0 1 1 3 3 3

二、改進需求:

求出某個元素在不在這個數組(數據結構改良以前的集合)中

array[5] = count if count > 0


三、既然是判斷存在不存在。

因此結果其實就是一個狀態 : 要麼存在 要麼不存在

存在 : 1
不存在: 0

把int數組進化成 爲位數組

優點:把數組所要消耗的內存下降到原來的 1/32


改良了以後這種數據結構: BitMap

真正的結構: 一個位數組 + 一個hash函數

四、BitMap再次進行進化

解決的問題: BitMap 中很是容易出現 hash碰撞的問題

我們能夠結合使用多個hash函數來搞定

缺點: 存在必定的誤判率

一、若是這種數據結構(BloomFilter) 告訴你說你要驗證的那個元素不在這個 BloomFilter 中
那就表示 這個元素必定不在這個 BloomFilter 中


二、若是它告訴你這個元素存在, 它告訴你的這個存在的結果 有多是假的

真正的組成:

一個位數組 + 一組hash函數

若是要作工程實現:不論是什麼變種的BloomFilter, 都必定要實現兩個方法:

一、第一個方法是往BloomFilter中存入一個元素

二、第二個方法是驗證一個元素是否在這個BloomFilter 中

誤判率的估計:

一、位數組的長度 m

二、總元素的個數 n

三、hash函數的個數 k

hash函數的個數 並非越多越好

在誤判率最低的狀況下。 這三個參數應該知足的一個公式: k = 0.7 * m / n

相關文章
相關標籤/搜索