公衆號(五分鐘學大數據)將推出大數據面試系列文章—五分鐘小面試,此係列文章將會深刻研究各大廠筆面試真題,並根據筆面試題擴展相關的知識點,助力你們都可以成功入職大廠!java
大數據筆面試系列文章分爲兩種類型:混合型(即一篇文章中會有多個框架的知識點—融會貫通);專項型(一篇文章針對某個框架進行深刻解析—專項演練)。mysql
此篇文章爲系列文章的第一篇(混合型)面試
class Father{ static { System.out.println("Static Father"); } { System.out.println("Non-static Father"); } public Father(){ System.out.println("Constructor Father"); } } public class Son extends Father{ static { System.out.println("Static Son"); } { System.out.println("Non-static Son"); } public Son(){ System.out.println("Constructor Son"); } public static void main(String[] args) { System.out.println("First Son"); new Son(); System.out.println("Second Son"); new Son(); } }
運行結果:算法
Static Father Static Son First Son Non-static Father Constructor Father Non-static Son Constructor Son Second Son Non-static Father Constructor Father Non-static Son Constructor Son
分析:sql
這道程序題考察的是Java中的靜態代碼塊、構造代碼塊、構造函數的概念。數據庫
隨着類的加載而執行,即JVM加載類後就執行,並且只執行一次,執行優先級高於非靜態的初始化塊,它會在類初始化的時候執行一次,執行完成便銷燬,它僅能初始化類變量,即static修飾的數據成員。編程
執行的時候若是有靜態代碼塊,先執行靜態代碼塊再執行非靜態代碼塊,在每一個對象生成時都會被執行一次,它能夠初始化類的實例變量。非靜態代碼塊會在構造函數執行時,在構造函數主體代碼執行以前被運行。緩存
對象一創建,就會調用與之相應的構造函數,也就是說,不創建對象,構造函數是不會運行的。
一個對象創建,構造函數只運行一次,而通常方法能夠被該對象調用屢次。安全
再來看本題,程序運行,執行main()方法會先加載main()方法所在的類,加載 Son 類,可是 Son 類繼承自 Father 類,因此先加載父類,同時父類的靜態代碼塊執行,而後加載 Son 類自己,Son 類本身的靜態代碼塊開始執行,類加載完成以後執行main()方法內部的語句,打印 First Son,而後 new Son(),在建立對象時先構造父類的對象,由於靜態代碼塊只在類加載時執行一次,因此再也不執行,而後執行父類的構造代碼塊,構造函數,構造代碼塊的優先級大於構造函數。而後在執行 Son 對象自己。完成以後打印 Second Son,接着又 new Son(),重複以上步驟。構造代碼塊和構造函數在每次new的時候都會執行一次。mysql優化
答:一般咱們定義一個基本數據類型的變量,一個對象的引用,還有就是函數調用的現場保存都使用內存中的棧空間;而經過new關鍵字和構造器建立的對象放在堆空間;程序中的字面量(literal)如直接書寫的100、「hello」和常量都是放在靜態存儲區中。棧空間操做最快可是也很小,一般大量的對象都是放在堆空間,整個內存包括硬盤上的虛擬內存均可以被當成堆空間來使用。
String str = new String(「hello」);
上面的語句中str放在棧上,用new建立出來的字符串對象放在堆上,而「hello」這個字面量放在靜態存儲區。
補充:較新版本的Java中使用了一項叫「逃逸分析「的技術,能夠將一些局部對象放在棧上以提高對象的操做性能。(在 Java SE 6u23+ 開始支持,並默認設置爲啓用狀態,能夠不用額外加這個參數。)
答:方案 1:申請 512M 的內存,512M是42億多 bit,一個 bit 位表明一個 unsigned int 值。讀入 40 億個數,設置相應的 bit 位,讀入要查詢的數,查看相應 bit 位是否爲 1,爲 1 表示存在,爲 0 表示不存在。
方案 2:這個問題在《編程珠璣》裏有很好的描述,你們能夠參考下面的思路,探討一下: 由於 2^32 爲 42 億多,因此給定一個數可能在,也可能不在其中; 這裏咱們把 40 億個數中的每個用 32 位的二進制來表示 ,假設這 40 億個數開始放在一個文件中。 而後將這 40 億個數分紅兩類:
並將這兩類分別寫入到兩個文件中,其中一個文件中數的個數<=20 億,而另外一個>=20 億(至關於折半); 與要查找的數的最高位比較並接着進入相應的文件再查找
而後再把這個文件爲又分紅兩類:
並將這兩類分別寫入到兩個文件中,其中一個文件中數的個數<=10 億,而另外一個>=10 億(至關於折半); 與要查找的數的次最高位比較並接着進入相應的文件再查找。
.....
以此類推,就能夠找到了,並且時間複雜度爲 O(logn)。
答:
一個 MapReduce 做業由 Map 階段和 Reduce 階段兩部分組成,這兩階段會對數據排序,從這個意義上說,MapReduce 框架本質就是一個 Distributed Sort。
在 Map 階段,Map Task 會在本地磁盤輸出一個按照 key 排序(採用的是快速排序)的文件(中間可能產生多個文件,但最終會合併成一個),在 Reduce 階段,每一個 Reduce Task 會對收到的數據排序(採用的是歸併排序),這樣,數據便按照 Key 分紅了若干組,以後以組爲單位交給 reduce 處理。
不少人的誤解在 Map 階段,若是不使用 Combiner 便不會排序,這是錯誤的,無論你用不用 Combiner,Map Task 均會對產生的數據排序(若是沒有 Reduce Task,則不會排序,實際上 Map 階段的排序就是爲了減輕 Reduce端排序負載)。
答:
kafka數據分區和消費者的關係:1個partition只能被同組的⼀一個consumer消費,同組的consumer則起到均衡效果
kafka的數據offset讀取流程:
答:
利用select … where … for update 排他鎖
注意: 其餘附加功能與實現基本一致,這裏須要注意的是「where name=lock 」,name字段必需要走索引,不然會鎖表。有些狀況下,好比表不大,mysql優化器會不走這個索引,致使鎖表問題。
所謂樂觀鎖與悲觀鎖最大區別在於基於CAS思想,是不具備互斥性,不會產生鎖等待而消耗資源,操做過程當中認爲不存在併發衝突,只有update version失敗後才能覺察到。咱們的搶購、秒殺就是用了這種實現以防止超賣。
樂觀鎖是經過增長遞增的版本號字段實現的。
基於緩存(Redis等)實現分佈式鎖:(過時時間很差控制,非阻塞,失敗須要輪詢耗CPU)
獲取鎖的時候,使用setnx加鎖,並使用expire命令爲鎖添加一個超時時間,超過該時間則自動釋放鎖,鎖的value值爲一個隨機生成的UUID,經過此在釋放鎖的時候進行判斷。
獲取鎖的時候還設置一個獲取的超時時間,若超過這個時間則放棄獲取鎖。
大體思想:每一個客戶端對某個功能加鎖時,在zookeeper上的與該功能對應的指定節點的目錄下,⽣生成⼀個惟一的瞬時有序節點。判斷是否獲取鎖的方式很簡單,只須要判斷有序節點中序號最小的一個。當釋放鎖的時候,只需將這個瞬時節點刪除便可。同時,其能夠避免服務宕機致使的鎖沒法釋放,⽽而產生的死鎖問題。
優勢:鎖安全性高,zk可持久化,且能實時監聽獲取鎖的客戶端狀態。一旦客戶端宕機,則瞬時節點隨之消失,zk因⽽而能第一時間釋放鎖。這也省去了用分佈式緩存實現鎖的過程當中須要加入超時時間判斷的這一邏輯。
缺點:性能開銷⽐比較高。由於其須要動態產生、銷燬瞬時節點來實現鎖功能。因此不太適合直接提供給高併發的場景使用。
實現:能夠直接採用zookeeper第三方庫curator便可方便地實現分佈式鎖。
答:
Hadoop底層使用MapReduce計算架構,只有map和reduce兩種操做,表達能力比較欠缺,並且在MR過程當中會重複的讀寫hdfs,形成大量的磁盤io讀寫操做,因此適合高時延環境下批處理計算的應用;
Spark是基於內存的分佈式計算架構,提供更加豐富的數據集操做類型,主要分紅轉化操做和行動操做,包括map、reduce、filter、flatmap、groupbykey、reducebykey、union和join等,數據分析更加快速,因此適合低時延環境下計算的應用;
spark與hadoop最大的區別在於迭代式計算模型。基於mapreduce框架的Hadoop主要分爲map和reduce兩個階段,兩個階段完了就結束了,因此在一個job裏面能作的處理頗有限;spark計算模型是基於內存的迭代式計算模型,能夠分爲n個階段,根據用戶編寫的RDD算子和程序,在處理完一個階段後能夠繼續往下處理不少個階段,而不僅是兩個階段。因此spark相較於mapreduce,計算模型更加靈活,能夠提供更強大的功能。
可是spark也有劣勢,因爲spark基於內存進行計算,雖然開發容易,可是真正面對大數據的時候,在沒有進行調優的狀況下,可能會出現各類各樣的問題,好比OOM內存溢出等狀況,致使spark程序可能沒法運行起來,而mapreduce雖然運行緩慢,可是至少能夠慢慢運行完。
答:
當 jobclient 向YARN提交一個應用程序後,YARN將分兩個階段運行這個應用程序:一是啓動ApplicationMaster;第二個階段是由ApplicationMaster建立應用程序,爲它申請資源,監控運行直到結束。
具體步驟以下:
用戶向YARN提交一個應用程序,並指定ApplicationMaster程序、啓動ApplicationMaster的命令、用戶程序。
RM爲這個應用程序分配第一個Container,並與之對應的NM通信,要求它在這個Container中啓動應用程序ApplicationMaster。
ApplicationMaster向RM註冊,而後拆分爲內部各個子任務,爲各個內部任務申請資源,並監控這些任務的運行,直到結束。
AM採用輪詢的方式向RM申請和領取資源。
RM爲AM分配資源,以Container形式返回。
AM申請到資源後,便與之對應的NM通信,要求NM啓動任務。
NodeManager爲任務設置好運行環境,將任務啓動命令寫到一個腳本中,並經過運行這個腳本啓動任務。
各個任務向AM彙報本身的狀態和進度,以便當任務失敗時能夠重啓任務。
答:
如一張表的記錄數在一個已知的範圍內,或者上下浮動不會超過某個閾值:
SQL結果:var 數據量 = select count(*)from 表 where 時間等過濾條件
報警觸發條件設置:若是數據量不在[數值下限, 數值上限], 則觸發報警
同比增長:若是((本週的數據量 -上週的數據量)/上週的數據量*100)不在 [比例下線,比例上限],則觸發報警
環比增長:若是((今天的數據量 - 昨天的數據量)/昨天的數據量*100)不在 [比例下線,比例上限],則觸發報警
單表空值檢測
某個字段爲空的記錄數在一個範圍內,或者佔總量的百分比在某個閾值範圍內
目標字段:選擇要監控的字段,不能選「無」
SQL結果:var 異常數據量 = select count(*) from 表 where 目標字段 is null
單表重複值檢測
一個或多個字段是否知足某些規則
目標字段:第一步先正常統計條數;select count(*) form 表;
第二步,去重統計;select count(*) from 表 group by 某個字段
第一步的值和第二步的值作減法,看是否在上下線閥值以內
跨表數據量對比
主要針對同步流程,監控兩張表的數據量是否一致
SQL結果:count(本表) - count(關聯表)
答:這類問題都歸爲求Top K的問題,解決方法都差很少。
將這一天訪問百度的日誌的IP取出來,逐個寫入到一個大文件中。注意到IP是32位的,最多有個2^32個IP。一樣能夠採用映射的方法,好比模1000,把整個大文件映射爲1000個小文件,再找出每一個小文中出現頻率最大的IP(能夠採用 HashMap 進行頻率統計,而後再找出頻率最大的幾個)及相應的頻率。而後再在這1000個最大的IP中找出那個頻率最大的IP,即爲所求。
算法思想:分而治之+Hash
IP地址最多有2^32=4G種取值狀況,因此不能徹底加載到內存中處理;
能夠考慮採用分而治之的思想,按照IP地址的Hash(IP) % 1024值,把海量IP日誌分別存儲到1024個
小文件中,這樣每一個小文件最多包含4MB個IP地址; 這裏解釋一下爲何用Hash(IP) % 1024值,若是不用,而直接分類的話,可能會出現這樣一種狀況,就是有個IP在每一個小文件中都存在,並且這個IP並不必定在那個小文件中是數量最多的,那麼最終可能選擇的結果會有問題,因此這裏用了Hash(IP)%1024值,這樣的話,經過計算IP的Hash值,相同IP確定會放到一個文件中,固然了不一樣的IP的Hash值也可能相同,就存在一個小文件中。
對於每個小文件,能夠構建一個IP爲key,出現的次數爲value的HashMap,同時記錄當前出現次數最多的那個IP地址;