前幾天寫了Java面試題彙總---基礎版,總結了面試中常見的問題及答案,那我今天基於昨天的話題作一次升級,也就是說,求職者除了要學習瞭解哪些常見的基礎面試題以外,還得準備些什麼呢?html
對有工做經驗的求職者來講,項目經歷也是一個重點。這個我想你們應該仍是比較清楚,你要知道,通常招聘有經驗的人,不是你投的,就是HR經過用人部門需求關鍵詞搜索到你的。好比用人部門想招聘幾個有分佈式開發和電商項目經驗的,那麼HR可能會用「Dubbo」,「SpringCloud」,「電商」等關鍵詞搜索。那你去面試,這些技術及相關內容也就是常問的話題了。java
一,項目經驗nginx
當HR邀約你去面試前,簡歷中寫到的項目必定得總結熟悉,尤爲以前項目中涉及的技術。我曾經有面試一個JAVA開發,當時他的簡歷寫的很完美,有三年多的開發經驗,而卻最近一個項目是B2C的電商項目,什麼Dubbo, ZK, Redis, MQ, Springboot, FastDfs等目前新的技術包羅萬象。而後我就問他Dubbo和ZK的理解以及它們怎麼協調工做,他回答的卻很簡單,僅僅概念上的一些東西。後來又問他文件服務是用什麼技術實現的,他告訴一個徹底聽不懂的玩意,而後我指着簡歷上的FastDFS問他用來作什麼,而後發現他楞了一下,接着說很差意思他說錯了,而後順帶問了下FastDFS,他居然徹底說不清楚,那面試的結果呢,確定是over了。但那哥們最後還算坦誠,告訴我B2C電商項目他沒作過,是從其餘地方搬過來的,爲了提升簡歷曝光率。所以,我要告訴你們,簡歷中的項目經歷能夠適當包裝,但必定不可過於離譜,你要保證涉及的技術在面試中可控,能應對面試官基礎的問答。程序員
二,目前流行技術及問題web
這塊也是一個重點,要想找一份心儀不錯的工做,那你在準備找工做前,必定要了解目前市場動態。最簡單的方式,去51job搜你想應聘的崗位,看看各個公司都有什麼要求,看過50家,你的內心基本就有數了。在這裏,我總結下目前流行的技術吧!面試
1,分佈式redis
目前最流行的Java後端開發,莫過於分佈式開發了。說到分佈式,那什麼是分佈式系統呢?分佈式系統就是由多個節點(計算機服務器)組成的系統。並且這些節點通常不是孤立的,是互通的。這些連通的節點上部署了咱們的節點,而且相互的操做會有協同。算法
分佈式系統對於用戶而言,他們面對的就是一個服務器,提供用戶須要的服務而已,而實際上這些服務是經過背後的衆多服務器組成的一個分佈式系統,所以分佈式系統看起來像是一個超級計算機同樣。數據庫
例如京東商城,這個平時你們都會使用,它自己就是一個分佈式系統。當咱們使用它的App時,這個請求的背後就是一個龐大的分佈式系統在爲咱們提供服務,整個系統中有的負責請求處理,有的負責存儲,有的負責計算,最終他們相互協調把最後的結果返回並呈現給用戶。編程
2,微服務
說完分佈式,那什麼又是微服務呢?對於微服務,業界並無一個統一的,標準的定義。一般而言,微服務是一種架構風格,一個大型複雜軟件應用由一個或多個微服務組成。系統中的各個微服務可被獨立部署,各個微服務之間是鬆耦合的。每一個微服務僅關注於完成一件任務並很好地完成該任務。在全部狀況下,每一個任務表明着一個小的業務能力。
而傳統項目開發應用程序都是單體型,全部的功能和業務模塊都集中在一個項目中,雖然開發和部署比較方便,但後期隨着業務的不斷增長,開發迭代和性能瓶頸等問題,將會困擾開發工做,微服務就是解決此問題的有效手段。那麼要用微服務,他涉及哪些技術呢?大體整理以下:
流行的微服務Java項目框架:Spring Boot
微服務治理:Dubbo, SpringCloud
涉及技術:Zookeeper, Eureka, Redis, MQ等
Dubbo和SpringCloud等原理及區別這裏不作解釋,我前面的文章《又到了跳槽季,大家都準備好了嗎?我來告訴Java程序員們如何快速全面的複習》中有介紹,這裏只作相關面試問題彙總。
3,分佈式環境中如何實現單點登陸與session共享
在單服務器web應用中,登陸用戶信息只需存在該服務的session中,這是咱們幾年前最長見的辦法。而在當今分佈式系統的流行中,微服務已成爲主流,用戶登陸由某一個單點服務完成並存儲session後,在高併發量的請求(須要驗證登陸信息)到達服務端的時候經過負載均衡的方式分發到集羣中的某個服務器,這樣就有可能致使同一個用戶的屢次請求被分發到集羣的不一樣服務器上,就會出現取不到session數據的狀況,因而session的共享就成了一個問題。目前實現session共享的解決方案:
1)Session複製與共享 多個server之間相互同步session,這樣每一個server上都包含所有Service的session。
優勢:tomcat等多數主流web服務器都支持此功能。
不足:session同步須要數據傳輸,佔內網帶寬,有時延。全部服務器都包含全部session數據,特別是當session中保存了較大的對象,並且對象變化較快時,性能降低顯著,這種特性使得web應用的水平擴展受到了限制。
2)客戶端存儲法 服務端存儲全部用戶的session,內存佔用較大,也能夠將session存儲到瀏覽器cookie中,每一個端只要存儲一個用戶的數據了。
優勢:服務端不須要存儲
缺點:每次http請求都攜帶session,佔外網帶寬數據存儲在端上,並在網絡傳輸,存在泄漏、篡改、竊取等安全隱患。session存儲的數據大小受cookie限制。
3)反向代理hash一致性 爲了保證高可用,有多臺冗餘,反向代理層能不能作一些事情,讓同一個用戶的請求保證落在一臺web服務器上呢?具體方案:反向代理使用IP或http協議中的某些業務參數來作hash,以保證同一個瀏覽器用戶的請求落在同一個web服務器上。
優勢:只須要改nginx配置,不用改應用代碼,負載均衡,只要hash屬性是均勻的,多臺web服務器的負載是均衡的。能夠支持web服務器水平擴展(session同步法是不行的,受內存限制)
缺點:若是web服務器重啓,一部分session會丟失,產生業務影響,例如部分用戶從新登陸。若是web服務器水平擴展,rehash後session從新分佈,也會有一部分用戶路由不到正確的session。
4)服務端集中存儲 將session存儲在後端的存儲層,如:數據庫或者緩存。客戶端每發次一次請求,都會先從存儲中獲取,再處理具體的業務邏輯。
優勢:無安全隱患,能夠水平擴,服務器重啓或者擴容都不會形成session丟失。
不足:增長了一次網絡調用,要修改應用代碼。
總結:通常對單點登陸和session共享的處理,大都選擇在服務端集中存儲來實現。對於db存儲仍是cache,確定cache是首選。由於session讀取的頻率會很高,使用數據庫壓力會比較大。若是有session高可用需求,cache能夠作高可用,但大部分狀況下session能夠丟失,通常也不須要考慮高可用。目前主流的現實方案是用redis實現session的存儲。
4,分佈式環境下的事務處理方案
分佈式事務顧名思義就是在分佈式環境下運行的事務,對於分佈式事務來講,事務的每一個操做步驟是運行在不一樣機器上的服務的。本質上來講,分佈式事務就是爲了保證不一樣數據庫的數據一致性。
事務的ACID特性:原子性,一致性,隔離性,持久性。
解決方案:
1)消息事務+最終一致性
所謂的消息事務就是基於消息中間件的兩階段提交,本質上是對消息中間件的一種特殊利用,它是將本地事務和發消息放在了一個分佈式事務裏,保證要麼本地操做成功成功而且對外發消息成功,要麼二者都失敗。以支付寶轉帳到餘額寶爲例,當支付寶帳戶扣除1萬後,只要生成一個憑證(消息)便可,這個憑證(消息)上寫着「讓餘額寶帳戶增長 1萬」,只要這個憑證(消息)能可靠保存,咱們最終是能夠拿着這個憑證(消息)讓餘額寶帳戶增長1萬的,即咱們能依靠這個憑證(消息)完成最終一致性。
2)TCC編程模式
TCC提供了一個編程框架,將整個業務邏輯分爲三塊:Try、Confirm和Cancel三個操做。以在線下單爲例,Try階段會去扣庫存,Confirm階段則是去更新訂單狀態,若是更新訂單失敗,則進入Cancel階段,會去恢復庫存。總之,TCC就是經過代碼人爲實現了兩階段提交,不一樣的業務場景所寫的代碼都不同,複雜度也不同,所以,這種模式並不能很好地被複用。
5,Zookeeper的原理及選舉機制?
ZooKeeper是一個分佈式的,開放源碼的分佈式應用程序協調服務,是Google的Chubby一個開源的實現,它是集羣的管理者,監視着集羣中各個節點的狀態根據節點提交的反饋進行下一步合理操做。Zookeeper能夠做爲服務協調的註冊中心,還能夠作分佈式鎖。它做爲註冊中心,主要存儲的數據是ip、端口,還有心跳機制。
Zookeeper作集羣最好是奇數個,它的集羣管理主要是檢查是否有機器的退出和加入、選舉master。Zookeeper的角色主要分:Leader、Follower、Observer。Leader主機負責讀和寫,Follower負責讀,並將寫操做轉發給Leader,Follower還參與Leader選舉投票。Observer充當觀察者的角色,不參與投票。當Leader不可用時,會從新選舉Leader。超過半數的Follower選舉投票便可。
6,使用Redis作緩存有哪些優點?
Redis是內存式緩存,它的存取是純內存操做,所以性能很是出色,每秒可處理超過10萬次讀寫。它的優點以下:
內存式緩存,讀寫速度特別快;
支持豐富數據類型,包括:string,list,set,sorted set,hash;
支持事務,操做都是原子性,所謂的原子性就是對數據的更改要麼所有執行,要麼所有不執行;
豐富的特性: 可用於緩存、消息,按key設置過時時間,過時後自動清除;
單線程,單進程,採用IO多路複用技術;
7,分佈式系統中如何生成惟一ID?
系統惟一ID是咱們在設計一個系統的時候經常會碰見的問題,也經常爲這個問題而糾結。生成ID的方法有不少,適應不一樣的場景、需求以及性能要求。因此有些比較複雜的系統會有多個ID生成的策略。下面就介紹一些常見的ID生成策略。
1)數據庫自增加序列實現
這是最多見的方式,利用數據庫自增ID,實現全數據庫ID惟一。
優勢:
a)簡單,代碼方便,性能能夠接受。
b)數字ID自然排序,對分頁或者須要排序的結果頗有幫助。
缺點:
a)不一樣數據庫語法和實現不一樣,數據庫遷移的時候或多數據庫版本支持的時候須要處理。
b)在單個數據庫或讀寫分離或一主多從的狀況下,只有一個主庫能夠生成。有單點故障的風險。
c)在性能達不到要求的狀況下,比較難於擴展。
d)若是碰見多個系統須要合併或者涉及到數據遷移會至關痛苦。
e)分表分庫的時候會有麻煩。
2) 經過UUID實現
常見的方式。能夠利用數據庫也能夠利用程序生成。UUID的的組成部分:當前日期和時間+時鐘序列+全局惟一的IEEE機器識別號。如:550e8400-e29b-41d4-a716-446655440000。
優勢:
a)簡單,代碼方便。
b)生成ID性能很是好,基本不會有性能問題。
c)全球惟一,在碰見數據遷移,系統數據合併,或者數據庫變動等狀況下,能夠從容應對。
缺點:
a)沒有排序,沒法保證趨勢遞增。
b)UUID每每是使用字符串存儲,查詢的效率比較低。
c)存儲空間比較大,若是是海量數據庫,就須要考慮存儲量的問題。
d)傳輸數據量大,不可讀。
3) Redis生成ID
當使用數據庫來生成ID性能不夠要求的時候,咱們能夠嘗試使用Redis來生成ID。這主要依賴於Redis是單線程的,因此也能夠用生成全局惟一的ID。能夠用Redis的原子操做 INCR和INCRBY來實現。可使用Redis集羣來獲取更高的吞吐量。假如一個集羣中有5臺Redis。能夠初始化每臺Redis的值分別是1,2,3,4,5,而後步長都是5。各個Redis生成的ID爲:
A:1,6,11,16,21
B:2,7,12,17,22
C:3,8,13,18,23
D:4,9,14,19,24
E: 5,10,15,20,25
這個,隨便負載到哪一個機肯定好,將來很難作修改。可是3-5臺服務器基本可以知足器上,均可以得到不一樣的ID。可是步長和初始值必定須要事先須要了。使用Redis集羣也能夠方式單點故障的問題。
優勢:
a)不依賴於數據庫,靈活方便,且性能優於數據庫。
b)數字ID自然排序,對分頁或者須要排序的結果頗有幫助。
缺點:
a)若是系統中沒有Redis,還須要引入新的組件,增長系統複雜度。
b)須要編碼和配置的工做量比較大。
4) Twitter的snowflake算法
snowflake是Twitter開源的分佈式ID生成算法,結果是一個long型的ID。其核心思想是:使用41bit做爲毫秒數,10bit做爲機器的ID(5個bit是數據中心,5個bit的機器ID),12bit做爲毫秒內的流水號(意味着每一個節點在每毫秒能夠產生 4096 個 ID),最後還有一個符號位,永遠是0。
snowflake算法能夠根據自身項目的須要進行必定的修改。好比估算將來的數據中心個數,每一個數據中心的機器數以及統一毫秒能夠能的併發數來調整在算法中所須要的bit數。
優勢:
a)不依賴於數據庫,靈活方便,且性能優於數據庫。
b)ID按照時間在單機上是遞增的。
缺點:
a)在單機上是遞增的,可是因爲涉及到分佈式環境,每臺機器上的時鐘不可能徹底同步,也許有時候也會出現不是全局遞增的狀況。
三,其餘相關問題
1,Java代碼優化(基礎版)
Java代碼的基本優化總結以下:
1) 儘可能指定類、方法的final修飾符, 儘可能重用對象, 儘量用局部變量。
2) 及時關閉流。
3) 儘可能減小對變量的重複計算。
4) 儘可能採用懶加載的策略,即在須要的時候才建立。
5) 慎用異常,不要在循環中使用try...catch...,應該把其放在最外層。
6) 若是能估計到待添加的內容長度,爲底層以數組方式實現的集合、工具類指定初始長度。
7) 當複製大量數據時,使用System.arraycopy()命令。
8) 乘法和除法使用移位操做。
9) 循環內不要不斷建立對象引用。
10) 基於效率和類型檢查的考慮,應該儘量使用array,沒法肯定數組大小時才使用ArrayList。
11) 儘可能使用HashMap、ArrayList、StringBuilder,除非線程安全須要,不然不推薦使用Hashtable、Vector、StringBuffer,後三者因爲使用同步機制而致使了性能開銷。
12) 不要將數組聲明爲public static final。
13) 儘可能減小硬編碼,提升代碼的易維護性。
2,談談常見的SQL優化?
通常的SQL優化注意及方案:
1)在數據量大的表中建索引, 優先考慮where、group by使用到的字段;
2)避免使用select *,返回無用的字段會下降查詢效率;
3)儘可能避免使用in 和not in, or等, 致使數據庫放棄索引進行全表掃描;
4)儘可能避免在 where 子句中使用!=或<>操做符;
5)儘可能避免在字段開頭模糊查詢;
6)儘可能避免在Where條件後進行null值;
7)儘可能避免在where條件中等號的左側進行表達式、函數操做;
8)儘可能避免向客戶端返回大數據量;
9)儘可能避免大事務操做,提升系統併發能力;
10)經過EXPLAIN 分析低效 SQL的執行計劃;
3,你是如何實現Api接口安全的?
目前市面上有不少實現方案,如最典型的ouath。這裏我只談談目前最廣泛的實現方案。也就是http+token受權+參數簽名(sign)的方式。實現方案:
1)token受權 用戶登陸成功後,服務器端生成一個Token(32位隨機字符串),並用這個token爲key,登陸用戶信息爲值存放在緩存中(Redis)。而後就token返回客戶端,做爲受權憑證。
2)封裝sign參數 登陸後請求任何一個Api接口,請求參數除正常的業務參數外,必須帶token,並用業務參數和token參數經過規定的簽名算法生成簽名,將生成的sign也做爲請求參數發起請求。如:經過ID查用戶信息,請求參數:{「id」:"11","token":"受權返回的token值","sign":"生成的簽名參數"}。
3)過濾器檢驗攔截 請求發起後,先進入服務端的過濾器,基於相同的簽名算法校驗sign參數,若是校驗不經過,直接攔截請求。若是sign校驗經過,再經過請求參數中的token值獲取緩存中的登陸信息,若是此token在緩存中不存在,咱們認爲此用戶沒有登陸或登陸過時,直接攔截請求。若是獲取到登陸信息並校驗經過,過濾器不作攔截,請求進入服務層。
4,HTTP和HTTPS的區別,及HTTPS工做流程?
這都是些基礎知識,但我也曾見過一個Java高級開發者不知道什麼的HTTPS。那HTTPS到底是什麼呢?若是你平時細心,應該早都注意到,大多數網站都是用HTTPS請求的,例如:百度。
其實,HTTPS協議就是由HTTP+SSL構建的可進行加密傳輸、身份認證的網絡協議。比http協議安全。
HTTPS工做流程以下:
1) 客戶端發送本身支持的加密規則給服務器,告訴服務器要進行鏈接。
2) 服務器從中選出一套加密算法和hash算法以及本身的身份信息(地址等)以證書的形式發送給瀏覽器,證書中包含服務器信息,加密公鑰,證書的辦法機構。
3) 客戶端收到網站的證書以後要作下面的事情:
a,驗證證書的合法性
b,若是驗證經過證書,瀏覽器會生成一串隨機數做爲密鑰K,並用證書中的公鑰進行加密
c,用約定好的hash算法計算握手消息,而後用生成的密鑰K進行加密,而後一塊兒發送給服務器
4) 服務器接收到客戶端傳送來的信息,要求下面的事情:
a,用私鑰解析出密碼,用密碼解析握手消息,驗證hash值是否和瀏覽器發來的一致
b,使用密鑰加密消息,回送
若是計算法hash值一致,握手成功。
5,談談負載均衡的原理及算法?
在一些大的網站中,當系統面臨大量用戶訪問,負載太高的時,一般會使用增長服務器數量來進行橫向擴展,使用集羣和負載均衡提升整個系統的處理能力。通常系統的擴展可分爲縱向(垂直)擴展和橫向(水平)擴展。
縱向擴展,是從單機的角度經過增長硬件處理能力,好比CPU處理能力,內存容量,磁盤等方面,實現服務器處理能力的提高,不能知足大型分佈式系統(網站),大流量,高併發,海量數據的問題。
所以須要採用橫向擴展的方式,經過添加機器來知足大型網站服務的處理能力。好比應用集羣,一臺機器不能知足,則增長兩臺或者多臺機器,組成處理集羣,接收負載均衡設備分發的請求,進行處理,並返回相應數據。
負載均衡算法:
常見6種算法: 輪詢, 隨機, 源地址哈希, 加權輪詢, 加權隨機, 最小鏈接數。
nginx的5種算法: 輪詢, weight, ip_hash, fair(響應時間), url_hash。
dubbo的均衡算法: 隨機, 輪詢, 最少活躍調用數, 一致性Hash。
6,談談你用過的設計模式?
說出幾個你熟悉的設計模式就行,這裏我列舉幾個。
1)單例模式 一個類在Java虛擬機中只有一個對象,並提供一個全局訪問點。生活中例子如:太陽、月亮等。
模式結構:分爲餓漢式和懶漢式(若是考慮性能問題的話,就使用懶漢式,由於懶漢式是在方法裏面進行初始化的),構造器私 有化,對外提供方法加同步關鍵字。
2)代理模式 爲其餘對象提供一個代理,以控制對當前對象的訪問。生活中的例子如:房屋中介。
模式結構:代理類和被代理類實現同一個接口,用戶訪問的時候先訪問代理對象,而後讓代理對象去訪問被代理對象。框架裏面使用:Spring裏面的AOP實現。JDK裏面使用:java.lang.reflect.Proxy。
3)適配器模式 將兩個原來不兼容的類兼容起來一塊兒工做。生活中的例子:變壓器、充電器。
模式結構:分爲類適配器和對象適配,通常經常使用的就是對象適配器,由於組合因爲繼承。框架裏面使用:單元測試裏面的asserEquels。
7,說說實現高併發量網站的解決方案
對一些中大型網站,在面對大量用戶訪問、高併發請求方面,基本的解決方案集中在這樣幾個環節:使用高性能的服務器、高性能的數據庫、高效率的編程語言、還有高性能的Web容器。這些解決思路在必定程度上意味着更大的投入。
1)HTML靜態化
其實你們都知道,效率最高、消耗最小的就是純靜態化的html頁面,因此咱們儘量使咱們的網站上的頁面採用靜態頁面來實現,這個最簡單的方法其實也是最有效的方法。
2)圖片服務器分離
你們知道,對於Web服務器來講,無論是Apache、IIS仍是其餘容器,圖片是最消耗資源的,因而咱們有必要將圖片與頁面進行分離,這是基本上大型網站都會採用的策略,他們都有獨立的、甚至不少臺的圖片服務器。這樣的架構能夠下降提供頁面訪問請求的服務器系統壓力,而且能夠保證系統不會由於圖片問題而崩潰。
3)數據庫集羣、庫表散列
大型網站在高併發訪問的時候,數據庫瓶頸很快就能顯現出來,這時一臺數據庫將很快沒法知足應用,因而咱們須要使用數據庫集羣或者庫表散列。
4)緩存
緩存一詞搞技術的都接觸過,不少地方用到緩存。網站架構和網站開發中的緩存也是很是重要。這裏先講述最基本的兩種緩存。高級和分佈式的緩存在後面講述。
5)鏡像
鏡像是大型網站常採用的提升性能和數據安全性的方式,鏡像的技術能夠解決不一樣網絡接入商和地域帶來的用戶訪問速度差別,好比ChinaNet和EduNet之間的差別就促使了不少網站在教育網內搭建鏡像站點,數據進行定時更新或者實時更新。
6)負載均衡
負載均衡也是大型網站解決高負荷訪問和大量併發請求採用的解決辦法。
7)CDN加速技術(最新)
CDN的即內容分發網絡。其目的是經過在現有的Internet中增長一層新的網絡架構,將網站的內容發佈到最接近用戶的網絡「邊緣」,使用戶能夠就近取得所需的內容,提升用戶訪問網站的響應速度。
8,Linux經常使用指令及服務安裝、部署維護
Linux操做系統使用相關的面試問題,也是中高級面試者確定要面對的,這個徹底得靠平時使用狀況了。最簡單的操做命令必須得知道,好比:ps, mkdir, vi, find等。具體這裏很少說,若是沒運維經驗,就去把最基本的指令記住吧。
若是你想了解和學習,能夠關注此公衆號,在公衆號聯繫或私聊