感覺面試官挺不友好的,說不上來的怪。依舊沒有問項目。
這次其實挺虧的,很多問題都會,但是回答好像沒有get到面試官的點,然後算法當時太緊張也沒寫出來,面試完立刻就寫出來了c
Web
1. Nginx和Redis的網絡模型
Nginx採用Master-Worker多進程模型(易於管理,各個Worker不相互影響),多路複用
Redis基於內存和多路複用,同時採用單線程模型
2. Nginx反向代理使用TCP還是HTTP
看見這個題,我第一個反應是 ?HTTP不是基於TCP的嗎???,我說了nginx反向代理的Tomcat,Tomcat使用HTTP,所以是HTTP
3. TCP和HTTP的區別
- TCP屬於運輸層,HTTP屬於應用層
- TCP基於Socket,即IP+端口,而HTTP則是基於相對的url
- HTTP的長連接和多路複用基於TCP的長連接
4. Nginx緩存的方式
三種方式,基於文件,基於內存,通過lua腳本
5. 多個緩存失效時間不一樣怎麼辦
我回答的是採用hash,這樣一臺client就會鎖定一個緩存
6. 多路複用模型
多個IO請求註冊到select中,然後select負責阻塞,如果內核數據準備好了之後則會返回Select
多路複用分爲三種,分別是selector,poll,epoll
對於selector來說,使用數組,限制1024,selector需要把數據從用戶態拷貝到內核態,然後當selector中某個時間準備好之後就會重新把selector中的事件從用戶態拷貝到內核態,此時IO線程則在遍歷整個selector
對於poll來說,使用鏈表,沒有1024限制
對於epoll來說,使用map,每個請求都通過epoll_create()封裝爲一個epoll對象,然後通過epoll_ctl將epoll對象加入到內核態,有內核對事件進行準備,如果準備好則放入list中,epoll_wait相當於之前的select/poll的調用,只不過不需要遍歷整個事件
7. Epoll的邊緣觸發和水平觸發
水平觸發:當被監控的文件描述符上有可讀寫事件發生時,epoll_wait()會通知處理程序去讀寫。如果這次沒有把數據一次性全部讀寫完(如讀寫緩衝區太小),那麼下次調用 epoll_wait()時,它還會通知你在上沒讀寫完的文件描述符上繼續讀寫,當然如果你一直不去讀寫,它會一直通知你!!!如果系統中有大量你不需要讀寫的就緒文件描述符,而它們每次都會返回,這樣會大大降低處理程序檢索自己關心的就緒文件描述符的效率
邊緣觸發:當被監控的文件描述符上有可讀寫事件發生時,epoll_wait()會通知處理程序去讀寫。如果這次沒有把數據全部讀寫完(如讀寫緩衝區太小),那麼下次調用epoll_wait()時,它不會通知你,也就是它只會通知你一次,直到該文件描述符上出現第二次可讀寫事件纔會通知你!!!這種模式比水平觸發效率高,系統不會充斥大量你不關心的就緒文件描述符
代碼
8. 寫SQL
table A
Id | Name |
---|---|
1 | abc |
2 | bcd |
table B
Id | Age |
---|---|
1 | 15 |
寫出id,name,age
select A.id, name,
(IF(B.age IS NULL, 0, B.age)) AS age
from A left outer join B
on A.id = B.id;
9. 拷貝帶有random和next指針的鏈表
Node copyList(Node head) {
Node p = head;
Map<Node, Node> map = new HashMap<>();
while (p != null) {
map.put(p, new Node(p.val));
p = p.next;
}
p = head;
Node out = map.get(p);
while (p != null) {
map.get(p).next = map.get(p.next);
map.get(p).random = map.get(p.random);
p = p.next;
}
return out;
}
10. 找到數組中每個元素右邊最大的第一個元素
public int[] getMax(int[] arr) {
int len = arr.length;
Map<Integer, Integer> map = new HashMap<>(len);
int[] out = new int[len];
out[len - 1] = -1;
map.put(out[len - 1], -1);
for (int i = len - 1; i >= 0; i ++) {
if (arr[i] < arr[i + 1]) {
out[i] = arr[i + 1];
} else {
int temp = map.get(arr[i + 1]);
whlie (temp != -1) {
if (temp > arr[i]) {
out[i] = temp;
break;
}
}
out[i] = -1;
}
map.put(arr[i], out[i]);
}
return out;
}
11. 計算1000億個32位正整數重複度top100個元素所需的空間複雜度
1000億 / 100 = 10億 ≈ 2^30;
2^32*30 = 120G
我回答的是120G,但是面試官說是64G