一、面試崗位選擇
1.公司&團隊:
第一維度爲業務/團隊
小公司 | 大公司 | |
---|---|---|
核心業務/團隊 | 〇 | ✔ |
邊緣業務/團隊 | ✖ | 〇 |
2.崗位匹配度:
與自己發展方向越匹配越好
面試準備
面試準備決定面試成功與否
影響面試成敗三大基石:能力,面試,溝通
第一,優秀的技術基本功是必要條件,沒有技術能力其他的無從談起。
第二,注重平衡心態,過於緊張會導致平時會的內容都答不上來。
第三,與面試官順暢的溝通,開行的交流,能給你的面試加分,反之可能影響整個面試。
面試準備主要包括:
一、能力
1. 瞭解應試公司及其崗位
2. 系統化複習基礎知識
3. 對原公司負責的項目進行梳理總結
4. 學習典型框架案例
5. 閱讀常考考點源碼
6. 針對性準備加分項
二、心態
儘量收集應試公司崗位所屬團隊、平均福利等資料信息,知己知彼有助於增加信心。
面對壓力面試時,可進行自我暗示。如:
這個面試官我可能永遠不會遇到。
失敗了也並不可怕。
三、溝通
1. 提前準備一個簡短有特色的自我介紹,包括興趣特長、技術優勢
2. 避免冷場,回答不上來的問題可主動坦白,並提供應對或處理辦法,亦或是詢問面試官能否換一個問題。
3. 當沒有聽清或不理解問題時,不應強行作答,應與面試官溝通再次確認問題。
4. 面試細節。包括面部微表情、坐姿、手勢,說話語速不要過快或過慢,表達邏輯清晰觀點明確,不可隨意打斷面試官以及謙虛有禮的態度等。
ps.及時觀察面試官的反映。面試官奮筆疾書可能是你給與的信息有用,反之,長時間未有反應,應反思是否跑題。面試官表情不耐煩或深呼吸,可能意味着未能領會考察意圖,可以再次詢問。
面試考察點
面試考察點相對綜合,一般分爲兩大塊:
硬技能:
指基礎知識、項目經驗、架構能力、應用能力等
軟實力:
指邏輯思維、溝通協作、管理推進、學習思考、培養潛力等、
二、操作系統與網絡知識
- 知識點彙總
- 知識點詳解
- HTTP
- TCP
- 三次握手
- 四次揮手
知識點彙總
操作系統對於服務問題的排查定位很重要,在面試時,一般以瞭解和應用考察爲主,面試題目佔的比重不會過高.
線程共享同一進程資源
進程間的通信IPC,中間件研發相關職位。6鍾原理和使用場景。eg:進程間共享可以使用共享內存,進程間交換可以使用Unix socket或消息隊列。
協程更輕量化,是在用戶態進行,調度切換的代價比線程上下文切換要低很多。
服務之間通過不同的網絡協議進行交互,在面試中被考的機率非常大.
知識點詳解
HTTP
1. 需要知道協議中的Method,Header,Cookies.
2. 知道常見狀態碼含義404:未找到503:服務不可用302:臨時移動
3. 瞭解HTTPs的交互流程
4. QUIC基於UDP實現原HTTP功能,現已被標準化爲HTTP3協議,類似tcp的流量控制、可靠性保證
TCP
1. TCP和HTTP在服務交互中使用最多.瞭解報文標誌狀態和鏈接狀態有利於抓包分析.
2. Nagel和ACK 延遲算法是爲了解決小包問題和數據載荷比.對於延遲比較敏感且發送頻率比較低,可以關閉nagel
3. KeepALive是在長時間沒有數據發送的情況下保持連接可用的機制.需要了解開啓和設置方式.
4. 瞭解如何通過滑動窗口機制實現流量控制.
-
位於OSI模型的第四層-傳輸層
-
面向連接
- 每次發送數據先要建立連接
-
雙工通信
- 連接建立後可進行雙向通信
-
可靠
- 通過對數據包編號,並按序號接受,可確保數據的完整性和有序性
-
流量控制
- 通過滑動窗口控制數據的發送速率.滑動窗口的本質是動態緩衝區,接收端根據自己的處理能力,在tcp的Header中動態調整大小,通過ACK應答包通知發送端,進而調整發送速度
-
擁塞控制
- 主要通過慢啓動,擁塞避免,擁塞發生,快速恢復算法實現
-
基於字節流
將數據按字節大小進行編號,接收端通過AKC確認收到的數據編號,保證接收數據的有序性完整性
除了以上特點,還可以瞭解tcp協議的報文狀態,滑動窗口的工作流程,KeepAlive的參數設置,Nagel算法的細節
三次握手
tcp是基於鏈接的所以在傳輸數據前需要先建立鏈接(三次握手是爲了建立雙向的鏈接)
首先建立鏈接前需要server端先監聽端口,因此初始狀態就是listen狀態。client端準備建立鏈接,發送SYN同步包,之後client端的鏈接狀態就變成了SYN_SEND狀態.server端收到SYN後同意建立鏈接,會向client端回覆一個ACK.由於tcp是雙工傳輸server端也會同時向client端發送一個同步請求SYN.client端收到後變爲established狀態,同時client端向server端發送ACK響應回覆,收到後server端的鏈接狀態也就變成了established的狀態。此時建聯完成雙方隨時可以進行數據傳輸。
回答建連的問題時,可以提到syn洪水攻擊.即請求端只發送SYN包,而不對接收端的SYNACK包進行回覆,使得接收端大量連接處於半連接狀態,影響其他正常請求的建連.
解決方法:設置linux的tcp參數
tcp_synack_retries=0,加快對於半連接的回收速度,或加大tcp_max_syn_backlog應對少量的syn洪水攻擊
四次揮手
關閉通信雙方都可以先發起,首先鏈接狀態都是established狀態。然後可client端先發起了關閉鏈接請求,向server發送了一個FIN包表示client端已經沒有數據要發送。然後client端就進入了FIN_WAIT_1狀態。server端收到FIN後返回ACK然後進入close_wait狀態。此時server屬於半關閉狀態,因爲此時client不會向server發送數據,server有可能向client端發送數據。當server端數據發送完畢,向client端發送FIN,進入LAST_ACK狀態,等待應答就可以關閉鏈接了。client端收到server端的FIN後,回覆ACK然後進入time_wait狀態(等待兩倍的msl,即最大報文段生存時間來保證鏈接的可靠關閉)之後纔會進入close狀態。而server端收到ACK後直接就可以進入close狀態。
爲什麼需要4次:兩端並不是同時都不需要發送數據了
處於CLOSE_WAIT狀態時,HOSTB仍有可能向HOSTA發送數據,HOSTB發送完數據後,纔會向HOSTA發送FIN包
發送關閉連接請求,表示沒有數據需要發送,進入wait1,進入last_ACK等待應答,之後就可以closed,
爲何HOSTA要在2MSL(Maximum Segment Lifetime 最大報文生存時長)後才關閉連接?
- 要保證TCP的全雙工連接能可靠關閉
- 要保證這次連接中重複的數據段從網絡中消失,防止端口重用時可能的數據混淆
回答問題是也可以提到,有可能大量socket會處於TIME_WAIT和CLOSE_WAIT的問題.
解決TIME_WAIT過多,可通過開啓Linux的tcp參數tw_reuse或tw_recycle能加快TIME_WAIT狀態的回收.
CLOSE_WAIT過多則可能是被動關閉的一方存在代碼BUG,沒有正確關閉連接導致的
三、設計模式與Java語言特性
- 知識點彙總
- 知識點詳解
- 常用設計模式
- 單例模式
- 工廠模式
- 代理模式
- 責任鏈模式
- 適配器模式
- 觀察者模式
- 構造者模式
- Java語言特性
- Java基礎常考點–Map
- HashMap
- ConcurrentHashMap
- Java版本特性
- 1.8
- 1.9-1.10
- 1.11
- 面試考察點
- 加分項
- 真題彙總
知識點彙總
該內容需掌握主要兩點
- 常用設計模式的實現
- 各設計模式的使用場景
常見集合類和Java併發工具包(JUC)是常見考點
知識點詳解
常用設計模式
有**單例模式,工廠模式,代理模式,觀察者模式,**構造者模式,責任鏈模式,適配器模式等.
在回答設計模式問題時,可結合實際業務場景,體現對設計模式的理解和應用能力.
單例模式
線程安全實現的常見三種方法:
1. 靜態初始化(餓漢).不管是否使用都會創建
2. 雙檢鎖(懶漢).單例變量必須要用volatile修飾.
3. 單例註冊表.spring中bean的單例模式就是用該方法實現.
工廠模式
在實際業務中經常用到,也是面試的主要考察點.是創建不同類型實例常用的方式.
spring中的bean都是由不同工廠類創建的.
代理模式
在不適合或不能直接引用另一個對象的場景,可以用代理模式對被代理的對象進行訪問行爲的控制.Java的代理模式分爲靜態代理和動態代理,靜態代理是指在編譯時就創建好的代理類,例如在源代碼中編寫的類.動態代理指在JVM運行過程中動態創建的代理類,如JDK動態代理,CDLIB,javaasist等.
例如,在Mybatis中getMapper時會通過MapperProxyFactory及配置文件動態生成的Mapper代理對象,代理對象會攔截Mapper接口的方法調用,創建對應方法的MapperMethod類並執行exe cute方法,然後返回結果.
責任鏈模式
類似工廠流水線,其中的每個節點完成對對象的某一種處理.
Netty框架的處理消息的Pipeline就是採用的責任鏈模式.
適配器模式
類似於轉接頭,將兩種不匹配的對象進行適配,也可以起到對兩個不同的對象進行解耦的作用.
SLF4J可使項目與Log4、logback等具體日誌實現框架進行解耦,其通過不同適配器與不同框架進行適配,完成日誌功能的使用.
觀察者模式
也可稱爲發佈訂閱模式,適用於一個對象某個行爲需要觸發一系列操作的場景.
GRPC中stream流式請求的處理.
構造者模式
適用於一個對象擁有很多複雜的屬性,需要根據不同情況創建不同的具體對象.
創建Protocol Buffer對象時,需要用到Builder
Java語言特性
-
集合類
主要掌握如何實現. -
動態代理與反射
是java語言的特色,需要掌握動態代理與反射的使用場景.ORM框架中會大量使用代理類,PRC調用時使用反射機制調用實現類的方法.
-
數據類型
也是面試的常見問題.如每種數據類型佔用多大空間,數據類型的自動轉換與強制轉換,基礎數據類型與Wrapper數據類型的自動裝箱與拆箱等. -
對象引用
(可自行搜索)
Java基礎常考點–Map
能考查到數據結構,java的基礎實現以及對併發問題的處理思路的掌握程度.
HashMap
-
通過數組加鏈表實現.
數組中的元素爲一個鏈表,通過計算存入對象的hashcode,確認存入位置,用鏈表解決散列衝突.鏈表的節點存入的是鍵值對.
-
填充因子的作用???
-
Map擴容的rehash機制
-
容量是二的冪次方.
是爲了方便按位與操作計算餘數,比求模更快
-
多線程風險的原因
對線程put時,會在超過填充因子的情況下rehash.HashMap爲避免尾部遍歷,鏈表插入採用頭插法,多線程場景下可能產生死循環.
ConcurrentHashMap
-
分段鎖思想
1.7中採用segment分段加鎖,降低併發鎖定程度.
-
CAS自旋鎖
1.8中採用CAS自旋鎖(一種樂觀鎖實現模式)提高性能.但在併發度較高時,性能一般.
-
紅黑樹
1.8引入紅黑樹解決hash衝突時的鏈表查找問題.在鏈表長度大於8且總容量大於64時啓用.擴容後鏈表長度小於6時重新轉爲一般鏈表.(8,6,64爲默認參數)
Java版本特性
1.8:長期支持版本
* Lambda表達式:簡潔並行計算
* StreamAPI
* 方法引用
* 接口默認方法:簡化掉簡單的抽象類
* Metaspace替換PremGen
M使用本地內存,不在虛擬機中,目的提升對原數據的處理,提成GC效率;以後hotSport與Jrocket合併
1.9-1.10
* 模塊系統
* 默認G1回收器
* 接口私有方法
* 局部變量判斷
* Graal編譯器
1.11:長期支持版本
* ZGC:新的垃圾回收器,大堆內存設計
* 字符串API增強
* 內建HTTP Client
面試考察點
-
基本概念和基本原理
要求:正確清晰* 網絡協議4/7層模型的概念 * TCP協議流量控制的實現原理
-
實現方法和使用方式
* HashMap在JDK1.8中的實現方式 * 單例模式有哪幾種實現方式,什麼場景該使用靜態方法實現,什麼場景該使用雙檢鎖實現
-
經常用到的知識點
* 常用的Linux命令有哪些,用來解決什麼樣的問題
-
實際應用中容易犯錯的點
* ==與equals區別是什麼 * 對象強引用使用不當會導致內存泄露,考察不同引用方式和作用的理解
-
與面試方向相關的知識點
* 中間件:存儲,網絡相關的考察
加分項
-
知識點與典型的業務場景關聯.
如,談到設計模型時,可以講XX框架在解決XX問題時使用了那種設計模式.
-
以反例來描述實際場景中誤用的危害.
如,大量使用反射會影響性能.
-
與知識點相關的優化點.
如,講到tcp建連和斷連時,如遇到洪水攻擊或大量TIME_WAIT時,可以調整系統參數預防.
-
與知識點相關的最新技術趨勢.
如,講到ConcurrentHashMap,可以介紹1.8的改進細節. 或,講到HTTP時,能說出HTTP2和QUIC的特點和實現.
-
在瞭解的前提下,儘量增加回答內容深度.
如,講到tcp的滑動窗口時,能講到流量與擁塞控制,進一步能指出解決擁塞的不同算法.
ps.面試官可能會順着細節追問,回答不上來會適得其反.
真題彙總
-
進程和線程的區別和聯繫
從資源佔用,切換效率,通信方式等方面解答
-
簡單介紹一下進程的切換過程
線程上下文的切換代價,要回答,切換會保存寄存器,棧等線程相關的現場,需要由用戶態切換到內核態,可以用vmstat命令查看線程上下文的切換狀況
-
你經常使用哪些Linux命令,主要用來解決哪些問題?
參考之前操作系統彙總中提到的命令
-
爲什麼TCP建連需要3次握手而斷連需要4次?
參考之前內容
-
爲什麼TCP關閉鏈接時需要TIME_WAIT狀態,爲什麼要等2MSL?
參考之前內容
-
一次完整的HTTP請求過程是怎樣的?
DNS解析,TCP建連,HTTP請求,HTTP響應等.
-
HTTP2和HTTP的區別有哪些?
-
在你的項目中你使用過那些設計模式?主要用來解決哪些問題?
-
Object中的equals和hashcode的作用分別是什麼?
-
final,finally,finalize的區別與使用場景
-
簡單表述一下Java的異常機制
-
先上使用的那個版本jdk,爲什麼使用這個版本(有什麼特色)?
四、JVM
- 知識點彙總
- 知識點詳解
- JVM內存模型
- 棧
- 本地方法棧
- 程序計數器
- 堆
- 方法區
- JMM與內存可見性
- 類加載與卸載
- 加載過程
- 加載機制-雙親委派模式
- 分代回收
- 回收算法
- 考察點
- 加分項
- 真題彙總
知識點彙總
JVM是Java運行基礎,面試時一定會遇到JVM的有關問題,內容相對集中,但對只是深度要求較高.
其中內存模型,類加載機制,GC是重點方面.性能調優部分更偏向應用,重點突出實踐能力.編譯器優化和執行模式部分偏向於理論基礎,重點掌握知識點.
需瞭解
內存模型
各部分作用,保存哪些數據.
類加載
雙親委派加載機制,常用加載器分別加載哪種類型的類.
GC
分代回收的思想和依據以及不同垃圾回收算法的回收思路和適合場景.
性能調優
常有JVM優化參數作用,參數調優的依據,常用的JVM分析工具能分析哪些問題以及使用方法.
執行模式
解釋/編譯/混合模式的優缺點,Java7提供的分層編譯技術,JIT即時編譯技術,OSR棧上替換,C1/C2編譯器針對的場景,C2針對的是server模式,優化更激進.新技術方面Java10的graal編譯器
編譯器優化
javac的編譯過程,ast抽象語法樹,編譯器優化和運行器優化.
知識點詳解
JVM內存模型(Java虛擬機內存模型)
線程獨佔:棧,本地方法棧,程序計數器
線程共享:堆,方法區
棧
又稱方法棧,線程私有的,線程執行方法是都會創建一個棧陣,用來存儲局部變量表,操作棧,動態鏈接,方法出口等信息.調用方法時執行入棧,方法返回式執行出棧.
本地方法棧
與棧類似,也是用來保存執行方法的信息.執行Java方法是使用棧,執行Native方法時使用本地方法棧.
程序計數器
保存着當前線程執行的字節碼位置,每個線程工作時都有獨立的計數器,只爲執行Java方法服務,執行Native方法時,程序計數器爲空.
堆
JVM內存管理最大的一塊,對所有線程共享,目的是存放對象的實例,幾乎所欲的對象實例都會放在這裏,當堆沒有可用空間時,會拋出OOM異常.根據對象的存活週期不同,JVM把對象進行分代管理,由垃圾回收器進行垃圾的回收管理
方法區
又稱非堆區,用於存儲已被虛擬機加載的類信息,常量,靜態變量,即時編譯器優化後的代碼等數據.1.7的永久代和1.8的元空間都是方法區的一種實現
回答以上問題是需回答兩個要點:
- 各部分功能
- 是否是線程共享
JMM與內存可見性
[外鏈圖片轉存失敗(img-iomYGzAw-1565101632758)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555596294412.png)]
JMM是定義程序中變量的訪問規則。所有共享變量都存在主內存中共享,每個線程有自己的工作內存,保存的是主內存中變量的工作副本。線程對於變量的讀寫等操作只能在自己的工作內存中進行,而不能直接對主內存操作。只有從A的工作內存區寫回到主內存,B從主內存區讀取到自己的工作內存區,才能進一步的操作。由於指令重排序,讀寫的順序會被打亂,因此JMM需要提供原子性,可見性,有序性保證.
[外鏈圖片轉存失敗(img-3Zyimc80-1565101632759)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1554779864119.png)]
volatile強制變量的賦值會同步刷新回主內存,強制變量的讀取會從主內存中重新加載,保證不同的線程總是能夠看到該變量的最新值。
volatile另一個作用就是阻止指令重排續這樣就可以保證變量讀寫的有序性。
happens before 原則包括一系列規則比如
- 程序順序原則:就是一個線程內必須保證語義串行性
- 鎖規則就是對同把鎖的解鎖一定要發生在再次加鎖之前
- 此外還包括happens-before原則的傳遞性
- 線程的啓動中斷中止規則等
類加載與卸載
class字節碼讀入到內存,放到方法區內,並創建對應的class對象
加載過程:加載-鏈接(驗證,準備,解析)-初始化
[外鏈圖片轉存失敗(img-ZaeMvGXg-1565101632760)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1554779890785.png)]
-
加載通過類的完全限定名,查找此類字節碼文件,利用字節碼文件創建Class對象.
-
驗證確保Class文件符合當前虛擬機的要求,不會危害到虛擬機自身安全.
-
準備進行內存分配,爲static修飾的類變量分配內存,並設置初始值(0或null).
不包含final修飾的靜態變量,因爲final變量在編譯時分配.
-
解析將常量池中的符號引用替換爲直接引用的過程.直接引用爲直接指向目標的指針或者相對偏移量等.
-
初始化主要完成靜態塊執行以及靜態變量的賦值.先初始化父類,再初始化當前類.
只有對類主動使用時纔會初始化,觸發條件包括,創建類的實例時,訪問類的靜態方法或靜態變量的時候,使用Class.forName反射類的時候,或者某個子類初始化的時候.
JVM自帶的3種類加載器加載的類,在虛擬機的生命週期中是不會被卸載的,只有用戶自定義的加載器加載的類纔可被卸載
加載機制-雙親委派模式
[外鏈圖片轉存失敗(img-MlCj4Pi9-1565101632761)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555596268040.png)]
雙親委派模式,即加載器加載類時先把請求委託給自己的父類加載器執行,直到頂層的啓動類加載器.父類加載器能夠完成加載則成功返回,不能則子類加載器才自己嘗試加載.
優點:
- 避免類的重複加載
- 避免Java的核心API被篡改
分代回收:方便垃圾回收
分代回收基於兩個事實:大部分對象很快就不使用了,還有一部分不會立即無用,但也不會持續很長時間.
堆分代 | |||
---|---|---|---|
年輕代 | Dden | Survivor1 | Survivor2 |
老年代 | Tenured | Tenured | Tenured |
永久代 | PremGen/MetaSpace | PremGen/MetaSpace | PremGen/MetaSpace |
- 年輕代主要用來存放新創建的對象,分爲Eden區和兩個survivor區,大部分對象在Eden區生成,當Eden區滿時,還存活的對象會在兩個surval區交替保存,達到定次數後對象會晉升到老年代。
- 老年代用來存放從年輕代晉升而來的存活時間較長的對象。
- 永久帶主要保存類信息等內容。這裏的永久代是指對象劃分方式不是專指1.7的PremGen或者1 8之後的MetaSpace。
垃圾回收算法:根據年輕代與老年代的特點JVM提供了不同的垃圾回收算法。
- 引用計數法:對象被引用的次數確定對象是否再被使用,缺點是無法解決循環引用的問題
- 標記複製算法:需要from和to兩塊大小相同的內存空間,對象分配時只在from塊進行,回收時把存活對象複製到to塊,並清空from塊。然後交換兩塊的分工,from變爲to。缺點是內存使用率低。
- 標記清除法:分爲標記對象和清除不再使用的對象兩個階段。缺點是會產生內存碎片。
年輕代->標記-複製:
老年代->標記-清除:CMS、G1、ZGC
回收算法
1.CMS算法
1.7前主流垃圾回收算法,爲標記-清楚算法,優點是併發收集,停頓小.
[外鏈圖片轉存失敗(img-0bQHOg5m-1565101632761)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555643016840.png)]
初始標記
會StopTheWorld,標記的對象是root即最直接可達的對象.併發標記
GC線程和應用線程併發執行,標記可達的對象.重新標記
第二個StopTheWorld,停頓時間比併發標記
小很多,但比初始標記
稍長.主要對對象重新掃描並標記.併發清理
進行併發的垃圾清理.併發重置
爲下一次GC重置相關數據結構.
2.G1算法
1.9後默認的垃圾回收算法,特點保持高回收率的同時減少停頓.採用每次只清理一部分,而不是清理全部的增量式清理,以保證停頓時間不會過長
[外鏈圖片轉存失敗(img-3ByOThvl-1565101632761)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555643173106.png)]
其取消了年輕代與老年代的物理劃分(改爲了邏輯分代),但仍屬於分代收集器,算法將堆分爲若干個邏輯區域(region),一部分用作年輕代,一部分用作老年代,還有用來存儲巨型對象的分區.
同CMS相同,會遍歷所有對象,標記引用情況,清除對象後會對區域進行復制移動,以整合碎片空間.
- 年輕代回收:
並行複製
採用複製算法,並行收集,會StopTheWorld. - 老年代回收:
會對年輕代一併回收
初始標記
完成堆root對象的標記,會StopTheWorld.
併發標記
GC線程和應用線程併發執行.
最終標記
完成三色標記週期,會StopTheWorld.
複製/清楚
會優先對可回收空間較大的區域進行回收(garbage first)
只清理一部分的增量式清理,保證每次清理停頓時間不會過長
可以通過JVM算法設置region的大小,1-32m,還可以設置最大GC停頓時間
CMS、G1三色標記算法
3.ZGC
1.11中提供的高效垃圾回收算法,針對大堆內存設計,可以處理TB級別的堆,可以做到10ms以下的回收停頓時間.
特點:
- 着色指針:最大4TB堆(尋址需要42位),剩下22位保存額外信息,對象進行着色標記
- 讀屏障:GC線程和應用線程可能併發修改對象狀態的問題,而非簡單的STW,只有單個對象處理有概率減速
- 併發處理:讀屏障,大部分不需要STW
- 基於region:並未進行分代,動態決定大小(G1固定大小),動態創建銷燬,更好的管理大對象
- 內存壓縮(整理):CMS原地清理,內存碎片。ZGC同G1清理後移動合併,解決碎片問題。
[外鏈圖片轉存失敗(img-QCdDYj8O-1565101632762)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555643934423.png)]
初始劃分爲許多小大不用的region
- roots標記`標記root對象,會StopTheWorld.
併發標記
對對象指針進行着色進行標記。結合讀屏障(解決單個對象的併發問題)與應用線程一起運行標記,最後可能會有StopTheWorld用來處理邊緣部分.清除
會清理標記爲不可用的對象.roots重定位
是對存活的對象進行移動,以騰出大塊內存空間,減少碎片產生.重定位最開始會短暫StopTheWorld(時間取決於root數量,和重定位集與對象總活動集的比例),用來重定義集合中的root對象併發重定位
與併發標記
類似.
考察點
-
深入理解JVM內存模型、JMM
-
瞭解類加載過程,雙親委派機制
-
瞭解內存可見性,JMM保證的幾個機制
-
瞭解常用的GC算法特點、執行過程和適用場景
eg:G1對最大延遲有要求的場合,ZGC 64位系統的大內存服務中
-
能夠根據業務場景選擇合適JVM參數和GC算法
eg:垃圾回收的併發數,偏向鎖的設置
加分項
-
編譯器優化
利用棧上分配,降低GC壓力
編寫適合內聯優化的代碼
-
問題排查經驗與思路
解決過線上經FULL GC 的問題
排查過內存泄露的問題
-
JVM調優經驗和調優思路
高併發低延遲的場景,如何調整GC參數,降低停頓時間
針對隊列處理機,如何儘可能提高吞吐力
-
瞭解最新的技術趨勢(ZGC高效的實現原理和Graalvm實現特點)
真題彙總
-
簡單描述一下JVM的內存模型
-
什麼時候會觸發FullGC?
年輕帶晉升時,老年代空間不足
永久代空間不足
-
Java類加載器有幾種,關係怎樣的?
-
雙請問歐派機制的加載流程是譖言的,有什麼好處?
-
1.8爲首麼用Metaspace替換掉PermGen?Meatspace保存在哪?
-
編譯器會對指令做哪些優化?(簡答描述編譯器的指令重排)
-
簡單描述一下volatile可以解決什麼問題?如何做到的?
強制主內存讀寫同步,防止指令重排序
-
簡單描述一下GC的分代回收?
-
G1與CMS的區別?
-
對象引用有哪幾種,有什麼特點?
強引用,不會被GC
軟引用,內存空間不足時GC
弱引用,每次GC都回收
虛引用,和引用隊列聯合使用,跟蹤一個對象被垃圾回收的過程
-
使用過哪些JVM調試工具,主要分析哪些內容?
GMC飛行計數器、堆分析工具MAT、線程分析工具JStack、獲取堆信息JMap
五、併發與多線程
- 知識點彙總
- 知識點詳解
- 線程的狀態轉換
- CAS與ABA問題
- Synchronized實現原理
- AQS與Lock
- 線程池
- 線程池參數介紹
- 考察點
- 加分項
- 真題彙總
知識點彙總
知識點詳解
線程的狀態轉換
[外鏈圖片轉存失敗(img-IFmDuGv2-1565101632762)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555645391502.png)]
六個狀態對應ThreadState的枚舉
CAS與ABA問題
**CAS:**一種樂觀鎖的實現,輕量級鎖,JUC很多工具類基於CAS
[外鏈圖片轉存失敗(img-j3JGycmH-1565101632763)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555646955807.png)]
線程在讀取數據時不進行加鎖,準備寫回數據時,比較原值是否修改,若未被其它線程修改則寫回,若已被修改則重新執行讀取流程。
樂觀策略,認爲併發操作並不總會發生。比較並寫回採用操作系統中的原語,保證不會被中斷。
**ABA問題:**不一定會影響結果,但還是需要防範:增加額外的標位或者時間戳,JUC中有。
[外鏈圖片轉存失敗(img-CddBv4tA-1565101632763)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1554780070499.png)]
Synchronized實現原理
[外鏈圖片轉存失敗(img-YyPAZ022-1565101632764)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555647304472.png)]
保證同一時刻只有一個線程進入臨界區:
對對象進行加鎖,對象在內存中分爲三塊區域(對象頭、實例數據、對其填充),對象頭中,保存了鎖標誌位和指向Monitor對象的起始地址。Monitor被某個線程佔用後,就會處於鎖定狀態,Owner指向持有Moniator對象的線程,兩個隊列,存放進入以及等待獲取鎖的線程。
鎖優化
先使用偏向鎖,優先同一線程再次獲取鎖。鎖優化會將鎖由輕量級升級爲重量級
AQS與Lock
[外鏈圖片轉存失敗(img-s0hGoVgM-1565101632764)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555647844234.png)]
AQS隊列同步器,實現Lock的基礎。state標誌位,1有線程佔用,其他需要進入同步隊列等待。同步隊列是一個雙向鏈表,當獲得鎖的線程需要等待某個條件時,需要進入等待隊列。可以有多個,當條件滿足時,可以重進入同步隊列,進行獲取鎖的競爭。
Re entrant Lock:基於AQS。有公平鎖,非公平鎖,差別在於新來的線程有沒有可能比已經等待的更早獲得鎖。獨佔鎖。Semaphore,共享鎖。
線程池
複用線程,避免線程頻繁的創建與銷燬。
- NewFixedThreadPool 固定大小線城池,固定線程數,無界隊列.適用於任務數量不均勻的場景,對內存壓力不敏感,但系統負載敏感的場景.
- NewCachedThreadPool cached線程池,無限線程數,適用於要求低延遲的短期任務場景.
- newSingleThreadPool 單個線程的固定線程池,適用於保證異步執行順序的場景.
- newScheduledThreadPool Scheduled線城池,適用於定期執行任務場景,支持固定頻率和固定延遲.
- newWorkStealingPool 工作竊取線程池,使用ForkJoinPool,多任務隊列的固定並行度,適合任務執行時長不均勻的場景.
線程池參數介紹
線程池構造方法:除newWorkStealingPool
ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepaAliveTime,TimeUnit timeUnit,BlockQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExceptionHandler rejectedHandler) //ThreadPoolExecutor構造方法
corePoolSize
核心線程數,也可理解爲最小線程數
maximumPoolSize
最大線程數
keepaAliveTime
非核心線程非活躍存活時間長度,線程閒置超過空閒時間時,被銷燬
timeUnit
存活時間單位,枚舉等
可以通過allowedCoreThreadTimeout方法允許核心線程被回收
workQueue
緩衝隊列,
ArrayBlockingQueue(capacity):有界隊列,隊列有最大限制
LinkedBlockingQueue:無界隊列,隊列不限制容量
SynchronousQueue:同步隊列,內部沒有緩衝區
threadFactory
設置線程池工廠方法,可用來對線程的一些屬性定製,一般使用默認即可,線程名,優先級等
rejectedHandler
線程池滿時拒絕策略,
Abort:默認,滿時,提交新任務會拋出異常
Discard:提交失敗時,對任務直接丟棄
CallerRuns:提交失敗時,由提交任務的線程直接執行提交任務
DiscardOldest:丟棄最早提交的任務
每種線程具體創建方法
- NewFixedThreadPool 固定大小線城池,核心、最大線程數指定的,無界隊列LinkedBlockingQueue
- NewCachedThreadPool cached線程池,核心線程數0,最大整數Int的最大值,SynchronousQueue,只要沒有空閒的線程,就會新建。
- newSingleThreadPool 單個線程的固定線程池,線程數設置爲1
- newScheduledThreadPool Scheduled線城池,DelayedQueue按延遲時間獲取任務的優先級隊列
線程池任務執行流程
提交任務execute,submit(可以返回一個對象,瞭解任務的執行情況 ,可以取消任務的執行,獲取執行結果,執行異常,最終也是通過execute執行的)
[外鏈圖片轉存失敗(img-9QI1gaTg-1565101632764)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555649924146.png)]
先判斷最大線程數
JUC常用工具
第一格,基本數據類型的原子類。
unsafe類:底層工具類,提供了類似C的指針操作,提供CAS功能,所有方法都是native
Semaphore:允許多個線程共享資源,適用限制使用共享資源,100個車,20個車位,最多20個有車位
寫飢餓:多線程讀寫時,讀線程訪問非常頻繁,導致總是有讀線程佔用資源,寫線程很難加上寫鎖。
CompletableFuture:可以同時執行兩個異步任務,然後對執行結果進行合併處理
ForkJoinPool:分治思想+工作竊取(有效平衡任務執行時間長短不一的場景)
考察點
-
理解線程的同步與互斥原理
臨界資源與臨界區的概念 重量級鎖,輕量級鎖,自旋鎖,偏向鎖,讀寫鎖,重入鎖的概念
-
掌握線程安全相關機制
CAS,synchronized,lock同步方式的實現原理 ThreadLocal是線程獨享的局部變量,使用弱引用的ThreadLocalMap保存ThreadLocal變量
-
瞭解JUC工具的使用場景與實現原理
ReentrantLock,ConcurrentHash,LongAdder的實現方式
-
熟悉線程池的原理,使用場景,常用配置
大量短期的任務,適合使用Cached;系統資源緊張,固定線程池; 慎用無界隊列,可能會有OOM的風險
-
理解線程的同步與異步,阻塞與非阻塞
同步異步:任務是否在同一個線程中執行 阻塞非阻塞:異步執行任務時,線程是否會阻塞等待結果,還是會繼續執行後面的邏輯
加分項
-
結合實際項目經驗或實際案例介紹原理
eg:項目中有一個需要高吞吐量的場景,使用了Cache的線程池
-
解決多線程問題的排查思路與經驗
-
熟悉常用的線程分析工具與方法
如Jstack分析線程的運行狀態,查找鎖對象的持有狀況
-
瞭解Java8對JUC的增強
用LongAdder替換AtomicLong,更適合併發度高的場景
-
瞭解Reactive異步編程思想,被壓的概念與應用場景
真題彙總
-
如何實現生產者消費者模型?
可利用鎖,信號量,線程通信,阻塞隊列等方法實現
-
如何理解線程的同步與異步,阻塞與非阻塞?
-
線程池處理任務的流程?
-
wait與sleep有什麼不同?
wait是Object方法,sleep是Thread方法 wait會釋放鎖,sleep不會 wait要在同步塊中使用,sleep在任何地方使用 wait不需要捕獲異常,sleep需要
-
Synchronized與ReentrantLock有什麼不同,各適用什麼場景?
-
讀寫鎖適用與什麼場景,ReentrantReadWriteLock是如何實現的?
讀寫鎖:適合讀併發多,寫併發少的場景,另外一個可以的是CopyOnWrite
-
線程之間如何通信?
wait/notify機制 共享變量的synchronize&lock同步機制
-
保證線程安全的方法有哪些?
CAS,synchronized,lock,ThreadLocal
-
如何儘可能提高多線程併發性能?
減少臨界區範圍 使用ThreadLocal 減少線程切換 使用讀寫鎖或CopyOnWrite
-
ThreadLocal用來解決什麼問題,ThreadLocal是如何實現的?
不是用來解決多線程共享變量問題,而是用來解決線程數據隔離問題
-
死鎖的產生條件,如何分析線程是否有死鎖?
-
在實際工作中遇到過什麼樣的併發問題,如何發現排查並解決的?
六、數據結構與算法
- 知識點彙總
- 知識點詳解
- 數據結構
- 樹
- 二叉搜索樹
- 平衡二叉樹
- 紅黑樹
- B樹
- B+樹
- 算法
- 字符串匹配問題
- TopK問題
- 找出N個數中最小的k個數(N非常大)
- 從N有序隊列中找到最小的K個值
- 常用算法介紹
- 面試考察點
- 加分項
- 真題彙總
知識點彙總
知識點詳解
數據結構
樹
二叉搜索樹
每個節點都包含一個值,每個節點至多有兩棵子樹,左孩子小於自己,右孩子大於自己,時間複雜度是O(log(n)),隨着不斷插入節點,二叉樹樹高變大,當只有左(右)孩子時,時間複雜度變爲O(n).
平衡二叉樹
保證每個節點左右子樹高度差絕對值不超過1.
比如,AVL樹在插入和刪除數據是經常需要旋轉以保持平衡.適合插入刪除少場景.
紅黑樹
非嚴格平衡二叉樹,更關注局部平衡,而非總體平衡,沒有一條路徑比其他路徑長出兩倍,接近平衡,減少了許多不必要的旋轉操作,更加實用.
特點:
- 每個節點不是紅就是黑
- 根節點是黑色
- 每個葉子都是黑色空節點
- 紅色節點的子節點都是黑的
- 任意節點到其葉節點的每條路徑上存在的黑色節點數量相同.
B樹
適用於文件索引,優先減少磁盤IO次數,最大子節點稱爲B樹的階
關鍵字分佈在整棵樹中,一個關鍵字只出現在一個節點中,搜索可能在非葉節點停止
m階b樹特點:
- 非葉子節點最多有m棵子樹
- 根節點最少有兩棵子樹
- 非根非葉節點最少有m/2棵子樹
- 非子葉節點保存的關鍵字個數,爲該節點子樹個數減一,有三個子樹,必定包含兩個關鍵字
- 非葉子節點的關鍵字大小有序,eg 37 51
- 關鍵字的左孩子都小於該關鍵字,右孩子都大於關鍵字
- 所有葉節點都在同一層
- 採用二分查找法
B+樹
定義與b樹基本相同,
區別:
- 節點有多少關鍵字,有多少子樹
- 關鍵字對應子樹的節點都大於等於關鍵字,子樹中包括關鍵字自身
- 所有關鍵字都出現在葉節點中
- 所有葉節點都有指向下一個葉節點的指針
- 搜索時只會命中葉節點,葉子節點相當於數據存儲層,保存關鍵字對應的數據,非葉節點只保存關鍵字與指向葉節點的指針,非葉節點B+樹小很多(只保存了指針)
B+樹比B樹更適合做索引:
- 葉節點之間有指針相連,B+樹跟適合範圍檢索
- 由於非葉節點只保留關鍵字和指針,B+樹可以容納更多的關鍵字,降低樹高,磁盤IO代價更低
- B+樹查詢過程穩定,必須由根節點到葉節點,所有關鍵字查詢路徑相同,效率相當.Mysql數據的索引就提供了B+樹的實現
B*樹
在B+樹的非葉節點上增加了指向同一層下一個非葉節點的指針
算法
字符串匹配問題
先於面試官交流,詢問是否有其他要求
Example:判斷給定字符串中的符號是否匹配
解題思路:
1. 使用棧
2. 遇到左括號入棧
3. 與右括號出棧,判斷出棧括號是否成對
private static fianl Map<Character,Character> brackets = new HashMap<>();
static{
brackets.put(')','(');
brackets.put(']','[');
brackets.put('}','{');
}
public static boolean isMatch(String str){
if(str==null){
return false;
}
Stack<Character> stack = new stack<>();
for(char ch : str.toCharArray()){
if(barckets.containsValue(ch)){
stack.put(che);
} else if (brackets.contiansKey(ch)){
if(stack.empty() || stack.pop() != bracjets.get(ch)){
return false;
}
}
}
return stack.empty();
}
解題技巧
認真審題:
- 單模匹配還是多模匹配
- 時間複雜度空間複雜度是否有要求
- 明確期望的返回值,如,多匹配結果的處理
解題思路
- 單模匹配:BM,KMP算法
- 多模匹配:Tire樹
- 前綴或後綴匹配
- 可以藉助棧,樹等數據結構
TopK問題
找出N個數中最小的k個數(N非常大)
解法:
- 用前K個數創建大小爲K的大根堆
- 剩餘的N-K個數與堆頂進行比較,小於堆頂,則替換。
時間複雜度:O(N*log(K))
優點:不用在內存中讀入所有元素,適用於非常大的數據集
從N有序隊列中找到最小的K個值
解法:
- 用N個隊列的最小值組成大小爲K的小根堆
- 取堆頂值
- 將堆頂值所在隊列的下個值加入堆(與堆中最大值比較,若該值大於最大值則可停止循環)
- 重複步驟2,直到K次
時間複雜度:O((N+K-1)*log(K))
常用算法介紹
分治:快排,歸併排序
面試考察點
- 瞭解基本數據結構及特點
- 如,有哪些二叉樹,各有什麼特點
- 表/棧/隊列/數需要熟練掌握,深刻理解使用場景
- 紅黑樹適合用搜索,B+數適合做索引
- 瞭解常用的搜索/排序算法,以及複雜度和穩定性
- 特別是快速排序和堆排序
- 瞭解常用的字符串處理算法
- 如,BM使用後綴匹配進行字符串匹配
- 能夠分析算法實現的複雜度
- 特別是時間複雜度
- 瞭解常用算法分類,解決問題的實錄和解決哪類問題
加分項
- 能夠將數據結構與實際使用場景結合
- 如,介紹紅黑樹時,結合TreeMap的實現,介紹B+數時,結合Mysql中的索引實現
- 不同算法在業務場景中的應用
- 如,TopK算法在熱門排序中的應用
- 面對模糊的題目能夠後溝通確認條件和邊界
- 書寫算法代碼前,先講一下解題思路
- 能夠發現解答的一些問題,給出改進思路
真題彙總
- 各種排序算法的實現和複雜度,穩定性
- 二叉樹的前中後序遍歷
- 翻轉句子中單詞的順序
- 用棧模擬隊列(或用隊列模擬棧)
- 對10億個數進行排序,限制內存爲1G
- 採用分治的思路
- 去掉(或找出)兩個數組中重複的數
- 排序和hash兩種思路
- 將一顆二叉樹轉換成其鏡像
- 確定一個字符串中的括號是否匹配
- 給定一個開始詞,一個結束詞,一個字典,如何找到從開始詞到結束詞的最短單詞接龍
- 考慮使用深度優先算法
- 如何查找兩個二叉樹的最近公共祖先
- 遞歸與非遞歸皆可實現
七、常用工具集
- 知識點彙總
- 知識點詳解
- JMC(Java Mission Control)
- btrace
- 其他常用工具
- Git
- 常用Linux分析工具
- 考察點
- 加分項
- 真題彙總
知識點彙總
知識點詳解
JMC(Java Mission Control)
1.7提供的圖形化JVM分析與監控工具
[外鏈圖片轉存失敗(img-hI3EamWI-1565101632766)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555666380171.png)]
-
JVM瀏覽器
- 可列出正在運行的Java程序JVM,每個JVM實例叫做一個JVM連接,使用JDP(Java Discover Protocol),可以連接到本地和遠程運行的JVM
-
JMX(Java Management Extensions)
- 可以管理並監控JVM,通過對MBean的管理可以實時收集JVM信息,例如,類使用信息,堆使用情況,CPU負載,線程信息等,以及其他可以通過MBean管理的運行時屬性
-
JFR(Java Flight Recorder)
- 提供了能夠深入JVM內部,能看到運行時狀態的能力,是個非常強大的性能profile工具,適合對程序進行調優和問題排查.主要對運行事件進行採集,可以通過指定採集的事件和頻率,收集非常全面的的數據信息
- GC:不同階段及耗時情況,停頓時間,分代大小
b-trace
JVM實時監控工具,基於動態字節碼修改技術,實現對運行中的Java程序跟蹤和替換,可在不重啓JVM的情況下,監控系統運行情況,獲取JVM運行時的數據信息,如,方法參數,返回值,全局變量,堆棧信息等
[外鏈圖片轉存失敗(img-G5DrxP45-1565101632766)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555666734520.png)]
注意事項:
- 不恰當的使用會導致JVM崩潰
- btrace操作會持續JVM運行期間
- 通過JVM參數,取消btrace安全限制
其他常用工具
類 | 作用與特點 |
---|---|
jps | 查看Java進程信息:進程id,主類名稱,主類全路徑 |
jmap | 查看JVM中對象的統計信息:內存佔用,實例個數,對象類型,可以堆分析 |
jstat | 實時監控JVM的資源和性能:類加載情況,內存容量、使用量,GC次數、時間 |
jstack | 查看JVM線程棧信息:線程名稱、序號、優先級、線程狀態、鎖狀態 |
jinfo | 動態查看,調整JVM參數 |
jcmd | 1.7提供的綜合工具:向JVM發送診斷命令,包含jmap、jstat、jstack |
jconsole,jprofiler,jvisualvm | 監控與性能分析.建議使用JMC代替 |
實際應用場景
- 希望打印GC詳細日誌,發現未開啓時,可通過jinfo開啓print_gc_details,動態生效
- 分析內存泄漏風險時,使用jmap或jcmd定期獲取堆對象的統計信息,發現定期增長的可疑對象
- 發現所有服務都存在耗時較高的情況,可以使用jstat檢查gc回收狀況,看看是不是gc停頓耗時過高
- 遇到某個服務卡死或停止處理時,可用jstack查看線程棧,是否存在多個線程爲block狀態,產生了死鎖
- 當服務上線後沒有達到預期,可用jmc分析JVM運行信息,看看哪些熱點方法可以優化,哪些線程競爭可以避免
Git
Git常用工作流
常用Linux分析工具
類 | 作用與特點 |
---|---|
vmstat | 進程,虛擬內存,頁面交換,IO讀寫,CPU活動 |
instat&iotop | 系統IO狀態信息 |
ifstat&iftop | 實時網絡流量監控:能看到那個ip在霸佔網絡流量 |
netstat | 查看網絡相關信息,各種網絡協議套接字狀態 |
dstat | 全能型實時系統信息統計:CPU、內存、網絡、負載、系統磁盤信息 |
strace | 診斷,調試程序的系統調用:JVM執行native方法時進行調試 |
GDB | 程序調試,JVM因未知原因崩潰,coredump分析 |
lsof | 查看系統當前打開的文件信息 |
tcpdump | 網絡抓包工具:服務之間的調用 |
traceroute | 網絡路由分析工具:本地和目標計算機之間的所有路由,經過公網的服務之間網絡問題排查 |
考察點
- 瞭解常用的JVM分析工具
- 分析線程死鎖可用jstack
- 內存溢出可用jmap:堆中佔用最大的對象類型
- 分析程序性能可用jmc中的jfr
- 掌握Git的常用操作與工作流
- merge命令(提交commit來合併修改)與rebase命令(修改提交歷史記錄)的區別
- 各種工作流的優缺點
- 瞭解Linux系統下常用的分析工具
- 磁盤寫入用時較高,可用iostat分析磁盤io情況
- 不能確定問題,可用strace對文件寫入的系統調用進行分析
- 定位CPU負載較高的原因,可用top與jstack結合分析
加分項
- 能夠主動出擊體現知識廣度
- 能夠體現使實戰能力
實戰重點說明
詢問線上問題
遇到過單機請求耗時較高的問題,通過JMC的飛行記錄器採樣分析,發現寫log日誌時,線程競爭非常激烈,很多線程在等待寫鎖時耗時非常大。
進一步通過iostate排查發現,util利用率比較高,最後定位是磁盤出現了問題。解決方法,一方面更換磁盤來解決問題,另一方面對寫競爭比較激烈的日誌文件,使用了異步log機制。
介紹自己開發的項目:
1.上線前使用JMC做了性能profile,發現並優化了某些問題
2.對兩個不同方案使用JMH測試,驗證了兩個方案的性能
真題彙總
- 排查JVM問題有哪些常用工具?(你曾遇到過什麼問題,如何排查,如何解決的)
- Git合併代碼由哪些方法?有什麼區別?
- Git與SVN有哪些差異?
- 你所在的吐納對項目開發使用什麼樣的工作流?有什麼優點?
JMC,TCPdump,Strace
八、必會框架1️⃣一Spring全家桶
- 知識點彙總
- 知識點詳解
- Spring
- Spring中的基本概念
- Spring框架
- Spring機制與實現
- Spring應用
- Spring Context初始化流程
- Spring中Bean的生命週期
- Spring擴展接口
- SpringBoot
知識點彙總
知識點詳解
Spring
Spring中的基本概念
[外鏈圖片轉存失敗(img-TAawpDbs-1565101632767)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555670082098.png)]
- IOC/DI
- 對象的屬性由自己創建,爲正向流程,而由Spring創建,爲控制反轉.
- DI(依賴注入)爲實現IOC的一種方式,通過配置文件或註解包含的依賴關係創建與注入對象.
- 正向流程導致了對象與對象之間的高耦合,IOC可以解決對象耦合的問題,有利於功能的複用
例如,招聘中,公司按崗位要求安排人選爲正向流程,反之,由第三方獵頭匹配崗位和候選人,並向公司推薦,則爲控制反轉
- Context&Bean
- 所有由Spring創建,管理,用於依賴注入的對象,稱爲Bean
- 所有Bean創建並完成依賴注入後,都會放入Context上下文中進行管理
- AOP(Aspect Oriented Programming 面向切面編程)
- 以功能進行劃分,對服務順序執行流程中的位置進行橫切,完成各服務共同需要實現的功能
Spring框架
[外鏈圖片轉存失敗(img-oh1hG9gQ-1565101632768)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555670118767.png)]
重點了解一下幾點
- Core
- Spring組件的核心
- Beans和Context
- 實現IOC/DI的基礎
- Web
- 包括SpringMVC是Web服務的控制層實現
- AOP
- 面向切面編程
Spring機制與實現
Spring應用
-
@Component和@Bean的區別
Component在類上使用,表明其是組件類,需要Spring爲這個類創建bean
Bean使用在方法上,告訴Spring這個方法返回一個bean對象,需把返回的對象註冊到Spring應用的上下文中
-
設置類,autowried、qualilfier 以及bytype、byname不同的自動裝配機 制
-
Web類知道就行
Spring Context初始化流程
三種:xml配置的、Springboot的、web的ApplicationContext
[外鏈圖片轉存失敗(img-91cSprf7-1565101632769)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555677689877.png)]
[外鏈圖片轉存失敗(img-H3C7CbEB-1565101632770)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555677702922.png)]
-
prepareRefresh();
對刷新進行準備,包括設置開始時間,設置激活狀態,初始化Context中的佔位符,子類根據其需求執行具體準備工作,而後再由父類驗證必要參數 -
obtianFreshBeanFactory();
,刷新並獲取內部的BeanFactory對象 -
prepareBeanFactory(beanFactory);
,對BeanFactory進行準備工作,包括設置類加載器和後置處理器,配置不能自動裝配的類型,註冊默認的環境Bean -
postProcessBeanFactory(beanFactory);
爲Context的子類提供後置處理BeanFactory的擴展能力,如想在bean定義加載完成後,開始初始化上下文之前進行邏輯操作,可重寫這個方法 -
invokeBeanFactoryPostProcessors(beanFactory);
,執行Context中註冊的BeanFactory後置處理器,有兩張處理器,一種是可以註冊Bean的後置處理器,一種的針對BeanFactory的後置處理器,執行順序是先按優先級執行註冊Bean的後置處理器,而後再按優先級執行鍼對BeanFactory的後置處理器SpringBoot中會進行註解Bean的解析,由ConfigurationClassPostProcessor觸發,由ClassPathDefinitionScanner解析,並註冊到BeanFactory
-
registerBeanFactoryProcessor(beanFactory();
,按優先級順序在BeanFactory中註冊Bean的後置處理器,Bean處理器可在Bean的初始化前後處理 -
initMessageSource();
初始化消息源,消息源用於支持消息的國際化 -
initApplicationEventMuticaster();
初始化應用事件廣播器,用於向ApplicationListener通知各種應用產生的事件,標準的觀察者模型 -
onRefresh();
,用於子類的擴展步驟,用於特定的Context子類初始化其他的Bean -
registerListeners();
,把實現了ApplicationListener的類註冊到廣播器,並對廣播其中早期沒有廣播的事件進行通知 -
finishBeanFactoryInitialization(beanFactory);
,凍結所有Bean描述信息的修改,實例化非延遲加載的單例Bean -
finishRefresh();
,完成上下文的刷新工作,調用LifecycleProcessor.onRefresh(),以及發佈
ContextRefreshedEvent事件 -
resetCommonCaches();
在finally中執行該步驟,重置公共的緩存,如ReflectionUtils中的緩存,
AnnotationUtils等
Spring中Bean的生命週期
[外鏈圖片轉存失敗(img-9XhQo5cX-1565101632770)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555677947778.png)]
Spring擴展接口
擴展接口 | 作用 |
---|---|
BeanFactoryPostProcessor | 處理Bean前,對BeanFactory進行預處理,描述信息加載完未初始化 |
BeanDefinitionRegistryPostProcessor | 可添加自定義的Bean,根據scope創建新的代理bean |
BeanPostProcessor | 支持Bean初始化前後的處理 |
ApplicationContextAware | 可以獲得ApplicationContext及其中的Bean,動態獲取bean |
InitializingBean | 在Bean創建完,所有屬性注入後執行,對自動裝配的屬性驗證 |
DisposableBean | 在Bean銷燬前執行,回收工作 |
ApplicationListener | 用於監聽產生的應用事件 |
前三個可以通過實現ordered或者priordered接口指定執行順序,priorityordered先於ordered
SpringBoot
九、必會框架2️⃣Netty與RPC與ORM
- 知識點彙總
- 知識點詳解
- Netty
- Netty線程模型
- RPC
- 開源RPC框架介紹
- Mybatis
- Mybatis處理流程
- 面試考察點
- 加分項
- 真題彙總
知識點彙總
無
知識點詳解
Netty
Netty線程模型
[外鏈圖片轉存失敗(img-r6S1Rete-1565101632771)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555678637956.png)]
其中ChannelPiepline的設計模型採用的是Handler組成的責任鏈模型
更詳細介紹請看這可能是目前最透徹的Netty原理架構解析
添加~~~
RPC
Remote Procedure Call(遠程過程調用))
[外鏈圖片轉存失敗(img-1KD2N1IR-1565101632771)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555678719460.png)]
開源RPC框架介紹
Dubbo 打包(double) | Motan | gRPC |
---|---|---|
服務治理型框架 多種負載均衡策略 自動服務註冊治理 可視化服務治理 基於TCP私有協議,Netty | 輕量級服務治理框架 支持多語言 支持ServiceMesh方案 拓展能力強大 基於TCP私有協議,Netty | 支持多語言交互 提高服務治理拓展 支持流式調用 支持服務端推送 基於HTTP2.0 |
Mybatis
Mybatis處理流程
[外鏈圖片轉存失敗(img-3pfgDxvK-1565101632772)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555679091809.png)]
面試考察點
- 掌握Spring的IOC,AOP的概念與實現
- 掌握Spring的Context創建流程和Bean的生命週期
- 瞭解Spring常見註解的作用與使用方法
- 瞭解SpringBoot的相關知識點
- 掌握Netty的線程處理模型
- 知道常用RPC框架的特點
- 瞭解Mybatis和Hibernate的實現原理
加分項
- 閱讀過源碼,瞭解實現細節和思路,結合斷點調試的方法
- 不僅會應用,還能夠理解設計理念,設計思想
- 瞭解最新實現或方向
- 有實際優化經驗,例如netty調優,儘量減少io線程佔用,把可以後置的處理放到業務線程池中
真題彙總
- SSH與SSM框架組合的區別
- SpringMVC與Struct的區別,Mybatis與Hibernate的區別
- 描述一下SpringContext的初始化流程
- 簡單介紹一下Bean的生命週期與作用域
- Spring配置中的placeholder佔位符是如何替換的,有什麼辦法實現自定義的配置替換
- 通過BeanFactoryPostProcessor處理,
- 自定義處理可以擴展PropertyPlaceholderConfigurer或PropertySourcesPlaceholderConfigurer
- SpringMVC工作流程
- 從HandlerMapping查找handler,執行handler,執行完成返回ModelAndView,由視圖解析返回視圖,再由渲染器進行渲染
- Spring如何解決循環依賴
- 構造器循環依賴和setter循環依賴兩部分解答,構造器通過使用創建Bean中的標識池判斷是否產生了循環創建,setter通過引入ObjectFactory解決
- Bean構造方法,@PostConstuct註解,InitiatingBean,init-method的執行順序
- Netty中有哪些重要的對象,它們之間的關係是什麼
- Channel,Socket,NioEventLoop,ChannelPipeline等
- RPC與HTTP的區別,以及相對應的使用場景
- 使用方式:HTTP使用C/S(client)方式調用,RPC使用動態代理方式調用
- 請求模型:HTTP經過dns解析,4/7層代理等中間環節,rpc點對點直連
- 服務治理:rpc豐富的服務治理功能,熔斷,負載均衡
- 語言友好:HTTP對跨語言之間的更加友好
- RPC的交互流程是怎樣的
- 介紹一下Mybatis的緩存機制
- Mybatis如何配置動態Sql,有哪些動態標籤
十、緩存(Redis與Memcache)
- 知識點彙總
- 知識點詳解
- MC的內存結構
- Redis
- 功能
- 持久化
- 淘汰策略
- Redis數據結構
- 緩存常見問題
- 面試考察點
- 加分項
- 真題彙總
知識點彙總
緩存是高併發場景下,提升熱點數據訪問性能的手段
知識點詳解
MC的內存結構
[外鏈圖片轉存失敗(img-YpKQLgqg-1565101632773)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555679749069.png)]
添加~~~
Redis
功能
bitmap
支持按位存取信息,可用於實現bloomfilter
hyperLogLog
提供不精確的去重統計功能,適合用作大規模數據的去重統計
geospatial
可用於保存地理位置,並作位置距離計算或根據半徑計算位置等
Sub/Pub
訂閱發佈功能,可用於簡單的消息隊列
pipeline
可批量執行一組指令,一次性返回全部結果,另一種方式是使用腳本
事務功能是串行執行,但失敗不會回滾
持久化
- RDB
- 將數據集以快照形式寫入磁盤,通過fork子進程執行,採用二進制壓縮存儲
- redis數據保存在單一文件中,適合用作災害備份,
- 缺點:快照寫入磁盤之前宕機會丟失數據,保存快照時會短時間服務停頓
- AOF
- 以文本日誌的形式,記錄redis的每一個操作
- 追加模式,靈活同步策略以保持同步(每秒,每次操作,不同步)
- 缺點:磁盤文件與RDB方式比大,效率低於RDB
高可用
三級能哨兵監視redis主服務器狀態,主掛掉,選出新主
master選舉
- slave的priority越低,優先級越高
- 同等情況,slave複製的數據越多
- id越小,容易被選中
集羣中sentinel也會多實例部署,之間通過rift協議保證自身的高可用
redis-claster使用分片機制,16384(2^10)個slat,每個負責一部分,通過slave節點保障數據冗餘
淘汰策略
voltile-
對設置的生存時間的key進行lru,最小生存時間,隨機剔除
allkeys-
則是對所有key
no-eviction
則是不進行剔除,讀取正常,寫入則會報異常
Redis數據結構
[外鏈圖片轉存失敗(img-lfHZnttW-1565101632773)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555680619319.png)]
使用字典存儲不同類型的數據,如圖中的dict HT,字典由一組dictEntry組成(指向K-V的指針,及指向下一個dictEntry的指針)。所有對象都被封裝爲redisObject(包括了對象的類型與具體對象的存儲方式)
-
sting類型,最常使用的,通過SDS(Simple Dynamic String)實現
SDS類似ArrayList可以通過預分配冗餘空間,減少內存頻繁分配
-
list由ziplist壓縮鏈表和linkedlist雙鏈表實現
ziplist
存儲在連續位置上,存儲效率高,不利於修改操作,適用於數據較少的情況linkedlist
再插入節點上複雜度低,但內存開銷大,節點地址不連續,容易產生內存碎片- 3.2後增加了
quicklist
,其本身是雙向無環鏈表,每個節點是ziplist
-
hash由ziplist和hashtable實現
- 當
hash
中的K/V字符串長度小於64B且hash長度小於512時使用ziplist
,超過時使用hashtable
- 當
-
set由hashtable和intset
- 當set中的值都爲數值且set長度小於512時使用
intset
,否則使用hashtable
- 當set中的值都爲數值且set長度小於512時使用
-
sorted set有序集合(zset)由ziplist和skiplist實現
- 當sorted set中元素長度小於64B且
zset
長度小於128時使用ziplist
,超過時會使用skiplist
- 當sorted set中元素長度小於64B且
redis內存分配採用jemalloc,將內存劃分爲small,large,huge三個範圍,並在其中劃分了不同大小的內存塊,存儲數據時選擇大小合適的內存塊進行存儲,有利於減小內存碎片
緩存常見問題
緩存問題 | 產生原因 | 解決方案 |
---|---|---|
緩存更新方式 | 數據變更,緩存時效性 | 同步更新,失效更新,異步更新,定時更新 |
緩存不一致 | 同步更新失敗,異步更新 | 增加重試,異步補償任務,最終一致 |
緩存穿透 | 惡意攻擊 | 空對象緩存,bloomfilter過濾器 |
緩存擊穿 | 熱點key失效 | 互斥更新,隨機退避,差異失效時間 |
緩存雪崩 | 緩存宕機 | 快速失敗熔斷,主從模式,集羣模式 |
-
失效時繼續使用數據,由異步更新數據,避免了失效瞬間的空窗期。純異步:定時更新
-
緩存穿透,一直用不存在的用戶id頻繁請求接口,查詢緩存不命中,穿透db查詢依然不命中,大量db查詢
不存在的用戶,緩存中保存空對象進行標記,可能會導致大量無用數據
bloomfilter,存在性檢測,不存在則數據一定不存在;存在則實際可有可無
-
緩存擊穿,某個熱點數據失效時,大量針對這個數據的請求會針對到數據源
互斥鎖更新,同一個進程,針對同一個數據不會併發請求db,減小db的壓力
隨機退避,失效時隨機sleep一個很短的時間,再次查詢如果失敗,才執行更新
差異失效時間,針對多個熱點,避免同一時刻失效
面試考察點
- 瞭解緩存的使用場景,不同類型緩存的使用方式
- 對db熱點數據進行緩存能減輕db壓力,對熱點服務進行緩存能提高服務併發性能
- 單純的K/V緩存場景可以使用MC,需要緩存特殊數據結構時可以使用Redis
- 如,緩存視頻播放列表可以使用redis的list緩存,計算排行榜數據時可以使用zset
- 掌握MC和Redis的常用命令
- 瞭解MC和Redis在內存中的存儲結構
- 瞭解MC和Redis得數據失效方式和提出策略
- 如主動觸發的定期刪除,被動觸發的延期刪除
- 瞭解Redis的持久化,主從同步與cluster部署的原理
- 如RDB與AOF的實現方式與區別
加分項
- 結合實際應用場景來介紹緩存的使用
- 如調用後端服務接口獲取信息時,可使用本地+遠程的多級緩存
- 動態排行榜,使用zset
- 有過分佈式緩存設計和應用經驗
- 什麼場景使用了redis,使用了什麼樣的數據結構,解決了那類的問題
- 使用MC時,根據預估值的大小,調整MC slave的分配參數
- 瞭解緩存使用中可能出現的問題
- redis 單線程處理,避免耗時較高的單個請求任務,防止相互影響
- 避免和其他CPU密集型的進程部署在同一臺機器
- 禁用內存交換,防止redis的緩存數據交互在硬盤上,影響性能
- 知道Redis的典型應用場景
- 實現分佈式鎖,
- 使用bit-map實現bloom filter
- 使用 進行uv統計
- 知道Redis的新特新
- 5.0stream相較Sub/Pub功能可將未消費的信息進行緩存類似(kafka)
真題彙總
- Redis和Memcache有什麼區別,該如何選擇?
- 你用到那些Redis的數據結構,在什麼場景下?
- Redis有哪些持久化方式,有什麼區別?
- Redis的失效機制是怎樣的,Redis有哪些淘汰策略?
- 如何保證Redi的高併發和高可用?
- 高併發:主從讀寫分離,多從庫,多端口實例以及cluster集羣部署
- 高可用:sentinel保證主庫宕機時,重新選住並完成從庫的變更
- 如何使用Redis實現延時隊列,如何使用Redis實現分佈式鎖?
- 可使用sortedset實現延遲隊列,使用時間戳做score,消費方使用zrange by score命令獲取指定延遲時間之前的數據.
- 可是使用setnx設置key,返回1則獲取鎖成功,返回0則獲取鎖失敗,需要同時使用px參數設置超時時間,防止獲取鎖的實例宕機後產生死鎖,嚴格場景下使用red log方案,單比較複雜
十一、消息隊列與數據庫
- 知識點彙總
- 消息隊列
- RabbitMQ
- ActiveMQ
- RocketMQ
- kafka
- 數據庫
- 關係型數據庫
- NoSQL(Not Only SQL)
- NewSQL
- 數據庫範式
- 知識詳解
- Kafka架構
- Kafka消息生產/生產流程
- 數據庫事務
- 事務特性
- 事務併發問題與隔離級別
- 事務分類
- MySQL
- 索引
- MySQL調優
- 考察點
- 加分項
- 真題彙總
知識點彙總
消息隊列
RabbitMQ
Erlang開發的開源消息隊列,通過Erlang的Actor模型,實現了數據的穩定可靠傳輸.支持AMQP,XMPP,SMPP等多種協議,因此也比較重量級,由於採用broker代理架構,發送給客戶端時,先在中間隊列進行排隊.RabbitMQ單機吞吐量在萬級不算很高
ActiveMQ
可部署於代理模式和P2P模式,同樣支持多種協議,單機吞吐量在萬級.但是不夠輕巧,對於隊列較多的時候支持不是很好,並且有較低概率丟失消息
RocketMQ
阿里開源的消息中間件,單機支持十萬級的吞吐量,使用Java開發具有高吞吐量,高可用性的特點,適合在大規模分佈式系統中使用
kafka
有Scala開發的跨語言高性能分佈式消息隊列,單機吞吐量在十萬級,消息延遲在毫秒級.完全的分佈式系統,blocker,producer,consumer都是原生自動支持分佈式,依賴ZooKeeper做分佈式協調.支持一寫多讀,可被多個消費者消費.消息皆不會丟失,但可能重複
數據庫
關係型數據庫
- Oracle
- 功能強大,缺點貴
- MySQL
- 互聯網行業中最流行的數據庫,業務邏輯簡單數據可靠性要求低
- MariaDB
- MySQL的分支,由開源社區維護
- PostgreSQL
- 類似於Oracle的多進程模型,可支持高併發的應用場景,幾乎支持所有SQL標準,適合嚴格的企業應用場景
NoSQL(Not Only SQL)
- Redis
- 適用於數據變化快,數據大小可預測的場景
- MongoDB
- 基於分佈式文件存儲的數據庫
- 將數據存儲爲一個文檔,數據結構由鍵值對組成
- 適用於表結構不明確,數據結構不斷髮生變化的場景
- 不適合有事務和複雜查詢的場景
- Hbase
- 是在hdfs(Hadoop Distributed File System hadoop分佈式文件系統)中分佈式面向列的數據庫,類似於Google的Bigtable
- 可提供快速隨機訪問海量結構化數據,在表中由行排序,一個表中有多個列族,每個列族有任意數量的列
- 依賴於hdfs,可以實現海量數據的可靠存儲,適用於數據量大,寫多讀少,不需要複雜查詢的場景
- Cassandra
- 高可靠大規模分佈式存儲系統
- 支持分佈是的結構化K-V存儲
- 以高可用爲主要目標
- 適合寫多場景,簡單查詢,不適合數據統計
- Pika
- 提供大容量類Redis的存儲服務
- 兼容Redis的五種數據結構的大部分命令
- 使用磁盤存儲,解決Redis存儲成本問題
NewSQL
- TiDB
- 開源分佈式關係型數據庫
- 幾乎完全兼容MySQL
- 支持水平彈性擴展,ACID事務,標準SQL,MySQL語法和MySQL協議
- 具有數據強一致性的高可用性
- 既適合在線事務處理,也適合在線分析處理
- OceanBase
- 螞蟻金服所有,滿足金融級數據可靠性以及數據一致性要求的數據庫系統
- 已商業化不再開源
數據庫範式
範式級別越高,對數據表要求的越嚴格
- 第一範式(最低)
- 要求表中的字段不可再拆分
- 第二範式
- 在滿足第一範式的基礎上,要求每條記錄由主鍵唯一區分,記錄中的所有屬性都依賴與主鍵
- 第三範式
- 在滿足第二範式的基礎上,要求所有屬性直接依賴於主鍵,不允許間接依賴
- 巴斯-科德範式(一般滿足至此即可)
- 在滿足第三範式的基礎上,要求聯合主鍵的各字段之間互不依賴
- 第四範式
- 第五範式
知識詳解
Kafka架構
[外鏈圖片轉存失敗(img-gu6Ns5tB-1565101632774)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555736863349.png)]
- Kafka集羣有多個server組成,每個server稱爲一個Broker,爲消息代理
- Kafka中消息是按topic進行劃分的,一個topic就是一個queue,實際應用中不同數據可設置爲不同topic
- 一個topic可以有多個consumer,當producer發送數據到topic中時,訂閱了該topic的consumer都能接收到消息
- 爲提高並行能力,維護了多個portion分區,每個portion保證id唯一且有序,新消息會儲存在隊尾,
- portion持久化時會分段,保證對較小的文件進行寫操作,以提高性能
- 每個topic會被分爲多個portion,存於多個broker上,以保證容災
Kafka消息生產/生產流程
[外鏈圖片轉存失敗(img-iT7kuUlk-1565101632774)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555737083837.png)]
- 對consumer進行分組管理,以支持消息的一寫多讀
- producer有多種方式選擇portion,輪循(默認),指定,根據key值得hash選擇portion
- 消息得發送有三種
- 同步(默認):producer發送消息時,同步獲得反饋
- 異步:producer以batch的方式push消息,可以極大地提高性能,也增加消息丟失風險
- oneway:只發送消息,不返回結果
- Kafka確保每個group中只能有一個consumer消費
- 通過group coordinator管理哪個consumer負責消費哪個portion.默認支持range和輪循分配
- 在zookeeper中保存了每個topic的每個portion的消費偏移量offset.通過更新offset,以保證每條消息都被消費
ps.每個consumer線程相當於一個consumer實例,當consumer group中的consumer數量大於portion時,有的consumer會讀取不到數據
數據庫事務
事務特性
原子性(操作要麼全成功,要麼失敗回滾)、一致性、隔離性(多個事務之間相互隔離)、持久性
事務併發問題與隔離級別
髒讀:事務處理過程中,讀取了另一個事務中未提交的數據
不可重複讀:多次查詢,返回不同的數據值(因爲中間可能被其他事務更改數據了)
幻讀:第二次查詢,結果集不同,記錄的增加或刪除導致
[外鏈圖片轉存失敗(img-ttVPxzM5-1565101632775)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555737420868.png)]
事務分類
-
扁平事務:所有操作都在同一層次(日常使用最多).缺點:不能提交事物的某一部分
-
帶保存點的扁平事務:在事務中插入保存點,失敗回滾時,可回滾至任意保存點,而不是回滾整個事務
-
鏈事務:可看作上一事務的變種,事務提交時會將上下文隱式傳遞給下一個事務,事務失敗時,回滾至最近的事務
只能是最近的一個保存點
-
嵌套事務:由上層事務和子事務組成,類似樹形結構.頂層事務負責邏輯處理,子事務負責具體操作.子事務提交後需等待上層事務提交纔算完成,若上層事務回滾,則所有子事務回滾
-
分佈式事務:分佈式環境中的扁平化事務
- XA規範:保證強一致性的剛性事務方案
- 兩段式提交 實際中使用多
- 需要事務協調者保證,事務參與者都完成第一階段的事務準備階段.當都準備完成則通知事務參與者進行下一階段事務.(類似於Java中的countdownlatch和cyclicbarruer)
- 在一個進程發生故障時,會有較長時間的阻塞
- 三段式提交
- 增加PreCommit環節,減少兩段式提交中的阻塞時間
- 兩段式提交 實際中使用多
- TCC:滿足最終一致性的柔性事務方案
- 對每個操作都註冊確認和補償操作
- try階段:檢測業務系統,預留資源
- confirm階段:確認提交
- cancel階段:業務執行錯誤時執行回滾,釋放預留資源
- 消息事務:消息一致性方案
- 將本地操作與消息發送封裝在一個事務中,保證本地操作與消息發送要麼都成功,要麼都失敗
- 下游應用收到收到消息執行對應操作
- GTS/Fescar(視頻中有)
- XA規範:保證強一致性的剛性事務方案
MySQL
以下是曾經收集的SQL筆記:
索引
可大幅增加數據庫的查詢性能,適合讀多寫少的場景
代價:需要額外空間保存索引,插入更新刪除時,由於更新索引增加額外的開銷
- 索引類型
- 唯一索引
- 索引列中的值唯一,允許出現空值
- 主鍵索引
- 特殊的唯一索引不允許出現空值
- 普通索引
- 索引列中的值不唯一,成績什麼的
- 聯合索引
- 多個列按順序組成索引,相同列不同順序爲不同索引,最左原則,從左到右匹配
- 全文索引
- 只能在char varchar text等類型使用
- 唯一索引
- 索引實現
- B-Tree
- 最常用,大於或者小於的範圍查詢
- R-Tree
- 用於處理多維數據的數據結構,可對地理數據進行空間索引
- Hash
- 效率比B-Tree高,不支持範圍查找,排序等功能
- FullText
- 適用於全文索引
- B-Tree
MySQL調優
-
表結構與索引
- 分庫分表,讀寫分離
- 爲字段選擇合適的數據類型
- 將字段多的表分揀成多個表,增加中間表
- 混合範式與反範式,適當冗餘
- 爲查詢創建必要索引,但避免濫用
- 儘可能地是以哦那個NOT NULL
-
SQL語句優化
-
尋找最需要優化的語句:分析慢查詢日誌
- 使用頻繁或效率最低的
-
利用查詢工具:explain,profile
explain:分析語句的執行計劃,是否使用索引,使用了哪個索引,掃描了多少記錄是否使用了文件排序
profile:每個語句執行過程中的各分部耗時
-
避免使用SELECT *, 只取需要的列
避免查詢出不需要使用的字段,避免查詢列字段的源信息
-
儘可能使用prepared statements
性能更好,防止SQL注入
-
使用索引掃描來排序
在有索引的字段上進行排序操作
-
-
MySQL參數優化
-
硬件及系統配置
從1到4優化成本增加,優化效果降低
考察點
-
瞭解消息隊列,數據庫的基本原理和常用隊列,數據庫的特點
- 消息隊列適用於異步隊列,削峯填谷
-
瞭解Kafka的架構和消息處理流程
- 如何通過portion保證併發能力與冗餘災備
- consumer group如何保證每個consumer不會回去重複的消息
-
理解數據庫事務的ACID特性和隔離級別
-
掌握常用的MySQL語句和常用函數
where、order by、join、sum、count
-
瞭解MySQL數據庫不同引擎多的特點以及不同類型的索引實現
加分項
-
瞭解新特性
MySQL8.0窗口函數,支持新的查詢方式;支持通用表表達式,複雜查詢中的嵌入表語句更加清晰
-
知道數據可表設計原則,有設計經驗
如何對容量進行評估,適當分庫分表保證未來服務的可擴展性
-
有過數據可調優經驗
明明建立了索引語句,但是查詢效率還很慢,後來通過explain分析,發現表中有多個索引,MySQL優化器選用了錯誤的索引導致查詢效率偏低,通過SQL語句中使用use index 指定索引來解決
-
消息隊列使用經驗,不同場景下的取捨
日誌推送場景,對小概率消息丟失可以容忍可以設置爲異步發送消息
金融類業務,需要設置同步發送消息,並且設置最高的消息可靠性,把request required參數設置爲-1
真題彙總
-
使用過消息隊列嗎,在什麼場景使用,用來解決什麼問題
-
使用隊列是如何保證可靠性
消息的發送者保證投遞到消息隊列,消息隊列自身的高可用,消費方處理完後修改offset
可以結合kafka的消息發送同步異步,消息的可靠性配置
-
MQ有可能發生重複消費嗎,如何解決
1.通過對消息處理實現密等,消除消息重複的影響2.使用redis 消息去重,避免重複消息的處理
-
數據庫查詢語句很慢,如何優化
創建索引,減少關聯查詢,優化SQL查詢條件
-
數據庫事務有哪些特性,事務隔離級別有哪幾種
-
如何隨SQL語句進行優化
十二、架構演進與容器技術
- 系統架構演進
- 單體架構
- 微服務架構
- 分佈式體統的CAP原則和BASE理論
- 雲原生服務
- 雲原生的12要素
- 下一代架構Service Mesh
- 微服務與Service Mesh的區別與聯繫
- 容器
- Docker
- Docker原理
- Kubernetes
- Kubernetes架構
- 考察點
- 加分項
- 面試技巧
- 提示
系統架構演進
單體架構
一個項目中的多個服務混合部署在一個進程內,服務之間的交互都是通過進程內調用完成的
優點:快速開發部署服務,服務之間調用的性能最好
缺點:隨着業務增長項目越來越臃腫,服務之間由於jar包引用導致頻繁的依賴衝突,服務資源變更困難,一個服務可能被不同業務引用,升級資源需要多個業務方同時升級.業務方可直連業務資源,存在明顯的數據安全風險.修改代碼後迴歸困難,架構難以調整等
以上問題都是由於服務之間的強耦合所導致
微服務架構
起源是爲了解決企業應用問題,特點高內聚低耦合,不同的服務單獨開發單獨測試單獨部署,服務之間通過RPC或HTTP進行遠程交互,微服務架構解決了單體架構的耦合問題,但也帶來了新的問題.由於不同服務部署在不同進程或主機中,要是用前需要先找到服務,即服務發現
一般微服務採用兩種發現方式
- RPC方式,通過註冊中心完成服務發現.由服務調用端獲得服務全部可用節點,再由client進行負載均衡調用服務
- 通過http調用服務端提供的restful接口,通過nginx反向代理完成負載均衡
不論哪種方式都從進程內通信變成了遠程通信,使得性能下降,可靠性降低
分佈式體統的CAP原則和BASE理論
Consistency 一致性:所有節點在同一時間的數據完全一致
Availability 可用性:任意時間總能執行讀寫任務
Partition tolerance 分區容差:同出現節點異常時,仍然能提供滿足需求的服務
三者只可能同時滿足兩個
只選擇CA相當於單機架構
只選擇CP,則允許在極端情況下出現短時的服務不可用,如zookeeper,不適合做服務註冊中心
只選擇AP,則允許出現短時間不一致,如eureka
Basically Available(基本可用),Soft state(軟狀態),Eventually consistent(最終一致性)
是對CAP中一致性權衡的結果,即使無法做到強一致性,也可以根據系統的特點採用適當的方法得到最終一致性
雲原生服務
雲原生架構由微服務組成,是一種能夠快速持續可靠規模化的交付業務服務的模式
一般爲兩種,私有云和公有云
- 容器化的微服務:雲原生的主體
- Devops:對微服務的動態管理
- 持續交付:雲原生的目的
IaaS提供計算資源
PaaS平臺提供運行環境
微服務的解耦會導致道德業務拆分成小的服務,每個服務的部署都需要考慮單點問題,需要多機房多節點部署,會造成系統資源的浪費,服務擴容是需重新整理服務依賴的環境
容器化技術把服務的運行環境進行打包管理,解決了擴縮容時對運行環境的管理問題和服務器的利用率問題
隨着容器技術的逐漸成熟,微服務架構也快速普及
雲原生的12要素
- 基準代碼:代碼由版本管理工具管理,一個應用只有一份基準代碼,運行時有多個部署實例
- 依賴:在應用中顯式的聲明依賴
- 配置:環境中存儲配置,說明配置與代碼要分開管理
- 後端服務:將依賴的後端服務當作統一資源來對待
- 構建,發佈,運行:需要嚴格區分構建,發佈,運行三個步驟,並且要按順序進行
- 進程:以一個或多個進程運行,要保證進程的無狀態性
- 端口綁定:應用啓動後,相應的端口可持續提供服務直至應用關閉
- 併發:應用進程之間可以併發處理,英雌可以通過對進程方式進行水平擴展
- 易處理:應該容易被管理,可以通過優雅停機和快速啓動構建最健壯的服務
- 開發/生產等價:指在開發生產環境中的應用儘可能一致
- 日誌:要合理記錄應用的運行日誌,要把日誌當作事件流來對待
- 管理進程:把後臺管理任務當作一次性進程來運行
下一代架構Service Mesh
service mesh在微服務的基礎上引入了sidecar邊車的概念,每個服務都伴生有一個sidecar,服務的交互不再由服務自身完成,服務所有出入的請求都交由sidecar處理,在管理層面對sidecar進行統一管理,由sidecar實現服務發現,負載均衡,流量調度等
微服務與Service Mesh的區別與聯繫
微服務要解決的是多個服務之間的耦合問題,如上圖綠色豎線,將ServiceA,B,C進行解耦,單獨部署單獨管理,使得每個服務都要實現服務發現,服務間遠程交互,負載均衡,高可用策略,服務熔斷等一系列的功能
service mesh是將與業務邏輯無關的功能進行解耦,如圖中紅色的線,把與服務交互的功能從服務中剝離出來,統一交由sidecar實現,讓服務更聚焦於業務邏輯,提高研發效率.sidecar更專注於服務的交互與治理,追求極致的功能與性能
因此service mesh並不能稱爲一項新的技術,而應當是微服務的演進
由於sidecar是獨立進程,所以天然適合爲不同語言的服務提供統一的治理能力,因此跨語言治理也是service mesh的一個重要特點
由於引入了額外的sidecar,service mesh也產生新的性能與可靠性問題,這也是service mesh架構需要解決的問題
只是讓問題轉移,方便對問題集中整治和處理,讓服務更聚焦於業務研發,不同的功能交給專門的組件處理
通過架構演進,雖然沒有消滅複雜度,但讓問題變得透明化,業務無感知,提升服務整體開發效率擴展能力
容器
Docker
微服務架構的基礎
- 作用:
- 構建,部署,運行服務
- 服務版本管理
- 屏蔽環境差異
- 隔離服務
- 提高資源利用率
- 特點:
- 開源容器技術
- 基於LXC,高效虛擬化
- 適合大規模構建
- 靈活可拓展
- 管理簡單
- 概念:
- 鏡像(Images):服務代碼與運行環境的封裝
- 容器(Container):基於鏡像的服務運行狀態,可以基於一個鏡像運行多個容器
- 守護進程(Daemon):運行在宿主機上的管理進程,用戶通過client與其進行交互
- 客戶端(Client):和守護進程交互的命令行工具
- 鏡像倉庫(Repository):
Docker原理
docker通過對不同運行進程進行隔離實現虛擬化
docker運用三種方式以實現進程的隔離:
- Namespace
- 進程:docker運用三種方式以實現進程的隔離利用Linux的Namespace隔離進程之間的可見性,不同的服務進程屬於不同的Namespace,互相無法感知對方的存在.
- 網絡:docker運用三種方式以實現進程的隔離實現了host,container,null和bridge(默認)四種網絡模式.每個容器創建時都會創建一對虛擬網卡,一個在容器中一個在docker0的網橋中,組成了數據的通道.docker0的網橋通過iptables中的配置與宿主機的網卡相連,所有符合條件的請求都會通過iptables轉發到docker0,再有網橋分發給相應的容器網卡.
- 掛載點(文件目錄):爲防止容器進程修改宿主機的文件目錄,docker通過修改進程訪問文件目錄的根節點結合namespace來隔離不同容器進程可以訪問的文件目錄
- Control Groups:資源限制
- UnionFS
- docker的鏡像是分層結構,存在操作系統層,技術環境層,web容器層,服務代碼層,層與層相互依賴通過UnionFS把Image的不同分層作爲只讀目錄
- Container是在Image的只讀目錄上創建的可讀可寫的目錄
docker有AUFS, Btrfs, overlay, Devicemapper, zfs等多種不同的存儲驅動實現
Kubernetes(K8s)
容器集羣管理系統,不是PaaS平臺
- 作用:
- 容器集羣管理
- 自動化部署
- 自動擴縮容
- 應用管理
- 特點:
- 可移植
- 可擴展
- 自動化
- 概念:
- Master:管理節點,負責協調集羣中所有節點的行爲與活動(例,應用的運行,修改,更新等)
- Node:運行容器,可有多個Pod
- Pod:Kubernetes可創建部署的基本單位,可運行多個Container
- Container:爲運行中的服務鏡像,共享所屬Pod的網絡存儲
- Service:爲Pod添加標籤,將其劃分爲不同的Service
- Deployment:表示對Kubernetes集羣的一次操作(例,創建,更新,滾動升級等)
Kubernetes架構
- Master
- api server:用戶資源操作的唯一入口
- 創建應用部署
- 管理部署狀態
- 認證授權
- 訪問控制
- api註冊和發現
- controller manager:維護集羣狀態,包含多個controller(例,node controller,route controller,service controller)
- 故障檢測
- 自動擴展
- 滾動更新
- scheduler:資源調度
- api server:用戶資源操作的唯一入口
- etcd:保存集羣狀態
- kubectl:運行命令的管理工具,與Master中的api server進行交互,通過api server下達指令
- Node
- 容器運行時(container runtime):可以不是docker
- Pod:可看作虛擬服務器,可運行多個Container
- kubelet:負責人與Master通信,週期性訪問api server,進行檢查和報告,執行容器的操作,維護容器的生命週期,也負責volume和網絡的管理
- kube-proxy:處理網絡代理和容器的負載均衡,通過改變iptables規則,控制容器上的tcp和udp包
- 容器運行時(container runtime):可以不是docker
Kubernetes把所有被管理的資源看作對象,使得對資源的管理變成對對象屬性的設置,配置文件使用yaml格式
對象可大致分爲四類:
- 資源對象
- 配置對象
- 存儲對象
- 策略對象
考察點
- 表達溝通
- 分佈式架構的理解
- 系統可用性,擴展性
- 故障的應對方法
- 熔斷,容災,流量遷移
- 架構設計中的解耦
- 瞭解系統優化的常用方法
- 並行,異步,水平擴展,垂直擴展,預處理,緩存,分區
- 對工作的熟悉程度
- 自己項目的規模,調用量級
- 解決問題能力
加分項
- 關注業界最新趨勢
- 能提供方案對比選型
面試技巧
- 交代背景:
- STAR法則(情境(situation)、任務(task)、行動(action)、結果(result))
- 描述架構:架構圖或交互流程圖
- 做了什麼:突出重點,最重要的突出工作,實現能力和亮點
- 結果如何:用實力作證
- 注意量化相關性能數據
- 如何改進:存在的問題與解決方法,問題的進一步思考,總結反思
提示
- 提前思考,提前準備
- 項目在精不在多
- 我瞭解的,就是我的
- 體現對架構的理解,對設計的理解
職場成長建議
-
有策略的努力
1-2年,學習新技術,知識的廣度,技術的好奇心
3+,主動思考,學習能力,團隊協作,跨團隊溝通,項目設計能力
5+,自己的技術品牌
-
打造自己的技術品牌
工作中責任心,自己的任務一定要做好
協助同事排查解決技術難題
做有技術深度或者技術排查案例的分享
後續的職場人脈建立於此,對今後發展很有幫助
-
總結與反思
某項工作或階段性任務完成之後,及時總結。有利於發現改進空間,後續準備晉升素材
- 獲得了哪些收益
- 開發中遇到了哪些問題
- 哪些問題在設計初期就能避免
- 哪些問題要及早解決
- 開發中自己哪些地方做的不好,後續如何改建
完成項目重構
- 舊項目的問題
- 重構時哪些地方收益最明顯