java常見疑難面試題及答案(阿里、螞蟻、百度、美團)(三)

21.mysql兩種引擎

MyISAM

1)不支持事務

2)不支持外鍵約束,只支持表鎖

3)非聚集索引,索引文件的數據域存儲指向數據文件的指針

4)支持全文索引

5)對於AUTO_INCREMENT類型的字段,可以和其他字段一起建立聯合索引

Innodb

1)支持事務

2)支持行級鎖和外鍵約束

3)主鍵索引採用聚集索引

4)不支持全文索引

22.什麼是B樹、B+樹?

B樹(B-樹)是一種多路搜索樹(不是二叉樹),搜索時相當於二分查找。每個節點既保存索引,又保存數據。查詢時間複雜度O(1)。

B+樹是B樹的變種,同樣是多路,搜索時相當於二分查找。只有葉子節點保存數據,增加了相鄰接點的指向指針(增加區間訪問性)。查詢時間複雜度是log(n)。

23.為什麼Mysql使用B+樹?

1)B+樹的磁盤讀寫代價更低,B+樹的內部節點並沒有指向關鍵字具體信息的指針。

2)B+樹的查詢效率更加穩定,由於非終結點並不是最終指向文件內容的結點,而只是葉子結點中關鍵字的索引。所以任何關鍵字的查找必須走一條從根結點到葉子結點的路。所有關鍵字查詢的路徑長度相同,導致每一個數據的查詢效率相當。

3)由於B+樹的數據都存儲在葉子結點中,分支結點均為索引。B+樹只需要遍歷葉子節點就可以實現整棵樹的遍歷,而B樹不支持這樣的操作或者說效率太低。在數據庫中基於範圍的查詢是非常頻繁的,所以通常B+樹用於數據庫索引。

24.如何設計一個高併發系統

1)系統拆分:拆分子系統,降低系統壓力,同時數據庫分開,減少數據壓力

2)緩存:讀多寫少的數據可以放在緩存中,減少數據庫壓力

3)MQ:異步處理後續業務,削峰、解耦合。

4)分庫分表:減少單表數據量,提高數據庫操作性能

5)讀寫分離:數據庫寫主讀從

6)ElasticSearch:一些比較簡單的查詢、統計、全文搜索的操作,可以考慮用 es 來承載

25.ArrayList,LinkedList的區別和使用場景

1)ArrayList是基於數組實現的,LinkedList是基於雙鏈表實現的

2)ArrayList搜索和讀取數據是很快的,可以直接返回數組中index位置的元素,但是要插入、刪除數據卻是開銷很大的(除非靠近末尾),需要移動數組中插入、刪除位置之後的的所有元素。

3)LinkedList的隨機訪問集合元素時性能較差,需要遍歷雙向鏈表,但是插入、刪除操作非常快。(靠近末尾查找時間長)

4)LinkedList需要更多的內存,因為ArrayList的每個索引的位置是實際的數據,而LinkedList中的每個節點中存儲的是實際的數據和前後節點的位置。

使用場景:

查詢較多用ArrayList,插入、刪除較多用LinkedList

26.加載器雙親委派模型及破壞

雙親委派是指特定的類加載器在接到加載類的請求時,首先將加載任務委託給父類加載器,如果父類加載器可以完成類加載任務,就成功返回。只有父類加載器無法完成此加載任務時,才去加載當前類。

可以避免重複加載,同時委派方式加載更加安全可靠

如果由各個類加載器自行加載的話,如果自己編寫了一個稱為java.lang.Object的類,那系統將會出現多個不同的Object類, Java類型體系中最基礎的行為就無法保證。

雙親委派破壞

第一次:

JDK1.2引入雙親委派模型的時候,由於類加載器和抽象類java.lang.ClassLoader則是JDK1.0時候就已經存在,為了向前兼容,java.lang.ClassLoader添加了一個新的proceted方法findClass()。可以把自己的類加載邏輯寫到findClass()方法中,在loadClass()方法的邏輯裡,如果父類加載器加載失敗,則會調用自己的findClass()方法來完成加載,這樣就可以保證新寫出來的類加載器是符合雙親委派模型的。

第二次:

雙親委派模型解決了各個類加載器的基礎類統一問題,但是如果基礎類又要調用用戶的代碼,卻無法實現。

因此在java設計團隊添加了線程上下文件類加載器(Thread Context ClassLoader)。這個類加載器可以通過java.lang.Thread類的setContextClassLoader()方法進行設置,如果創建線程時還未設置,它將會從父線程中繼承一個。如果在應用程序的全局範圍內都沒有設置過,那麼這個類加載器默認就是應用程序類加載器。有了線程上下文類加載器,可以通過使用這個線程上下文類加載器去加載所需要的代碼。Java中所有涉及SPI(Service Provider Interface,通過在ClassPath路徑下的META-INF/services文件夾查找文件,自動加載文件裡所定義的類)的加載動作基本上都採用這種方式,例如JNDI,JDBC,JCE,JAXB和JBI等。

第三次:

用戶對程序的動態性的追求導致的,例如OSGi(Open Service Gateway Initiative,以Java為技術平臺的動態模塊化規範)的出現。在OSGi環境下,類加載器不再是雙親委派模型中的樹狀結構,而是網狀結構。

27.跳錶怎麼實現的

跳錶是一種隨機化的數據結構,原有鏈表上添加多級索引,通過索引實現快速查找,每個元素插入時隨機生成它的level(防止索引節點下數據過多,跳錶退化成單鏈表),最低層包含所有的元素。遍歷鏈表的時候通過索引遍歷,減少遍歷次數。時間複雜度能做到 O(logn) ,但是數據結構所佔空間是2N。

目前開源軟件 Redis 和 LevelDB 都有用到它,效率和紅黑樹差不多(查找區間內所有元素效率比紅黑色略高

28.什麼是NginX,如何做負載均衡

Nginx是一個使用c語言開發的高性能http服務器,能夠支撐5萬併發鏈接,並且cpu、內存等資源消耗卻非常低,運行非常穩定。

1)反向代理:接受internet上的連接請求,然後將請求轉發給內部網絡上的服務器,並將從服務器上得到的結果返回給internet上請求連接的客戶端。

2)動靜分離:所有動態資源的請求交給應用服務器,靜態資源的請求(圖片、視頻、CSS、JavaScript文件等)則直接由Nginx返回到瀏覽器,這樣能大大減輕應用服務器的壓力

3)負載均衡:當用戶訪問網站時,選擇一臺壓力較小的服務器,然後將該訪問請求引入該服務器,保證服務器集群中的每個服務器壓力趨於平衡。負載均衡配置一般都需要同時配置反向代理,通過反向代理跳轉到負載均衡。

Nginx的負載均衡是通過upstream實現的

1)輪訓,請求按時間順序逐一分配到不同的後端服務器,如果後端某臺服務器宕機,故障系統被自動剔除。

upstream webname {

server 192.168.0.1:8080;

server 192.168.0.2:8080;

}

2)權重,權重和訪問比率成正比,用於後端服務器性能不均的情況。

upstream webname {

server 192.168.0.1:8080 weight 2;

server 192.168.0.2:8080 weight 1;

}

3)按後端服務器的響應時間來分配請求,響應時間短的優先分配。(需要下載Nginx的upstream_fair模塊)

upstream webname {

server 192.168.0.1:8080;

server 192.168.0.2:8080;

fair;

}

4)按訪問URL的hash結果來分配請求,使每個URL定向到同一個後端服務器。(需要安裝Nginx 的hash軟件包,且在upstream中加入hash語句後,server語句不能寫入weight等其他參數)

upstream webname {

ip_hash;

server 192.168.0.1:8080;

server 192.168.0.2:8080;

}

29.一致性哈希的一致性是什麼意思?

按照hash算法,將節點哈希到一個具有2的32次方個桶的環中。對數據進行哈希計算,按順時針方向將其映射到離其最近的節點上。(SortedMap::tailMap)

當有節點出現故障時,按照算法的映射方法,受影響的僅僅為環上故障節點開始逆時針方向至下一個節點之間區間的數據對象。當有節點出現變動時,將新增節點開始逆時針方向至下一個節點之間區間的數據重新映射,不會影響所有節點。

為了滿足平衡性引入了虛擬節點,虛擬節點是實際節點在 hash 空間的複製品,一個實際節點對應了若干個虛擬節點,虛擬節點在 hash 空間中以hash值排列。(虛擬節點的hash計算可以採用對應節點的IP地址加數字後綴的方式)

30.數據庫三大範式

一範式(1NF)

數據庫表每一項都是不可再分的項,所有的屬性都是單一的。

二範式(2NF)是建立在一範式的基礎上的,表中要有一列屬性可以將實體完全區分,這個屬性就是主鍵,即每一個屬性完全依賴於主鍵。非主屬性不能依賴於主鍵的部分屬性,必須依賴於主鍵的所有屬性。

三範式(3NF)是建立在二範式的基礎上的。一個數據表中不能包含已經在別的表中的非關鍵信息,屬性不依賴其他非主屬性。


分享到:


相關文章: