大數據面試總結


大數據基礎部分面試題:
一.你了解Hadoop嗎?講一下Hadoop中HDFS的讀寫原理。
讀:
客戶端調用FileSystem的open方法,來打開希望讀取的文件。
FileSystem通過Rpc與namenode通信,namenode將獲取到的信息整理,並將文件的所有內容發送給FileSystem對象,所有的副本塊都會有對應的datanode位置信息;namenode會根據當前的所有節點狀態判斷最佳datanode位置,並且將此datanode的位置信息封裝到傳送的信息中。
客戶端通過FileSystem返回的流對象,調用read方法,開始讀取文件的數據,如果一個文件非常大,數據塊數量龐大,namenode不會一次性返回所有的塊信息,而是一批一批的返回,並且從第一批開始逐次讀取。
對於客戶端來講,讀取數據的操作是不透明的,用戶並不需要關心底層流在數據塊之間的跳轉,或者讀取失敗后的流跳轉,底層流對象會從第一個數據塊開始,直接調用當前的FileSystem返回的流對象的read方法進行連續讀取。
按照順序每當讀完一個數據塊,底層流會跳轉到下一個數據塊讀取。
當所有的數據塊讀取完畢,用戶調用FSDataInputStream的close方法進行關流即可。

寫:

  1. 客戶端調用文件系統create()方法,創建一個新文件。
  2. FileSystem通過Rpc通信,與namenode溝通,在HDFS的命名空間創建一個空的文件名稱,對應一條元數據記錄,namenode會根據文件名稱和客戶端的操作權限進行校驗,如果校驗失敗,則返回IO異常,如果校驗成功就創建臨時的數據記錄。
  3. create()方法調用后,FileSystem對象返回一個流對象(DFSOutputStream),客戶端調用流的write方法進行寫入操作,數據源將會被底層流切分成一個一個64kb大小的package,並在內部以數據隊列“dataqueue”的形式管理這些package。
  4. 保存在DataStreamer隊列(dataqueue)里的package將會被寫入到對應第一個數據塊的最近datanode中,與此同時,package將會從dataqueue里移出,復制到ack queue中等待確認信息的反饋;在傳輸過程中,namenode返回的每個數據塊副本所在的datanode都會彼此之間建立pipeline,寫入到pipeline中的第一個datanode的package會通過雙工通信,傳到第二個,第二個傳到第三個,並且每個datanode每次傳完一個package都會放入一個到ack queue中。
  5. 每一個節點寫入package的時候,在完成寫入后會反饋一個當前package的寫成信息,當最后一個datanode成功存儲之后會返回一個ack package,ack queue成功收到datanode返回的ack package后,保存在ack queue中的package才會移出,到此為止才算一個package寫入成功。
  6. 當所有的數據客戶端調用write方法寫完后會立刻調用close方法,將內部的所有緩存flush,這時留存在dataqueue里的package也會全部寫入到pipeline中。
  7. 等到所有的寫入完成,會判斷當前的文件寫入是否成功,判斷的條件是所有文件的block的副本數量都達到了最小值(默認情況下是1);

二.Mapreduce 的Shuffle過程
在 Map 端的運作
Map function 的運行方式就是從 RecordReader 那邊讀出一個 input key value pair, 處理,然后把處理結果(通常也是 key value pair 形式)寫到一個Hadoop maintained memory buffer 里,然后讀取下一個 input key value pair.

Hadoop maintained memory buffer 里的 key value pair 按 key 值排序,並且按照 reduce partition 分到不同 partition 里(這就是 partitioner 被調用的時候)。一旦 memory buffer 滿了,就會被 Hadoop 寫到 file 里,這個過程叫 spill, 寫出的 file 叫 spill file.

注意,這些 spill file 存在 map 所在 host 的 local disk 上,而不是我們之前介紹過的 HDFS.

隨着 Map 不斷運行,有可能有多個 spill file 被制造出來。當 Map 結束時,這些 spill file 會被 merge 起來——不是 merge 成一個 file,而是按 reduce partition 分成多個。

在 Reduce 端的運作:
由於 Map tasks 有可能在不同時間結束,所以 reduce tasks 沒必要等所有 map tasks 都結束才開始。事實上,每個 reduce task 有一些 threads 專門負責從 map host copy map output(默認是5個,可以通過 $mapred.reduce.parallel.copies 參數設置);考慮到網絡的延遲問題,並行處理可以在一定程度上提高效率。

通過前面的學習,我們知道 Hadoop JobTracker 會根據輸入數據位置安排 map tasks,但 reduce tasks 是不知道這種安排的。那么當 reduce task 需要從map host copy map output 時,它怎么知道 map host 的位置呢(URL/IP)?

其實當 Map tasks 成功結束時,他們會通知負責的 tasktracker, 然后消息通過 jobtracker 的 heartbeat 傳給 jobtracker. 這樣,對於每一個 job, jobtracker 知道 map output 和 map tasks 的關聯。Reducer 內部有一個 thread 負責定期向 jobtracker 詢問 map output 的位置,直到 reducer 得到所有它需要處理的 map output 的位置。

Reducer 的另一個 thread 會把拷貝過來的 map output file merge 成更大的 file. 如果 map task 被 configure 成需要對 map output 進行壓縮,那 reduce 還要對 map 結果進行解壓縮。當一個 reduce task 所有的 map output 都被拷貝到一個它的 host上時,reduce 就要開始對他們排序了。

排序並不是一次把所有 file 都排序,而是分幾輪。每輪過后產生一個結果,然后再對結果排序。最后一輪就不用產生排序結果了,而是直接向 reduce 提供輸入。這時,用戶提供的 reduce function 就可以被調用了。輸入就是 map task 產生的 key value pairs.

三.NIO和IO的區別
NIO vs IO之間的理念上面的區別(NIO將阻塞交給了后台線程執行)
IO是面向流的,NIO是面向緩沖區的
Java IO面向流意味着每次從流中讀一個或多個字節,直至讀取所有字節,它們沒有被緩存在任何地方;
NIO則能前后移動流中的數據,因為是面向緩沖區的
IO流是阻塞的,NIO流是不阻塞的
Java IO的各種流是阻塞的。這意味着,當一個線程調用read() 或 write()時,該線程被阻塞,直到有一些數據被讀取,或數據完全寫入。該線程在此期間不能再干任何事情了
Java NIO的非阻塞模式,使一個線程從某通道發送請求讀取數據,但是它僅能得到目前可用的數據,如果目前沒有數據可用時,就什么都不會獲取。NIO可讓您只使用一個(或幾個)單線程管理多個通道(網絡連接或文件),但付出的代價是解析數據可能會比從一個阻塞流中讀取數據更復雜。
非阻塞寫也是如此。一個線程請求寫入一些數據到某通道,但不需要等待它完全寫入,這個線程同時可以去做別的事情。
選擇器
Java NIO的選擇器允許一個單獨的線程來監視多個輸入通道,你可以注冊多個通道使用一個選擇器,然后使用一個單獨的線程來“選擇”通道:這些通道里已經有可以處理的輸入,或者選擇已准備寫入的通道。這種選擇機制,使得一個單獨的線程很容易來管理多個通道。
四.Kfaka中topic和partition的關系是什么,如何理解?
topic在邏輯上可以被認為是一個queue。每條消費都必須指定它的topic,可以簡單理解為必須指明把這條消息放進哪個queue里。為了使得 Kafka的吞吐率可以水平擴展,物理上把topic分成一個或多個partition,每個partition在物理上對應一個文件夾,該文件夾下存儲 這個partition的所有消息和索引文件。partiton命名規則為topic名稱+有序序號,第一個partiton序號從0開始,序號最大值為partitions數量減1。

五.Mapreduce的shuffle過程
當MAP函數開始產生輸出時,不是直接將文件寫入到磁盤中,而是先將數據寫入到緩存中,並對數據進行一系列的優化操作,以減少數據傳輸的量,並減少REDUCE端的操作。
首先每個MAP會有一個100MB大小的緩沖區,數據從MAP函數輸出時會先進入到緩沖區,當到達緩沖區的閾值(80%)時,一個后台線程開始把數據SPILL(溢出)到磁盤中,此時數據仍然會不斷的寫入到緩存中,若緩沖區已滿,數據會阻塞等待數據從緩沖區寫入磁盤,當緩沖區有剩余大小時,才繼續寫入到緩沖區。
在寫入磁盤前,數據會根據REDUCE的數量並按照MAP函數輸出的KEY值進行PARTITION分區,這樣做的好處是可以將KEY值相同的數據最終匯聚到同一個REDUCE任務中,提高效率。在每個分區中,后台線程會對數據也按照KEY值進行排序,並且在排序后若存在COMBINER合並任務,會將數據按照合並的要求進行合並,其實COMBINER的過程也就是一個小型的REDUCER,這樣做的好處是減少REDUCE端的操作。在講數據寫入磁盤的過程中對數據進行壓縮,也是一個很好的選擇,可以加快磁盤寫入的效率,並且節約磁盤空間,從而減少傳輸到REDUCE任務端的數據量。
在REDUCE端會通過心跳機制向jobTracker來獲取已經執行完畢的MAP任務,通過HTTP的方式來獲得分區文件信息,REDUCE默認存在5個復制線程來對分區中的文件進行復制,在REDUCE端也會村在一個緩沖區,來處理復制過來的文件,若緩沖區同樣達到閾值,會將處理的文件寫入磁盤,在緩沖區處理文件時,若在MAP階段對數據進行了壓縮操作,在REDUCE端需要對數據進行解壓縮才可以處理。最后數據就會進入REDUCE函數進行合並。最終輸出到HDFS文件系統中。

六.Hadoop的調度機制
1.先入先出FIFO
Hadoop 中默認的調度器,它先按照作業的優先級高低,再按照到達時間的先后選擇被執行的作業。

2.公平調度器(相當於時間片輪轉調度)
為任務分配資源的方法,其目的是隨着時間的推移,讓提交的作業獲取等量的集群共享資源,讓用戶公平地共享集群。具體做法是:當集群上只有一個任務在運行時,它將使用整個集群,當有其他作業提交時,系統會將TaskTracker節點空間的時間片分配給這些新的作業,並保證每個任務都得到大概等量的CPU時間。
配置公平調度器
3.容量調度器
支持多個隊列,每個隊列可配置一定的資源量,每個隊列采用 FIFO 調度策略,為 了防止同一個用戶的作業獨占隊列中的資源,該調度器會對同一用戶提交的作業所占資源量進行限定。調度時,首先按以下策略選擇一個合適隊列:計算每個隊列中正在運行的任務數與其應該分得的計算資源之間的比值,選擇一個該比值最小的隊列;然后按以下策略選擇該隊列中一個作業:按照作業優先級和提交時間順序選擇 ,同時考慮用戶資源量限制和內存限制。但是不可剝奪式。

七.Hive中內部表與外部表的區別:
Hive 創建內部表時,會將數據移動到數據倉庫指向的路徑;若創建外部表,僅記錄數據所在的路徑,不對數據的位置做任何改變。在刪除表的時候,內部表的元數據和數據會被一起刪除,而外部表只刪除元數據,不刪除數據。這樣外部表相對來說更加安全些,數據組織也更加靈活,方便共享源數據。
八.Hadoop的二次排序
第一種方法是,Reducer將給定key的所有值都緩存起來,然后對它們再做一個Reducer內排序。但是,由於Reducer需要保存給定key的所有值,可能會導致出現內存耗盡的錯誤。

第二種方法是,將值的一部分或整個值加入原始key,生成一個組合key。這兩種方法各有優勢,第一種方法編寫簡單,但並發度小,數據量大的情況下速度慢(有內存耗盡的危險),

第二種方法則是將排序的任務交給MapReduce框架shuffle,更符合Hadoop/Reduce的設計思想。我們將編寫一個Partitioner,確保擁有相同key(原始key,不包括添加的部分)的所有數據被發往同一個Reducer,還將編寫一個Comparator,以便數據到達Reducer后即按原始key分組。

九.所有的hive任務都會有reducer的執行嗎?

答:不是,由於當前hive的優化,使得一般簡單的任務不會去用reducer任務;只有稍微復雜的任務才會有reducer任務

舉例:使用select * from person ; 就不會有reducer

十.hive表關聯查詢,如何解決數據傾斜的問題?

傾斜原因:

map輸出數據按key Hash的分配到reduce中,由於key分布不均勻、業務數據本身的特、建表時考慮不周、等原因造成的reduce 上的數據量差異過大。

1)、key分布不均勻;

2)、業務數據本身的特性;

3)、建表時考慮不周;

4)、某些SQL語句本身就有數據傾斜;

如何避免:對於key為空產生的數據傾斜,可以對其賦予一個隨機值。

解決方案

1>.參數調節:

hive.map.aggr = true

hive.groupby.skewindata=true

有數據傾斜的時候進行負載均衡,當選項設定位true,生成的查詢計划會有兩個MR Job。第一個MR Job中,Map的輸出結果集合會隨機分布到Reduce中,每個Reduce做部分聚合操作,並輸出結果,這樣處理的結果是相同的Group By Key有可能被分發到不同的Reduce中,從而達到負載均衡的目的;第二個MR Job再根據預處理的數據結果按照Group By Key 分布到 Reduce 中(這個過程可以保證相同的 Group By Key 被分布到同一個Reduce中),最后完成最終的聚合操作。

2>.SQL 語句調節:

1)、選用join key分布最均勻的表作為驅動表。做好列裁剪和filter操作,以達到兩表做join 的時候,數據量相對變小的效果。

2)、大小表Join:

使用map join讓小的維度表(1000 條以下的記錄條數)先進內存。在map端完成reduce.

4)、大表Join大表:

把空值的key變成一個字符串加上隨機數,把傾斜的數據分到不同的reduce上,由於null 值關聯不上,處理后並不影響最終結果。

5)、count distinct大量相同特殊值:

count distinct 時,將值為空的情況單獨處理,如果是計算count distinct,可以不用處理,直接過濾,在最后結果中加1。如果還有其他計算,需要進行group by,可以先將值為空的記錄單獨處理,再和其他計算結果進行union。

十一. 請談一下hive的特點是什么?
hive是基於Hadoop的一個數據倉庫工具,可以將結構化的數據文件映射為一張數據庫表,並提供完整的sql查詢功能,可以將sql語句轉換為MapReduce任務進行運行。其優點是學習成本低,可以通過類SQL語句快速實現簡單的MapReduce統計,不必開發專門的MapReduce應用,十分適合數據倉庫的統計分析。
十二. Kafka主要特點:

  1. 同時為發布和訂閱提供高吞吐量。據了解,Kafka每秒可以生產約25萬消息(50 MB),每秒處理55萬消息(110 MB)。
  2. 可進行持久化操作。將消息持久化到磁盤,因此可用於批量消費,例如ETL,以及實時應用程序。通過將數據持久化到硬盤以及replication防止數據丟失。
  3. 分布式系統,易於向外擴展。所有的producer、broker和consumer都會有多個,均為分布式的。無需停機即可擴展機器。
  4. 消息被處理的狀態是在consumer端維護,而不是由server端維護。當失敗時能自動平衡。
  5. 支持online和offline的場景。
    十三. Spark性能優化主要有哪些手段?
    將默認調用的java序列化器改為kyro序列化器(減少序列化數據80%的空間占用(問:為何序列化可以減少存儲空間占用(回答:對同類型的數據對象的頭進行壓縮合並:我感覺這個我回答錯誤了)));

由於Spark1.6.0的統一內存管理模型,若算法的數據量大,而計算邏輯較為簡單,可以增大內存管理中cache塊的比例(默認70%(我也一下子想不起來,感覺這個附近)),如果是數據量小而算法邏輯復雜,可以適當減少cache快的比例;

如果因對是集群CPU資源過分盈余,可以采用增加core的數目,但是core的數目增加到一定程度后,依舊無法完全利用CPU的計算資源,可以選擇增加Executor的數目,通常環境下,一個Executor推薦設置5個Core的個數,超過5個推薦增加Executor的個數

十四.用mapreduce如何處理數據傾斜問題
數據傾瀉產生原因:其次在reduce端默認的分區方式為按照map函數輸出key的哈希值,根據哈希值將數據散列在Reduce中,這盡在數據分布比較均衡的情況下比較適用。
首先在MAP函數中增加記錄數據傾斜的日志信息,可以通過代碼實現,當某個key值超過預先設定的范圍就打印該key值的日志
自定義分區方法,可以對原始數據進行抽樣的結果來預設定分區的邊界,totalOrderPartitioner中的范圍分區器可以通過預設的分區值進行分區。另一個自定義分區方法是根據數據輸出鍵的背景知識來自定義分區,假如map輸出的鍵值來自於一本書,其中大部分則肯定是省略詞,那么就可以自定義分區將這部分省略次分區到一個REDUCE中,將剩下的鍵值保存在其他的REDUCE中
執行兩次MR的過程,第一次不按照KEY值進行分區,打散數據到REDUCE端,在進行一次MR的操作,這次按照KEY值分區,可以有效的減少數據傾斜的問題。

十五. 列舉你知道的常用的hadoop管理和監控的命令
-ls -cat -text -cp -put -chmod -chown

   -du      -get   -copyFromLocal   -copyToLocal 

  -mv   -rm   - tail   -chgrp

十六. 在mr環節中,那些環節需要優化,如何優化,請詳細說明。
1、 setNumReduceTasks 適當的設置reduce的數量,如果數據量比較大,那么可以增加reduce的數量

2、適當的時候使用 combine 函數,減少網絡傳輸數據量

3、壓縮map和reduce的輸出數據

4、使用SequenceFile二進制文件。

5、通過application 的ui頁面觀察job的運行參數

6、太多小文件,造成map任務過多的問題,應該可以先合並小文件,或者有一個特定的map作為處理小文件的輸入

7、map端效率低原因分析

源文件的大小遠小於HDFS的塊的大小。這意味着任務的開啟和停止要耗費更多的時間,就沒有足夠的時間來讀取並處理輸入數據。
源文件無法分塊。這導致需要通過網絡IO從其他節點讀取文件塊。
一個節點的本地磁盤或磁盤控制器運行在降級模式中,讀取寫入性能都很差。這會影響某個節點,而不是全部節點。
源文件不來自於HDFS。則可能是Hadoop節點和數據源之間的延遲導致了性能低下。
Map任務從其他數據節點讀取數據。可以從JobTracker的map任務細節信息和任務運行嘗試中找到輸入塊的位置。如果輸入塊的位置不是任務執行的節點,那就不是本地數據了。

十七. 如何用MAPREDUCE實現兩張表的連接
方案一:Reduce side join。在Map階段讀取兩張表F1,F2,分別對讀取的KEY VALUE進行TAG標簽,然后輸入到REDUCE端,REDUCE端得到數據后按照相同KEY值,對不同標簽的相同KEY值進行JOIN。
方案二:由於在REDUCE端進行JOIN效率十分低,因為在MAP端有大量的數據進行SHUFFLE到REDUCE端。所以在以下情況下我們可以考慮在MAP端進行JOIN,若兩張表中有一張表比較少,甚至可以放到內存中,那么我們可以利用HADOOP的中DISTRIBUTEDCATCH.ADDCATCHFILE()將文件加載到緩存中,他的參數是URL,在JOBTRACKER加載任務時,會將這個URL下的文件拷貝到各個TASKTRACKER上,並通過DISTRIBUTEDCATCH.GETLOCALCATCHFILE()獲取這個文件,從而進行JOIN操作。

十八. fsimage和edit的區別?
Fsimage是在namenode節點中保存了文件系統所有的目錄、文件信息,文件信息中包含數據塊描述信息,修改時間,訪問時間等。對於目錄來說包括修改時間,訪問權限信息。edit保存的是當對hdfs進行增刪改時記錄的操作,在HADOOP中存在secoundNamenode節點,當namenode中的小文件太多時,將兩個文件發送到secoundNamenode中進行和並,並發送會Namenode來保證當前hdfs中信息的完整。

十九. synchronized和lock的區別
synchronized:在需要同步的對象中加入此控制,synchronized可以加在方法上,也可以加在特定代碼塊中,括號中表示需要鎖的對象。
lock:需要顯示指定起始位置和終止位置。一般使用ReentrantLock類做為鎖,多個線程中必須要使用一個ReentrantLock類做為對象才能保證鎖的生效。且在加鎖和解鎖處需要通過lock()和unlock()顯示指出。所以一般會在finally塊中寫unlock()以防死鎖。

二十. 給40億個不重復的unsigned int的整數,沒排過序的,然后再給一個數,如何快速判斷這個數是否在那40億個數當中?
這個問題在《編程珠璣》里有很好的描述,大家可以參考下面的思路,探討一下:
又因為2^32為40億多,所以給定一個數可能在,也可能不在其中;
這里我們把40億個數中的每一個用32位的二進制來表示
假設這40億個數開始放在一個文件中。
然后將這40億個數分成兩類:
1.最高位為0
2.最高位為1
並將這兩類分別寫入到兩個文件中,其中一個文件中數的個數<=20億,而另一個>=20億(這相當於折半了);
與要查找的數的最高位比較並接着進入相應的文件再查找
再然后把這個文件為又分成兩類:
1.次最高位為0
2.次最高位為1
並將這兩類分別寫入到兩個文件中,其中一個文件中數的個數<=10億,而另一個>=10億(這相當於折半了);
與要查找的數的次最高位比較並接着進入相應的文件再查找。

二十一. HDFS存儲大量的小文件會有什么問題,如何解決?
(1)HDFS不適合大量小文件的存儲,因namenode將文件系統的元數據存放在內存中,因此存儲的文件數目受限於 namenode的內存大小。HDFS中每個文件、目錄、數據塊占用150Bytes。如果存放的文件數目過多的話會占用很大的內存
(2)HDFS適用於高吞吐量,而不適合低時間延遲的訪問。如果同時存入大量的小文件會花費很長的時間
(3) 流式讀取的方式,不適合多用戶寫入,以及任意位置寫入。如果訪問小文件,則必須從一個datanode跳轉到另外一個datanode,這樣大大降低了讀取性能。

二十二.Hbase的表設計原則
HBase表的設計 主要是 列族的設計 和 行鍵的設計

1.列族的設計
	在設計hbase表時候,列族不宜過多,越少越好,官方推薦hbase表的列族不宜超過3個。
	經常要在一起查詢的數據最好放在一個列族中,盡量的減少跨列族的數據訪問。	
	如果有多個列族 多個列族中的數據應該設計的比較均勻
2.行鍵的設計
	hbase表中行鍵是唯一標識一個表中行的字段,所以行鍵設計的好不好將會直接影響未來對hbase的查詢的性能和查詢的便利性
	所以hbase中的行鍵是需要進行設計的
	
	行鍵設計的基本原則:
		行鍵必須唯一
			必須唯一才能唯一標識數據
		行鍵必須有意義
			這樣才能方便數據的查詢
		行鍵最好是字符串類型
			因為數值類型在不同的系統中處理的方式可能不同
		行鍵最好具有固定的長度
			不同長度的數據可能會造成自然排序時排序的結果和預期不一致
		行鍵不宜過長
			行鍵最多可以達到64KB,但是最好是在10~100字節之間,最好不要超過16字節,越短越好,最好是8字節的整數倍。
	
	行鍵的最佳實踐:
		散列原則:
			行鍵的設計將會影響數據在hbase表中的排序方式,這會影響region切分后的結果,要注意,在設計行鍵時應該讓經常要查詢的數據分散在不同的region中,防止某一個或某幾個regionserver成為熱點。
		有序原則:
			行鍵的設計將會影響數據在hbase表中的排序方式,所以一種策略是將經常連續查詢的條件作為行鍵最前面的數據,這樣一來可以方便批量查詢

二十三.Hadoop的壓縮算法
Hadoop 對於壓縮格式的是自動識別。如果我們壓縮的文件有相應壓縮格式的擴展名(比如 lzo,gz,bzip2 等)。
Hadoop 會根據壓縮格式的擴展名自動選擇相對應的解碼器來解壓數據,此過程完全是 Hadoop 自動處理,我們只需要確保輸入的壓縮文件有擴展名。
Hadoop 對每個壓縮格式的支持, 詳細見下表:
壓縮格式 工具 算法 擴展名 多文件 可分割性
DEFLATE 無 DEFLATE .deflate 不 不
GZIP gzip DEFLATE .gzp 不 不
ZIP zip DEFLATE .zip 是 是,在文件范圍內
BZIP2 bzip2 BZIP2 .bz2 不 是
LZO lzop LZO .lzo 不 是
如果壓縮的文件沒有擴展名,則需要在執行 MapReduce 任務的時候指定輸入格式。

  1. Bzip2 壓縮效果明顯是最好的,但是 bzip2 壓縮速度慢,可分割。

  2. Gzip 壓縮效果不如 Bzip2,但是壓縮解壓速度快,不支持分割。

  3. LZO 壓縮效果不如 Bzip2 和 Gzip,但是壓縮解壓速度最快!並且支持分割!

1.gzip壓縮
優點:
壓縮率比較高,而且壓縮/解壓速度也比較快;
hadoop本身支持,在應用中處理gzip格式的文件就和直接處理文本一樣;
有hadoop native庫;
大部分linux系統都自帶gzip命令,使用方便。
缺點:不支持split。
應用場景:
當每個文件壓縮之后在130M以內的(1個塊大小內),都可以考慮用gzip壓縮格式。譬如說一天或者一個小時的日志壓縮成一個gzip文件,運行mapreduce程序的時候通過多個gzip文件達到並發。
hive程序,streaming程序,和java寫的mapreduce程序完全和文本處理一樣,壓縮之后原來的程序不需要做任何修改。
2.lzo壓縮
優點:
壓縮/解壓速度也比較快,合理的壓縮率;
支持split,是hadoop中最流行的壓縮格式;
支持hadoop native庫;
可以在linux系統下安裝lzop命令,使用方便。
缺點:
壓縮率比gzip要低一些;
hadoop本身不支持,需要安裝;
在應用中對lzo格式的文件需要做一些特殊處理(為了支持split需要建索引,還需要指定inputformat為lzo格式)。
應用場景:
一個很大的文本文件,壓縮之后還大於200M以上的可以考慮,而且單個文件越大,lzo優點越明顯。
3.snappy壓縮
優點:
高速壓縮速度和合理的壓縮率;
支持hadoop native庫。
缺點:
不支持split;
壓縮率比gzip要低;
hadoop本身不支持,需要安裝;
linux系統下沒有對應的命令。
應用場景:
當mapreduce作業的map輸出的數據比較大的時候,作為map到reduce的中間數據的壓縮格式;
或者作為一個mapreduce作業的輸出和另外一個mapreduce作業的輸入。
4.bzip2壓縮
優點:
支持split;
具有很高的壓縮率,比gzip壓縮率都高;
hadoop本身支持,但不支持native;
在linux系統下自帶bzip2命令,使用方便。
缺點:
壓縮/解壓速度慢;
不支持native。
應用場景:
適合對速度要求不高,但需要較高的壓縮率的時候,可以作為mapreduce作業的輸出格式;
或者輸出之后的數據比較大,處理之后的數據需要壓縮存檔減少磁盤空間並且以后數據用得比較少的情況;
或者對單個很大的文本文件想壓縮減少存儲空間,同時又需要支持split,而且兼容之前的應用程序(即應用程序不需要修改)的情況。

二十四.算法思想題

  1. 給定a,b兩個文件,各存放50億個url,每個url各占64字節,內存限制4G,讓你找出a,b文件共同的url。
    方案1:可以估計每個文件按大小為50G*64=320G,遠遠大於內存限制的4G,所以不可能完全加載到內存中處理,考慮采取分而治之的方法。
    S遍歷文件a,對每個url求取hash%1000,然后根據所取得的值將rul分別存儲到1000個小文件(a0,a1,a2….a999),這樣每個文件大小約為300M。
    S遍歷文件b,采取和a相同的方式將url存儲到1000個小文件中,這樣處理后,所有可能相同的url都在對應的小文件(a0—b0,a1—b1….),不對應的小文件不可能有相同的url,然后我們只要求出1000對小文件中相同的url即可。 s 求每對小文件中相同的url時,可以把其中一個小文件的url存儲到hash_set中。然后遍歷另一個小文件的每個url,看其是否在剛才構建的hash_set中,如果是,那么就是共同的url,存到文件里面就可以了。

  方案2:如果允許有一定的錯誤率,可以使用Bloom filter,4G內存大概可以表示340億bit。將其中一個文件中的url使用Bloom filter映射為這340億bit,然后挨個讀取另外一個文件的url,檢查是否與Bloom filter,如果是,那么該url應該是共同的url(注意會有一定的錯誤率)。
二十五.算法思想題二 
有10個文件,每個文件1G,每個文件的每一行存放的都是用戶的query,每個文件的query都可能重復。要求你按照query的頻度排序。
  方案1:
  s 順序讀取10個文件,按照hash(query)%10的結果將query寫入到另外10個文件(記為)中。這樣新生成的文件每個的大小大約也1G(假設hash函數是隨機的)。
  s 找一台內存在2G左右的機器,依次對用hash_map(query, query_count)來統計每個query出現的次數。利用快速/堆/歸並排序按照出現次數進行排序。將排序好的query和對應的query_cout輸出到文件中。這樣得到了10個排好序的文件(記為)。
  s 對這10個文件進行歸並排序(內排序與外排序相結合)。
  方案2:
  一般query的總量是有限的,只是重復的次數比較多而已,可能對於所有的query,一次性就可以加入到內存了。這樣,我們就可以采用trie樹/hash_map等直接來統計每個query出現的次數,然后按出現次數做快速/堆/歸並排序就可以了。
  方案3:
  與方案1類似,但在做完hash,分成多個文件后,可以交給多個文件來處理,采用分布式的架構來處理(比如MapReduce),最后再進行合並。
二十六.算法思想題三
有一個1G大小的一個文件,里面每一行是一個詞,詞的大小不超過16字節,內存限制大小是1M。返回頻數最高的100個詞。

  方案1:順序讀文件中,對於每個詞x,取,然后按照該值存到5000個小文件(記為)中。這樣每個文件大概是200k左右。如果其中的有的文件超過了1M大小,還可以按照類似的方法繼續往下分,知道分解得到的小文件的大小都不超過1M。對每個小文件,統計每個文件中出現的詞以及相應的頻率(可以采用trie樹/hash_map等),並取出出現頻率最大的100個詞(可以用含100個結點的最小堆),並把100詞及相應的頻率存入文件,這樣又得到了5000個文件。下一步就是把這5000個文件進行歸並(類似與歸並排序)的過程了。

二十七.算法思想題四

一共有N個機器,每個機器上有N個數。每個機器最多存O(N)個數並對它們操作。如何找到個數中的中數?

  方案1:先大體估計一下這些數的范圍,比如這里假設這些數都是32位無符號整數(共有個)。我們把0到的整數划分為N個范圍段,每個段包含個整數。比如,第一個段位0到,第二段為到,…,第N個段為到。然后,掃描每個機器上的N個數,把屬於第一個區段的數放到第一個機器上,屬於第二個區段的數放到第二個機器上,…,屬於第N個區段的數放到第N個機器上。注意這個過程每個機器上存儲的數應該是O(N)的。下面我們依次統計每個機器上數的個數,一次累加,直到找到第k個機器,在該機器上累加的數大於或等於,而在第k-1個機器上的累加數小於,並把這個數記為x。那么我們要找的中位數在第k個機器中,排在第位。然后我們對第k個機器的數排序,並找出第個數,即為所求的中位數。復雜度是的。

  方案2:先對每台機器上的數進行排序。排好序后,我們采用歸並排序的思想,將這N個機器上的數歸並起來得到最終的排序。找到第個便是所求。復雜度是的。

二十八.算法思想題五
將多個集合合並成沒有交集的集合:給定一個字符串的集合,格式如:。要求將其中交集不為空的集合合並,要求合並完成的集合之間無交集,例如上例應輸出。
  (1) 請描述你解決這個問題的思路;
  (2) 給出主要的處理流程,算法,以及算法的復雜度;
(3) 請描述可能的改進。

  方案1:采用並查集。首先所有的字符串都在單獨的並查集中。然后依掃描每個集合,順序合並將兩個相鄰元素合並。例如,對於,首先查看aaa和bbb是否在同一個並查集中,如果不在,那么把它們所在的並查集合並,然后再看bbb和ccc是否在同一個並查集中,如果不在,那么也把它們所在的並查集合並。接下來再掃描其他的集合,當所有的集合都掃描完了,並查集代表的集合便是所求。復雜度應該是O(NlgN)的。改進的話,首先可以記錄每個節點的根結點,改進查詢。合並的時候,可以把大的和小的進行合,這樣也減少復雜度。

二十九.Hive UDF編寫錯誤從哪方面調錯?

首先查日志,UDF的日志是保存在Hadoop MR的日志文件中,
其次通過錯誤提示通過管道符grep |查找問題所在,並針對問題進行改進

在日志文件過大的情況下,可以通過head tail sed 等指令進行分段查找

三十.什么是tire樹?
Trie樹,又稱單詞查找樹、字典樹,是一種樹形結構,是一種哈希樹的變種,是一種用於快速檢索的多叉樹結構。典型應用是用於統計和排序大量的字符串(但不僅限於字符串),所以經常被搜索引擎系統用於文本詞頻統計。它的優點是:最大限度地減少無謂的字符串比較,查詢效率比哈希表高。
Trie的核心思想是空間換時間。利用字符串的公共前綴來降低查詢時間的開銷以達到提高效率的目的。
Trie樹也有它的缺點,Trie樹的內存消耗非常大.當然,或許用左兒子右兄弟的方法建樹的話,可能會好點.
三點特征:
1)根節點不包含字符,除根節點外每一個節點都只包含一個字符。  
2)從根節點到某一節點,路徑上經過的字符連接起來,為該節點對應的字符串。 
3)每個節點的所有子節點包含的字符都不相同。

三十一. 500桶酒,其中1桶是毒酒;48小時后要舉行酒會;毒酒喝下去會在之后的第23-24小時內毒死人;國王決定用囚犯來試酒,不介意囚犯死多少,只要求用最少的囚犯來測試出哪一桶是毒酒,問最少需要多少囚犯才能保證找出毒酒?請諸位自序們為烏有國王出個主意!

思路一
需要9個人
將500桶毒酒進行編號,並用二進制表示.得到000000000~111110100.
每個囚犯對應二進制的每一位,然后喝下對應位數為1的那個編號的毒酒
然后根據死亡的囚犯編號或者毒酒的二進制編碼.
進而獲得毒酒的編號.
如毒酒編號為350,那么二進制對應為101011110.難么囚犯234579會死亡.

思路二
需要兩個人,因為23*23=529>500
將毒酒進行編號,並且每23桶作為一組,123;2446…..
囚犯一每小時喝下每一組酒
囚犯二每小時喝下每一組中對應的酒,如第一小時喝下每組的第一桶酒.第二小時喝下每一組對應的第二桶酒.
然后根據死亡時間進行交叉查找

根據2人死亡計時和行、列交叉點即可找到那桶毒酒了。
如囚犯一34小時死亡,代表(34-23)組酒有毒,即231~253有毒.
囚犯二38小時死亡,代表每組的(38-23)號=15號有問題.
綜合后即為231+15-1=245號酒有問題.

簡單地說把500桶分成23行22列:
第一個囚犯每小時喝一行;
第二個囚犯每小時喝一列。
根據2人死亡計時和行、列交叉點即可找到那桶毒酒了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM