大數據基礎部分面試題:
一.你瞭解Hadoop嗎?講一下Hadoop中HDFS的讀寫原理。
讀:
客戶端調用FileSystem的open方法,來打開但願讀取的文件。
FileSystem經過Rpc與namenode通訊,namenode將獲取到的信息整理,並將文件的全部內容發送給FileSystem對象,全部的副本塊都會有對應的datanode位置信息;namenode會根據當前的全部節點狀態判斷最佳datanode位置,而且將此datanode的位置信息封裝到傳送的信息中。
客戶端經過FileSystem返回的流對象,調用read方法,開始讀取文件的數據,若是一個文件很是大,數據塊數量龐大,namenode不會一次性返回全部的塊信息,而是一批一批的返回,而且從第一批開始逐次讀取。
對於客戶端來說,讀取數據的操做是不透明的,用戶並不須要關心底層流在數據塊之間的跳轉,或者讀取失敗後的流跳轉,底層流對象會從第一個數據塊開始,直接調用當前的FileSystem返回的流對象的read方法進行連續讀取。
按照順序每當讀完一個數據塊,底層流會跳轉到下一個數據塊讀取。
當全部的數據塊讀取完畢,用戶調用FSDataInputStream的close方法進行關流便可。java
寫:node
二.Mapreduce 的Shuffle過程
在 Map 端的運做
Map function 的運行方式就是從 RecordReader 那邊讀出一個 input key value pair, 處理,而後把處理結果(一般也是 key value pair 形式)寫到一個Hadoop maintained memory buffer 裏,而後讀取下一個 input key value pair.linux
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 分紅多個。sql
在 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主要特色:
因爲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環節中,那些環節須要優化,如何優化,請詳細說明。
一、 setNumReduceTasks 適當的設置reduce的數量,若是數據量比較大,那麼能夠增長reduce的數量
二、適當的時候使用 combine 函數,減小網絡傳輸數據量 三、壓縮map和reduce的輸出數據
四、使用SequenceFile二進制文件。
五、經過application 的ui頁面觀察job的運行參數
六、太多小文件,形成map任務過多的問題,應該能夠先合併小文件,或者有一個特定的map做爲處理小文件的輸入
七、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,並且兼容以前的應用程序(即應用程序不須要修改)的狀況。
二十四.算法思想題
方案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桶做爲一組,1~23;24~46…..
囚犯一每小時喝下每一組酒
囚犯二每小時喝下每一組中對應的酒,如第一小時喝下每組的第一桶酒.第二小時喝下每一組對應的第二桶酒.
而後根據死亡時間進行交叉查找
根據2人死亡計時和行、列交叉點便可找到那桶毒酒了。
如囚犯一34小時死亡,表明(34-23)組酒有毒,即231~253有毒.
囚犯二38小時死亡,表明每組的(38-23)號=15號有問題.
綜合後即爲231+15-1=245號酒有問題.
簡單地說把500桶分紅23行22列: 第一個囚犯每小時喝一行; 第二個囚犯每小時喝一列。 根據2人死亡計時和行、列交叉點便可找到那桶毒酒了。