貓場面試題第 1 套
以下為我為大家整理的貓場面試題第一套,均為筆者自己參加面試或者一些讀者分享給我的題目,保證真實和准確性。
1 框架部分
1.1 Spark 提交 job 流程
所謂提交流程,其實就是我們開發人員根據需求寫的應用程序通過 Spark 客戶端提交給 Spark 運行環境執行計算的流程。在不同的部署環境中,這個提交過程基本相同,但又有細微的區別。
在國內的工作環境中,將 Spark 引用部署到 Yarn 環境中會更多一些,Spark 應用程序提交到 Yarn 環境中執行的時候,一般會有兩種部署執行的方式:Client 和 Cluster。兩種模式,主要的區別在於:Driver 程序的運行節點。
1.1.1 Yarn Client 模式
Client 模式將用於監控和調度的 Driver 模塊在客戶端執行,而不是 Yarn 中,所以一般用於測試。
- Driver 在任務提交的本地機器上運行。
- Driver 啟動后會和 ResourceManager 通訊申請啟動 ApplicationMaster。
- ResourceManager 分配 container,在合適的 NodeManager 上啟動 ApplicationMaster,負責向 ResourceManager 申請 Executor 內存。
- ResourceManager 接到 ApplicationMaster 的資源申請后會分配 container,然后 ApplicationMaster 在資源分配指定的 NodeManager 上啟動 Executor 進程。
- Executor 進程啟動后會向 Driver 反向注冊,Executor 全部注冊完成后 Driver 開始執行 main 函數。
- 之后執行 Action 算子時,觸發一個 job,並根據寬依賴開始划分 stage,每個 stage 生成對應的 TaskSet,之后將 task 分發到各個 Executor 上執行。
1.1.2 Yarn Cluster 模式
Cluster 模式將用於監控和調度的 Driver 模塊啟動在 Yarn 集群資源中執行。一般應用於實際生產環境。
- 在 Yarn cluster 模式下,任務提交后會和 ResourceManager 通訊申請啟動 ApplicationMaster。
- 隨后 ResourceManager 分配 container,在合適的 NodeManager 上啟動 ApplicationMaster,此時的 ApplicationMaster 就是 Driver。
- Driver 啟動后向 ResourceManager 申請 Executor 內存,ResourceManager 接到 ApplicationMaster 的資源申請后會分配 container,然后在合適的 NodeManager 上啟動 Executor 進程。
- Executor 進程啟動后會向 Driver 反向注冊,Executor 全部注冊完成后 Driver 開始執行 main 函數。
- 之后執行到 Action 算子時,觸發一個 job,並根據寬依賴開始划分 stage,每個 stage 生成對應的 TaskSet,之后將 task 分發到各個 Executor 上執行。
1.2 提交腳本中 -jar 是什么意思
使用 spark-submit 時,應用程序的jar包以及通過 —jars 選項包含的任意 jar 文件都會被自動傳到集群中。如果代碼依賴於其它項目,將這些資源集成打包,在執行 bin/spark-submit 腳本時就可以傳遞這些 jar 包了。
1.3 Executor 怎么獲取 Task
1.4 詳解 Hadoop 的 WordCount
-
將文件拆分成 splits,由於測試用的文件較小,所以每個文件為一個 split,並將文件按行分割形成 <key,value> 對。這一步由MapReduce框架自動完成,其中偏移量(即 key 值)包括了回車所占的字符數(Windows 和 Linux 環境會不同)。
-
將分割好的 <key,value> 對交給用戶定義的 map 方法進行處理,生成新的 <key,value> 對。
-
得到 map 方法輸出的 <key,value> 對后,Mapper 會將它們按照 key 值進行排序,並執行 Combine 過程,將 key 至相同 value 值累加,得到 Mapper 的最終輸出結果。
-
Reducer 先對從 Mapper 接收的數據進行排序,再交由用戶自定義的 reduce 方法進行處理,得到新的 <key,value> 對,並作為 WordCount 的輸出結果。
1.5 Spark 做過哪些優化
優化說完會問你為什么?原理是什么?
Spark 優化細則較多,以后我會把我整理的筆記逐漸上傳
- 常規性能調優
- 算子調優
- Shuffle 調優
- JVM調優
1.6 Spark 內存管理
有關 Spark 的內存管理請看我的下一章 Spark 內存管理
2 算法部分
2.1 單向鏈表翻轉
定義一個函數,輸入一個鏈表的頭節點,反轉該鏈表並輸出反轉后鏈表的頭節點。
示例:
輸入: 1->2->3->4->5->NULL 輸出: 5->4->3->2->1->NULL
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
//新鏈表
ListNode newHead = null;
while (head != null) {
// 先保存訪問的節點的下一個節點,保存起來
// 留着下一步訪問的
ListNode temp = head.next;
// 每次訪問的原鏈表節點都會成為新鏈表的頭結點,
// 其實就是把新鏈表掛到訪問的原鏈表節點的
// 后面就行了
head.next = newHead;
// 更新新鏈表
newHead = head;
// 重新賦值,繼續訪問
head = temp;
}
// 返回新鏈表
return newHead;
}
}
反轉從位置 m 到 n 的鏈表。請使用一趟掃描完成反轉。
說明:
1 ≤ m ≤ n ≤ 鏈表長度。示例:
輸入: 1->2->3->4->5->NULL, m = 2, n = 4 輸出: 1->4->3->2->5->NULL
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode reverseBetween(ListNode head, int m, int n) {
ListNode dmy = new ListNode(0);
dmy.next = head;
int delta = n-m;
ListNode pre = dmy,tail = head;
//先定位出m節點和m之前的節點
while(m>1){
pre = tail;
tail = tail.next;
m--;
}
while(delta > 0){
ListNode next = tail.next;
tail.next = next.next;//tail一直不變,只要修改指針到next.next
next.next = pre.next;//next.next指向pre的next,也就是最新的第m個位置
pre.next = next;//更新next為最新的第m個位置
delta --;
}
return dmy.next;
}
}
2.2 實現堆棧 Push Pop Min 復雜度 O(1)
定義棧的數據結構,請在該類型中實現一個能夠得到棧的最小元素的 min 函數在該棧中,調用 min、push 及 pop 的時間復雜度都是 O(1)。
示例:
MinStack minStack = new MinStack(); minStack.push(-2); minStack.push(0); minStack.push(-3); minStack.min(); --> 返回 -3. minStack.pop(); minStack.top(); --> 返回 0. minStack.min(); --> 返回 -2.
class MinStack {
Stack<Integer> A, B;
public MinStack() {
A = new Stack<>();
B = new Stack<>();
}
public void push(int x) {
A.add(x);
if(B.empty() || B.peek() >= x)
B.add(x);
}
public void pop() {
if(A.pop().equals(B.peek()))
B.pop();
}
public int top() {
return A.peek();
}
public int min() {
return B.peek();
}
}
/**
* Your MinStack object will be instantiated and called as such:
* MinStack obj = new MinStack();
* obj.push(x);
* obj.pop();
* int param_3 = obj.top();
* int param_4 = obj.min();
*/
3 技術部分
第一題
題目:億級的交易訂單量,每筆都有金額,快速找出 top1000,要求不是簡單的排序然后求出 top1000 ,代碼要有健壯性;提示注意是 top1000 不是 top10。
第二題
題目:有兩個約 1000 萬行記錄的 4 到 5G 文件,JVM 只有 32M,在內存不溢出的情況下,找出相似的條數並打印出來。
答案:布隆過濾器
布隆過濾器(Bloom Filter)是 1970 年由布隆提出的。它實際上是一個很長的二進制向量和一系列隨機映射函數。布隆過濾器可以用於檢索一個元素是否在一個集合中。它的優點是空間效率和查詢時間都比一般的算法要好的多,缺點是有一定的誤識別率和刪除困難。
當一個元素加入布隆過濾器中的時候,會進行如下操作:
- 使用布隆過濾器中的哈希函數對元素值進行計算,得到哈希值(有幾個哈希函數得到幾個哈希值)。
- 根據得到的哈希值,在位數組中把對應下標的值置為 1。
當我們需要判斷一個元素是否存在於布隆過濾器的時候,會進行如下操作:
- 對給定元素再次進行相同的哈希計算;
- 得到值之后判斷位數組中的每個元素是否都為 1,如果值都為 1,那么說明這個值在布隆過濾器中,如果存在一個值不為 1,說明該元素不在布隆過濾器中。
第三題
題目:有一個雙十一的天貓場景,我要做實時和離線兩種分析方向,從數據建模、計算性能、元數據管理、數據質量上講一講基本架構設計成什么樣子。
推薦大家兩本書《大數據之路 - 阿里巴巴大數據實踐》、《數倉建模工具箱》。
4 思維部分
第一題
題目:島上有100個囚犯,他們都是藍眼睛,但是他們都只能看到別人眼睛的顏色,並不能知道自己的眼睛顏色,而且他們之間不能去談論眼睛顏色的話題,規定每天晚上都可以有一個人去找守衛說出自己的眼睛顏色,如果錯了被殺死,如果對了被釋放。但是大家在沒有十足的把握前都不敢去找守衛,有一天,一個醫生對他們說你們之中至少有一個藍眼睛,然后N天,這些人都獲救了,為什么?這句話對他們有什么影響?
第二題
題目:有 100 層樓梯,從其中一層摔下雞蛋的時候雞蛋會碎,並且次層之上的都會碎,次層之下的都不會碎,如果你有一個雞蛋、兩個雞蛋、三個雞蛋,你會怎么去找出這個樓層,最多要試多少次?
筆者看法:如果只有一個雞蛋,那只能從第一層開始逐漸嘗試;有兩個雞蛋其中一個可以選擇從 30 層或者 50 層開始,如果碎了那就將第二個雞蛋從 0 開始,如果沒碎那就減少了一半或者三分之一。如果 n 個雞蛋可以進行 n - 1 次嘗試,減少逐層嘗試的次數。