Java面試通關要點彙總集及參考答案(不吹不黑耿直福利)

以下是本人從某個視頻中歸納出來的答案,感覺牛掰就總結了出來,

你們可以到直播間去問管理要高清思維導圖和一些實用的技術資料,他們會免費的發給你們,按照他們的說法是建立一個分享、交流、學習的平臺,感覺他們太耿直了。

反模式設計

簡單的來說,反模式是指在對經常面對的問題經常使用的低效,不良,或者有待優化的設計模式/方法。甚至,反模式也可以是一種錯誤的開發思想/理念。在這裡我舉一個最簡單的例子:在面向對象設計/編程中,有一條很重要的原則, 單一責任原則(Single responsibility principle)。其中心思想就是對於一個模塊,或者一個類來說,這個模塊或者這個類應該只對系統/軟件的一個功能負責,而且該責任應該被該類完全封裝起來。當開發人員需要修改系統的某個功能,這個模塊/類是最主要的修改地方。相對應的一個反模式就是上帝類(God Class),通常來說,這個類裡面控制了很多其他的類,同時也依賴其他很多類。整個類不光負責自己的主要單一功能,而且還負責了其他很多功能,包括一些輔助功能。很多維護老程序的開發人員們可能都遇過這種類,一個類裡有幾千行的代碼,有很多功能,但是責任不明確單一。單元測試程序也變複雜無比。維護/修改這個類的時間要遠遠超出其他類的時間。很多時候,形成這種情況並不是開發人員故意的。很多情況下主要是由於隨著系統的年限,需求的變化,項目的資源壓力,項目組人員流動,系統結構的變化而導致某些原先小型的,符合單一原則類慢慢的變的臃腫起來。最後當這個類變成了維護的噩夢(特別是原先熟悉的開發人員離職後),重構該類就變成了一個不容易的工程。

分庫與分表設計

垂直分表在日常開發和設計中比較常見,通俗的說法叫做“大表拆小表”,拆分是基於關係型數據庫中的“列”(字段)進行的。通常情況,某個表中的字段比較多,可以新建立一張“擴展表”,將不經常使用或者長度較大的字段拆分出去放到“擴展表”中。在字段很多的情況下,拆分開確實更便於開發和維護(筆者曾見過某個遺留系統中,一個大表中包含100多列的)。某種意義上也能避免“跨頁”的問題(MySQL、MSSQL底層都是通過“數據頁”來存儲的,“跨頁”問題可能會造成額外的性能開銷,拆分字段的操作建議在數據庫設計階段就做好。如果是在發展過程中拆分,則需要改寫以前的查詢語句,會額外帶來一定的成本和風險,建議謹慎。

垂直分庫在“微服務”盛行的今天已經非常普及了。基本的思路就是按照業務模塊來劃分出不同的數據庫,而不是像早期一樣將所有的數據表都放到同一個數據庫中。系統層面的“服務化”拆分操作,能夠解決業務系統層面的耦合和性能瓶頸,有利於系統的擴展維護。而數據庫層面的拆分,道理也是相通的。與服務的“治理”和“降級”機制類似,我們也能對不同業務類型的數據進行“分級”管理、維護、監控、擴展等。


眾所周知,數據庫往往最容易成為應用系統的瓶頸,而數據庫本身屬於“有狀態”的,相對於Web和應用服務器來講,是比較難實現“橫向擴展”的。數據庫的連接資源比較寶貴且單機處理能力也有限,在高併發場景下,垂直分庫一定程度上能夠突破IO、連接數及單機硬件資源的瓶頸,是大型分佈式系統中優化數據庫架構的重要手段。

然後,很多人並沒有從根本上搞清楚為什麼要拆分,也沒有掌握拆分的原則和技巧,只是一味的模仿大廠的做法。導致拆分後遇到很多問題(例如:跨庫join,分佈式事務等)。

水平分表也稱為橫向分表,比較容易理解,就是將表中不同的數據行按照一定規律分佈到不同的數據庫表中(這些表保存在同一個數據庫中),這樣來降低單表數據量,優化查詢性能。最常見的方式就是通過主鍵或者時間等字段進行Hash和取模後拆分。水平分表,能夠降低單表的數據量,一定程度上可以緩解查詢性能瓶頸。但本質上這些表還保存在同一個庫中,所以庫級別還是會有IO瓶頸。所以,一般不建議採用這種做法。

水平分庫分表與上面講到的水平分表的思想相同,唯一不同的就是將這些拆分出來的表保存在不同的數據中。這也是很多大型互聯網公司所選擇的做法。某種意義上來講,有些系統中使用的“冷熱數據分離”(將一些使用較少的歷史數據遷移到其他的數據庫中。而在業務功能上,通常默認只提供熱點數據的查詢),也是類似的實踐。在高併發和海量數據的場景下,分庫分表能夠有效緩解單機和單庫的性能瓶頸和壓力,突破IO、連接數、硬件資源的瓶頸。當然,投入的硬件成本也會更高。同時,這也會帶來一些複雜的技術問題和挑戰(例如:跨分片的複雜查詢,跨分片事務等)。

分佈式困境與應對之策

數據遷移與擴容問題

前面介紹到水平分表策略歸納總結為隨機分表和連續分表兩種情況。連續分表有可能存在數據熱點的問題,有些表可能會被頻繁地查詢從而造成較大壓力,熱數據的表就成為了整個庫的瓶頸,而有些表可能存的是歷史數據,很少需要被查詢到。連續分表的另外一個好處在於比較容易,不需要考慮遷移舊的數據,只需要添加分表就可以自動擴容。隨機分表的數據相對比較均勻,不容易出現熱點和併發訪問的瓶頸。但是,分表擴展需要遷移舊的數據。

如果想學習Java工程化、高性能及分佈式、深入淺出。微服務、Spring,MyBatis,Netty源碼分析、雙十一實戰或者是面試難題的朋友可以加582505643裡面的群主感覺蠢萌蠢萌的可以到她那騙資料,都是乾貨。

針對於水平分表的設計至關重要,需要評估中短期內業務的增長速度,對當前的數據量進行容量規劃,綜合成本因素,推算出大概需要多少分片。對於數據遷移的問題,一般做法是通過程序先讀出數據,然後按照指定的分表策略再將數據寫入到各個分表中。

表關聯問題

在單庫單表的情況下,聯合查詢是非常容易的。但是,隨著分庫與分表的演變,聯合查詢就遇到跨庫關聯和跨表關係問題。在設計之初就應該儘量避免聯合查詢,可以通過程序中進行拼裝,或者通過反範式化設計進行規避。

分頁與排序問題

一般情況下,列表分頁時需要按照指定字段進行排序。在單庫單表的情況下,分頁和排序也是非常容易的。但是,隨著分庫與分表的演變,也會遇到跨庫排序和跨表排序問題。為了最終結果的準確性,需要在不同的分表中將數據進行排序並返回,並將不同分表返回的結果集進行彙總和再次排序,最後再返回給用戶。

分佈式事務問題

隨著分庫與分表的演變,一定會遇到分佈式事務問題,那麼如何保證數據的一致性就成為一個必須面對的問題。目前,分佈式事務並沒有很好的解決方案,難以滿足數據強一致性,一般情況下,使存儲數據儘可能達到用戶一致,保證系統經過一段較短的時間的自我恢復和修正,數據最終達到一致。

分佈式全局唯一ID

在單庫單表的情況下,直接使用數據庫自增特性來生成主鍵ID,這樣確實比較簡單。在分庫分表的環境中,數據分佈在不同的分表上,不能再借助數據庫自增長特性。需要使用全局唯一 ID,例如 UUID、GUID等。

MySQL 遇到的死鎖問題

產生死鎖的四個必要條件:

(1) 互斥條件:一個資源每次只能被一個進程使用。

(2) 請求與保持條件:一個進程因請求資源而阻塞時,對已獲得的資源保持不放。

(3) 不剝奪條件:進程已獲得的資源,在末使用完之前,不能強行剝奪。

(4) 循環等待條件:若干進程之間形成一種頭尾相接的循環等待資源關係。

這四個條件是死鎖的必要條件,只要系統發生死鎖,這些條件必然成立,而只要上述條件之一不滿足,就不會發生死鎖。

下列方法有助於最大限度地降低死鎖:

(1)按同一順序訪問對象。

(2)避免事務中的用戶交互。

(3)保持事務簡短並在一個批處理中。

(4)使用低隔離級別。

(5)使用綁定連接。

數據庫索引的原理

數據庫索引,是數據庫管理系統中一個排序的數據結構,以協助快速查詢、更新數據庫表中數據。索引的實現通常使用B樹及其變種B+樹。

聚集索引與非聚集索引的區別

1).聚集索引一個表只能有一個,而非聚集索引一個表可以存在多個

2).聚集索引存儲記錄是物理上連續存在,而非聚集索引是邏輯上的連續,物理存儲並不連續

 3).聚集索引:物理存儲按照索引排序;聚集索引是一種索引組織形式,索引的鍵值邏輯順序決定了表數據行的物理存儲順序

 非聚集索引:物理存儲不按照索引排序;非聚集索引則就是普通索引了,僅僅只是對數據列創建相應的索引,不影響整個表的物理存儲順序.

4).索引是通過二叉樹的數據結構來描述的,我們可以這麼理解聚簇索引:索引的葉節點就是數據節點。而非聚簇索引的葉節點仍然是索引節點,只不過有一個指針指向對應的數據塊。

Redis 持久化機制和如何實現

redis有兩種持久化機制RDB與AOF。

RDB持久化方式會在一個特定的間隔保存那個時間點的一個數據快照。

AOF持久化方式則會記錄每一個服務器收到的寫操作。在服務啟動時,這些記錄的操作會逐條執行從而重建出原來的數據。寫操作命令記錄的格式跟Redis協議一致,以追加的方式進行保存。

Redis的持久化是可以禁用的,就是說你可以讓數據的生命週期只存在於服務器的運行時間裡。

兩種方式的持久化是可以同時存在的,但是當Redis重啟時,AOF文件會被優先用於重建數據。

緩存降級

頁面降級:在大促或者某些特殊情況下,某些頁面佔用了一些稀缺服務資源,在緊急情況下可以對其整個降級,以達到丟卒保帥;

頁面片段降級:比如商品詳情頁中的商家部分因為數據錯誤了,此時需要對其進行降級;

頁面異步請求降級:比如商品詳情頁上有推薦信息/配送至等異步加載的請求,如果這些信息響應慢或者後端服務有問題,可以進行降級;

服務功能降級:比如渲染商品詳情頁時需要調用一些不太重要的服務:相關分類、熱銷榜等,而這些服務在異常情況下直接不獲取,即降級即可;

讀降級:比如多級緩存模式,如果後端服務有問題,可以降級為只讀緩存,這種方式適用於對讀一致性要求不高的場景;如果想學習Java工程化、高性能及分佈式、深入淺出。微服務、Spring,MyBatis,Netty源碼分析、雙十一實戰或者是面試難題的朋友可以加582505643裡面的群主感覺蠢萌蠢萌的可以到她那騙資料,都是乾貨。

寫降級:比如秒殺搶購,我們可以只進行Cache的更新,然後異步同步扣減庫存到DB,保證最終一致性即可,此時可以將DB降級為Cache。

爬蟲降級:在大促活動時,可以將爬蟲流量導向靜態頁或者返回空數據,從而保護後端稀缺資源。

自動開關降級

自動降級是根據系統負載、資源使用情況、SLA等指標進行降級。

超時降級

當訪問的數據庫/http服務/遠程調用響應慢或者長時間響應慢,且該服務不是核心服務的話可以在超時後自動降級;比如商品詳情頁上有推薦內容/評價,但是推薦內容/評價暫時不展示對用戶購物流程不會產生很大的影響;對於這種服務是可以超時降級的。如果是調用別人的遠程服務,和對方定義一個服務響應最大時間,如果超時了則自動降級。

下面的截圖為視頻中的部分歸納思維圖

Java面試通關要點彙總集及參考答案(不吹不黑耿直福利)

Java面試通關要點彙總集及參考答案(不吹不黑耿直福利)

Java面試通關要點彙總集及參考答案(不吹不黑耿直福利)

Java面試通關要點彙總集及參考答案(不吹不黑耿直福利)

Java面試通關要點彙總集及參考答案(不吹不黑耿直福利)

Java面試通關要點彙總集及參考答案(不吹不黑耿直福利)

Java面試通關要點彙總集及參考答案(不吹不黑耿直福利)


分享到:


相關文章: