1. 程式人生 > >請拿出30分鐘鉆研此文,系統掌握java面試題分析技巧

請拿出30分鐘鉆研此文,系統掌握java面試題分析技巧

java 面試 架構師

談一談對MySQL InnoDB的認識

介紹:

InnoDB引擎是MySQL數據庫的一個重要的存儲引擎,和其他存儲引擎相比,InnoDB引擎的優點是支持兼容ACID的事務(類似於PostgreSQL),以及參數完整性(有外鍵)等。現在Innobase實行雙認證授權.MySQL5.5.5以後默認的存儲引擎都是InnoDB引擎。

技術分享圖片

特點是:

1、具有較好的事務支持:支持4個事務隔離級別,支持多版本讀

2、行級鎖定:通過索引實現,全表掃描仍然會是表鎖,註意間隙鎖的影響

3、讀寫阻塞與事務隔離級別相關

4、具有非常高效的緩存特性:能緩存索引,也能緩存數據

5、整個表和主鍵以Cluster方式存儲,組成一顆平衡樹

6、所有Secondary Index都會保存主鍵信息

適用場景:

1、需要事務支持(具有較好的事務特性)

2、行級鎖定對高並發有很好的適應能力,但需要確保查詢是通過索引完成

3、數據更新較為頻繁的場景

4、數據一致性要求較高

5、硬件設備內存較大,可以利用InnoDB較好的緩存能力來提高內存利用率,盡可能減少磁盤IO

MySQL主備同步的基本原理

MySQL支持單向、異步復制,復制過程中一個服務器充當主服務器,而一個或多個其它服務器充當從服務器。

MySQL復制是基於主服務器在二進制日誌中跟蹤所有對數據庫的更改。因此,要進行復制,必須在主服務器上啟用二進制日誌。每個從服務器從主服務器接收主服務器已經記錄到日誌的數據。

當一個從服務器連接主服務器時,它通知主服務器從服務器在日誌中讀取的最後一次成功更新的位置。從服務器接收從那時起發生的任何更新,並在本機上執行相同的更新。然後封鎖並等待主服務器通知新的更新。從服務器執行備份不會幹擾主服務器,在備份過程中主服務器可以繼續處理更新。

Java語言中一個顯著的特點就是引入了垃圾回收機制,這個大家都清楚,垃圾回收的概念這裏也不做介紹,重點是垃圾回收是在什麽時候開始?對什麽東西,做了什麽事情?

GC何時開始:

所有的回收器類型都是基於分代技術來實現的,那就必須要清楚對象按其生命周期是如何劃分的。

年輕代:劃分為三個區域:原始區(Eden)和兩個小的存活區(Survivor),兩個存活區按功能分為From和To。絕大多數的對象都在原始區分配,超過一個垃圾回收操作仍然存活的對象放到存活區。垃圾回收絕大部分發生在年輕代。

年老代:存儲年輕代中經過多個回收周期仍然存活的對象,對於一些大的內存分配,也可能直接分配到永久代。
持久代:存儲類、方法以及它們的描述信息,這裏基本不產生垃圾回收。
有了以上這些鋪墊之後開始回答GC何時開始:

Eden內存滿了之後,開始Minor GC(從年輕代空間回收內存被稱為 Minor GC);升到老年代的對象所需空間大於老年代剩余空間時開始Full GC(但也可能小於剩余空間時,被HandlePromotionFailure參數強制Full GC)

對什麽東西操作,即垃圾回收的對象是什麽:

從root開始搜索沒有可達對象,而且經過第一次標記、清理後,仍然沒有復活的對象。

做了什麽東西:

主要做了清理對象,整理內存的工作。具體的引申如下

垃圾回收器的類型:

Serial(串行GC)收集器

Serial收集器是一個新生代收集器,單線程執行,使用復制算法。它在進行垃圾收集時,必須暫停其他所有的工作線程(用戶線程)。是Jvm client模式下默認的新生代收集器。對於限定單個CPU的環境來說,Serial收集器由於沒有線程交互的開銷,專心做垃圾收集自然可以獲得最高的單線程收集效率。

ParNew(並行GC)收集器
如果想學習Java工程化、高性能及分布式、深入淺出。微服務、Spring,MyBatis,Netty源碼分析的朋友可以加我的Java進階群:582505643,群裏有阿裏大牛直播講解技術,以及Java大型互聯網技術的視頻免費分享給大家。

ParNew收集器其實就是serial收集器的多線程版本,除了使用多條線程進行垃圾收集之外,其余行為與Serial收集器一樣。

Parallel Scavenge(並行回收GC)收集器

Parallel Scavenge收集器也是一個新生代收集器,它也是使用復制算法的收集器,又是並行多線程收集器。parallel Scavenge收集器的特點是它的關註點與其他收集器不同,CMS等收集器的關註點是盡可能地縮短垃圾收集時用戶線程的停頓時間,而parallel Scavenge收集器的目標則是達到一個可控制的吞吐量。吞吐量= 程序運行時間/(程序運行時間 + 垃圾收集時間),虛擬機總共運行了100分鐘。其中垃圾收集花掉1分鐘,那吞吐量就是99%。

Serial Old(串行GC)收集器

Serial Old是Serial收集器的老年代版本,它同樣使用一個單線程執行收集,使用“標記-整理”算法。主要使用在Client模式下的虛擬機。

Parallel Old(並行GC)收集器

Parallel Old是Parallel Scavenge收集器的老年代版本,使用多線程和“標記-整理”算法。

CMS(並發GC)收集器

CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時間為目標的收集器。

CMS收集器是基於“標記-清除”算法實現的,整個收集過程大致分為4個步驟:

①.初始標記(CMS initial mark)

②.並發標記(CMS concurrenr mark)

③.重新標記(CMS remark)

④.並發清除(CMS concurrent sweep)

其中初始標記、重新標記這兩個步驟任然需要停頓其他用戶線程。初始標記僅僅只是標記出GC ROOTS能直接關聯到的對象,速度很快,並發標記階段是進行GC ROOTS 根搜索算法階段,會判定對象是否存活。而重新標記階段則是為了修正並發標記期間,因用戶程序繼續運行而導致標記產生變動的那一部分對象的標記記錄,這個階段的停頓時間會被初始標記階段稍長,但比並發標記階段要短。

由於整個過程中耗時最長的並發標記和並發清除過程中,收集器線程都可以與用戶線程一起工作,所以整體來說,CMS收集器的內存回收過程是與用戶線程一起並發執行的。

CMS收集器的優點:並發收集、低停頓,但是CMS還遠遠達不到完美,主要有三個顯著缺點:

1,CMS收集器對CPU資源非常敏感。在並發階段,雖然不會導致用戶線程停頓,但是會占用CPU資源而導致引用程序變慢,總吞吐量下降。CMS默認啟動的回收線程數是:(CPU數量+3) / 4。

2,CMS收集器無法處理浮動垃圾,可能出現“Concurrent Mode Failure“,失敗後而導致另一次Full GC的產生。由於CMS並發清理階段用戶線程還在運行,伴隨程序的運行自熱會有新的垃圾不斷產生,這一部分垃圾出現在標記過程之後,CMS無法在本次收集中處理它們,只好留待下一次GC時將其清理掉。這一部分垃圾稱為“浮動垃圾”。也是由於在垃圾收集階段用戶線程還需要運行,,即需要預留足夠的內存空間給用戶線程使用,因此CMS收集器不能像其他收集器那樣等到老年代幾乎完全被填滿了再進行收集,需要預留一部分內存空間提供並發收集時的程序運作使用。

在默認設置下,CMS收集器在老年代使用了68%的空間時就會被激活,也可以通過參數-XX:CMSInitiatingOccupancyFraction的值來提供觸發百分比,以降低內存回收次數提高性能。要是CMS運行期間預留的內存無法滿足程序其他線程需要,就會出現“Concurrent Mode Failure”失敗,這時候虛擬機將啟動後備預案:臨時啟用Serial Old收集器來重新進行老年代的垃圾收集,這樣停頓時間就很長了。

所以說參數-XX:CMSInitiatingOccupancyFraction設置的過高將會很容易導致“Concurrent Mode Failure”失敗,性能反而降低。

3,最後一個缺點,CMS是基於“標記-清除”算法實現的收集器,使用“標記-清除”算法收集後,會產生大量碎片。空間碎片太多時,將會給對象分配帶來很多麻煩,比如說大對象,內存空間找不到連續的空間來分配不得不提前觸發一次Full GC。為了解決這個問題,CMS收集器提供了一個-XX:UseCMSCompactAtFullCollection開關參數,用於在Full GC之後增加一個碎片整理過程,還可通過-XX:CMSFullGCBeforeCompaction參數設置執行多少次不壓縮的Full GC之後,跟著來一次碎片整理過程。
如果想學習Java工程化、高性能及分布式、深入淺出。微服務、Spring,MyBatis,Netty源碼分析的朋友可以加我的Java進階群:582505643,群裏有阿裏大牛直播講解技術,以及Java大型互聯網技術的視頻免費分享給大家。

垃圾回收算法:

技術分享圖片

引用計數法
標記清除法
復制算法
標記壓縮算法
分代算法
分區算法
類在虛擬機中的加載過程

加載Loading:

通過一個類的全限定名來獲取一個二進制字節流、將這個字節流所代表的靜態存儲結構轉化為方法區的運行時數據結構、在內存中生成一個代表這個類的java.lang.Class對象,作為方法區這個類的各種數據的訪問入口。

驗證Verification:

確保Class文件的字節流中包含的信息符合當前虛擬機的要求,並不會危害虛擬機的自身安全。

準備Preparation:

正式為類變量分配內存並設置類變量初始值。

解析Resolution:

虛擬機將常量池內的符號引用替換為直接引用的過程。

初始化Initialization:

類加載過程的最後一步,到了這個階段才真正開始執行類中定義的Java程序代碼。

使用Using:

根據你寫的程序代碼定義的行為執行。

卸載Unloading:

GC負責卸載,這部分一般不用討論。

說一下spring中Bean的作用域及生命周期

作用域

singleton:

Spring IoC容器中只會存在一個共享的Bean實例,無論有多少個Bean引用它,始終指向同一對象。Singleton作用域是Spring中的缺省作用域。

prototype:

每次通過Spring容器獲取prototype定義的bean時,容器都將創建一個新的Bean實例,每個Bean實例都有自己的屬性和狀態,而singleton全局只有一個對象。

request:

在一次Http請求中,容器會返回該Bean的同一實例。而對不同的Http請求則會產生新的Bean,而且該bean僅在當前Http Request內有效。

session:

在一次Http Session中,容器會返回該Bean的同一實例。而對不同的Session請求則會創建新的實例,該bean實例僅在當前Session內有效。

global Session:

在一個全局的Http Session中,容器會返回該Bean的同一個實例,僅在使用portlet context時有效。

生命周期

實例化一個Bean,也就是我們通常說的new。
按照Spring上下文對實例化的Bean進行配置,也就是IOC註入。
如果這個Bean實現了BeanNameAware接口,會調用它實現的setBeanName(String beanId)方法,此處傳遞的是Spring配置文件中Bean的ID。
如果這個Bean實現了BeanFactoryAware接口,會調用它實現的setBeanFactory(),傳遞的是Spring工廠本身(可以用這個方法獲取到其他Bean)。
如果這個Bean實現了ApplicationContextAware接口,會調用setApplicationContext(ApplicationContext)方法,傳入Spring上下文。
如果這個Bean關聯了BeanPostProcessor接口,將會調用postProcessBeforeInitialization(Object obj, String s)方法,BeanPostProcessor經常被用作是Bean內容的更改,並且由於這個是在Bean初始化結束時調用After方法,也可用於內存或緩存技術。
如果這個Bean在Spring配置文件中配置了init-method屬性會自動調用其配置的初始化方法。
如果這個Bean關聯了BeanPostProcessor接口,將會調用postAfterInitialization(Object obj, String s)方法。
當Bean不再需要時,會經過清理階段,如果Bean實現了DisposableBean接口,會調用其實現的destroy方法。
最後,如果這個Bean的Spring配置中配置了destroy-method屬性,會自動調用其配置的銷毀方法。

請拿出30分鐘鉆研此文,系統掌握java面試題分析技巧