Java面試題精選,大型網站系統架構你不得不懂的10個問題

李紅歐巴發表於2019-02-28

作者:JavaGuide(公眾號)

下面這些問題都是一線大廠的真實面試問題,不論是對你面試還是說拓寬知識面都很有幫助。之前發過一篇8 張圖讀懂大型網站技術架構 可以作為不太瞭解大型網站系統技術架構朋友的入門文章。

文章目錄
1. 你使用過哪些元件或者方法來提升網站效能,可用性以及併發量
2. 設計高可用系統的常用手段
3. 現代網際網路應用系統通常具有哪些特點?
4. 談談你對微服務領域的瞭解和認識
5. 談談你對 Dubbo 和 Spring Cloud 的認識(兩者關係)
6. 效能測試瞭解嗎?說說你知道的效能測試工具?
7. 對於一個單體應用系統,隨著產品使用的使用者越來越多,網站的流量會增加,最終單臺伺服器無法處理那麼大的流量怎麼辦?
8. 大表優化的常見手段
9. 在系統中使用訊息佇列能帶來什麼好處?
1) 通過非同步處理提高系統效能
2) 降低系統耦合性
10. 說說自己對 CAP 定理,BASE 理論的瞭解
CAP 定理
BASE 理論


1. 你使用過哪些元件或者方法來提升網站效能,可用性以及併發量

  1. 提高硬體能力、增加系統伺服器。(當伺服器增加到某個程度的時候系統所能提供的併發訪問量幾乎不變,所以不能根本解決問題)
  2. 使用快取(本地快取:本地可以使用JDK自帶的 Map、Guava Cache.分散式快取:Redis、Memcache.本地快取不適用於提高系統併發量,一般是用處用在程式中。比如Spring是如何實現單例的呢?大家如果看過原始碼的話,應該知道,Spiring把已經初始過的變數放在一個Map中,下次再要使用這個變數的時候,先判斷Map中有沒有,這也就是系統中常見的單例模式的實現。)
  3. 訊息佇列 (解耦+削峰+非同步)
  4. .採用分散式開發 (不同的服務部署在不同的機器節點上,並且一個服務也可以部署在多臺機器上,然後利用 Nginx 負載均衡訪問。這樣就解決了單點部署(All In)的缺點,大大提高的系統併發量)
  5. 資料庫分庫(讀寫分離)、分表(水平分表、垂直分表)
  6. 採用叢集 (多臺機器提供相同的服務)
  7. 7.CDN 加速 (將一些靜態資源比如圖片、視訊等等快取到離使用者最近的網路節點)
  8. 8.瀏覽器快取
  9. 9.使用合適的連線池(資料庫連線池、執行緒池等等)
  10. 適當使用多執行緒進行開發。


2. 設計高可用系統的常用手段

  1. 降級: 服務降級是當伺服器壓力劇增的情況下,根據當前業務情況及流量對一些服務和頁面有策略的降級,以此釋放伺服器資源以保證核心任務的正常執行。降級往往會指定不同的級別,面臨不同的異常等級執行不同的處理。根據服務方式:可以拒接服務,可以延遲服務,也有時候可以隨機服務。根據服務範圍:可以砍掉某個功能,也可以砍掉某些模組。總之服務降級需要根據不同的業務需求採用不同的降級策略。主要的目的就是服務雖然有損但是總比沒有好;
  2. 限流: 防止惡意請求流量、惡意攻擊,或者防止流量超出系統峰值;
  3. 快取: 避免大量請求直接落到資料庫,將資料庫擊垮;
  4. 超時和重試機制: 避免請求堆積造成雪崩;
  5. 回滾機制: 快速修復錯誤版本。


3. 現代網際網路應用系統通常具有哪些特點?

  1. 高併發,大流量;
  2. 高可用:系統7×24小時不間斷服務;
  3. 海量資料:需要儲存、管理海量資料,需要使用大量伺服器;
  4. 使用者分佈廣泛,網路情況複雜:許多大型網際網路都是為全球使用者提供服務的,使用者分佈範圍廣,各地網路情況千差萬別;
  5. 安全環境惡劣:由於網際網路的開放性,使得網際網路更容易受到攻擊,大型網站幾乎每天都會被黑客攻擊;
  6. 需求快速變更,釋出頻繁:和傳統軟體的版本釋出頻率不同,網際網路產品為快速適應市場,滿足使用者需求,其產品釋出頻率是極高的;
  7. 漸進式發展:與傳統軟體產品或企業應用系統一開始就規劃好全部的功能和非功能需求不同,幾乎所有的大型網際網路網站都是從一個小網站開始,漸進地發展起來。

4. 談談你對微服務領域的瞭解和認識
現在大公司都在用並且未來的趨勢都是 Spring Cloud,而阿里開源的 Spring Cloud Alibaba 也是 Spring Cloud 規範的實現 。

我們通常把 Spring Cloud 理解為一系列開源元件的集合,但是 Spring Cloud並不是等同於 Spring Cloud Netflix 的 Ribbon、Feign、Eureka(停止更新)、Hystrix 這一套元件,而是抽象了一套通用的開發模式。它的目的是通過抽象出這套通用的模式,讓開發者更快更好地開發業務。但是這套開發模式執行時的實際載體,還是依賴於 RPC、閘道器、服務發現、配置管理、限流熔斷、分散式鏈路跟蹤等元件的具體實現。

Spring Cloud Alibaba 是官方認證的新一套 Spring Cloud 規範的實現,Spring Cloud Alibaba 是一套國產開源產品集合,後續還會有中文 reference 和一些原理分析文章,所以,這對於國內的開發者是非常棒的一件事。阿里的這一舉動勢必會推動國內微服務技術的發展,因為在沒有 Spring Cloud Alibaba 之前,我們的第一選擇是 Spring Cloud Netflix,但是它們的文件都是英文的,出問題後排查也比較困難, 在國內並不是有特別多的人精通。Spring Cloud Alibaba 由阿里開源元件和阿里雲產品元件兩部分組成,其致力於提供微服務一站式解決方案,方便開發者通過 Spring Cloud 程式設計模型輕鬆開發微服務應用。

另外,Apache Dubbo Ecosystem 是圍繞 Apache Dubbo 打造的微服務生態,是經過生產驗證的微服務的最佳實踐組合。在阿里巴巴的微服務解決方案中,Dubbo、Nacos 和 Sentinel,以及後續將開源的微服務元件,都是 Dubbo EcoSystem 的一部分。阿里後續也會將 Dubbo EcoSystem 整合到 Spring Cloud 的生態中。

5. 談談你對 Dubbo 和 Spring Cloud 的認識(兩者關係)
具體可以看公眾號-阿里巴巴中介軟體的這篇文章:獨家解讀:Dubbo Ecosystem - 從微服務框架到微服務生態

Dubbo 與 Spring Cloud 並不是競爭關係,Dubbo 作為成熟的 RPC 框架,其易用性、擴充套件性和健壯性已得到業界的認可。未來 Dubbo 將會作為 Spring Cloud Alibaba 的 RPC 元件,並與 Spring Cloud 原生的 Feign 以及 RestTemplate 進行無縫整合,實現“零”成本遷移。

在阿里巴巴的微服務解決方案中,Dubbo、Nacos 和 Sentinel,以及後續將開源的微服務元件,都是 Dubbo EcoSystem 的一部分。我們後續也會將 Dubbo EcoSystem 整合到 Spring Cloud 的生態中。

6. 效能測試瞭解嗎?說說你知道的效能測試工具?
效能測試指通過自動化的測試工具模擬多種正常、峰值以及異常負載條件來對系統的各項效能指標進行測試。效能測試是總稱,通常細分為:

  1. 基準測試: 在給系統施加較低壓力時,檢視系統的執行狀況並記錄相關數做為基礎參考
  2. **負載測試:**是指對系統不斷地增加壓力或增加一定壓力下的持續時間,直到系統的某項或多項效能指標達到安全臨界值,例如某種資源已經達到飽和狀態等 。此時繼續加壓,系統處理能力會下降。
  3. 壓力測試: 超過安全負載情況下,不斷施加壓力(增加併發請求),直到系統崩潰或無法處理任何請求,依此獲得系統最大壓力承受能力。
  4. 穩定性測試: 被測試系統在特定硬體、軟體、網路環境下,載入一定業務壓力(模擬生產環境不同時間點、不均勻請求,呈波浪特性)執行一段較長時間,以此檢測系統是否穩定。

後端程式設計師或者測試平常比較常用的測試工具是 JMeter(官網:https://jmeter.apache.org/)。Apache JMeter 是一款基於Java的壓力測試工具(100%純Java應用程式),旨在載入測試功能行為和測量效能。它最初被設計用於 Web 應用測試但後來擴充套件到其他測試領域。

7. 對於一個單體應用系統,隨著產品使用的使用者越來越多,網站的流量會增加,最終單臺伺服器無法處理那麼大的流量怎麼辦?
這個時候就要考慮擴容了。《億級流量網站架構核心技術》這本書上面介紹到我們可以考慮下面幾步來解決這個問題:

  • 第一步,可以考慮簡單的擴容來解決問題。比如增加系統的伺服器,提高硬體能力等等。
  • 第二步,如果簡單擴容搞不定,就需要水平拆分和垂直拆分資料/應用來提升系統的伸縮性,即通過擴容提升系統負載能力。
  • 第三步,如果通過水平拆分/垂直拆分還是搞不定,那就需要根據現有系統特性,架構層面進行重構甚至是重新設計,即推倒重來。


對於系統設計,理想的情況下應支援線性擴容和彈性擴容,即在系統瓶頸時,只需要增加機器就可以解決系統瓶頸,如降低延遲提升吞吐量,從而實現擴容需求。

如果你想擴容,則支援水平/垂直伸縮是前提。在進行拆分時,一定要清楚知道自己的目的是什麼,拆分後帶來的問題如何解決,拆分後如果沒有得到任何收益就不要為了
拆而拆,即不要過度拆分,要適合自己的業務。

8. 大表優化的常見手段
當MySQL單表記錄數過大時,資料庫的CRUD效能會明顯下降,一些常見的優化措施如下:

  1. 限定資料的範圍: 務必禁止不帶任何限制資料範圍條件的查詢語句。比如:我們當使用者在查詢訂單歷史的時候,我們可以控制在一個月的範圍內。;
  2. 讀/寫分離: 經典的資料庫拆分方案,主庫負責寫,從庫負責讀;
  3. 垂直分割槽: 根據資料庫裡面資料表的相關性進行拆分。 例如,使用者表中既有使用者的登入資訊又有使用者的基本資訊,可以將使用者表拆分成兩個單獨的表,甚至放到單獨的庫做分庫。簡單來說垂直拆分是指資料表列的拆分,把一張列比較多的表拆分為多張表。 如下圖所示,這樣來說大家應該就更容易理解了。

垂直拆分的優點: 可以使得行資料變小,在查詢時減少讀取的Block數,減少I/O次數。此外,垂直分割槽可以簡化表的結構,易於維護。

垂直拆分的缺點: 主鍵會出現冗餘,需要管理冗餘列,並會引起Join操作,可以通過在應用層進行Join來解決。此外,垂直分割槽會讓事務變得更加複雜;

  1. 水平分割槽: 保持資料表結構不變,通過某種策略儲存資料分片。這樣每一片資料分散到不同的表或者庫中,達到了分散式的目的。 水平拆分可以支撐非常大的資料量。 水平拆分是指資料錶行的拆分,表的行數超過200萬行時,就會變慢,這時可以把一張的表的資料拆成多張表來存放。舉個例子:我們可以將使用者資訊表拆分成多個使用者資訊表,這樣就可以避免單一表資料量過大對效能造成影響。

水平拆分可以支援非常大的資料量。需要注意的一點是:分表僅僅是解決了單一表資料過大的問題,但由於表的資料還是在同一臺機器上,其實對於提升MySQL併發能力沒有什麼意義,所以 水平拆分最好分庫 。水平拆分能夠 支援非常大的資料量儲存,應用端改造也少,但 分片事務難以解決 ,跨界點Join效能較差,邏輯複雜。《Java工程師修煉之道》的作者推薦 儘量不要對資料進行分片,因為拆分會帶來邏輯、部署、運維的各種複雜度 ,一般的資料表在優化得當的情況下支撐千萬以下的資料量是沒有太大問題的。如果實在要分片,儘量選擇客戶端分片架構,這樣可以減少一次和中介軟體的網路I/O。

下面補充一下資料庫分片的兩種常見方案:

  • 客戶端代理: 分片邏輯在應用端,封裝在jar包中,通過修改或者封裝JDBC層來實現。 噹噹網的 Sharding-JDBC 、阿里的TDDL是兩種比較常用的實現。
  • 中介軟體代理: 在應用和資料中間加了一個代理層。分片邏輯統一維護在中介軟體服務中。 我們現在談的 Mycat 、360的Atlas、網易的DDB等等都是這種架構的實現。

9. 在系統中使用訊息佇列能帶來什麼好處?
《大型網站技術架構》第四章和第七章均有提到訊息佇列對應用效能及擴充套件性的提升。

  1. 通過非同步處理提高系統效能

如上圖,在不使用訊息佇列伺服器的時候,使用者的請求資料直接寫入資料庫,在高併發的情況下資料庫壓力劇增,使得響應速度變慢。但是在使用訊息佇列之後,使用者的請求資料傳送給訊息佇列之後立即 返回,再由訊息佇列的消費者程式從訊息佇列中獲取資料,非同步寫入資料庫。由於訊息佇列伺服器處理速度快於資料庫(訊息佇列也比資料庫有更好的伸縮性),因此響應速度得到大幅改善。

通過以上分析我們可以得出訊息佇列具有很好的削峰作用的功能——即通過非同步處理,將短時間高併發產生的事務訊息儲存在訊息佇列中,從而削平高峰期的併發事務。 舉例:在電子商務一些秒殺、促銷活動中,合理使用訊息佇列可以有效抵禦促銷活動剛開始大量訂單湧入對系統的衝擊。如下圖所示:

因為使用者請求資料寫入訊息佇列之後就立即返回給使用者了,但是請求資料在後續的業務校驗、寫資料庫等操作中可能失敗。因此使用訊息佇列進行非同步處理之後,需要適當修改業務流程進行配合,比如使用者在提交訂單之後,訂單資料寫入訊息佇列,不能立即返回使用者訂單提交成功,需要在訊息佇列的訂單消費者程式真正處理完該訂單之後,甚至出庫後,再通過電子郵件或簡訊通知使用者訂單成功,以免交易糾紛。這就類似我們平時手機訂火車票和電影票。

2.降低系統耦合性

我們知道模組分散式部署以後聚合方式通常有兩種:1.分散式訊息佇列和2.分散式服務。

先來簡單說一下分散式服務:

目前使用比較多的用來構建SOA(Service Oriented Architecture面向服務體系結構)的分散式服務框架是阿里巴巴開源的Dubbo.如果想深入瞭解Dubbo的可以看我寫的關於Dubbo的這一篇文章:《高效能優秀的服務框架-dubbo介紹》:https://juejin.im/post/5acadeb1f265da2375072f9c

再來談我們的分散式訊息佇列:

我們知道如果模組之間不存在直接呼叫,那麼新增模組或者修改模組就對其他模組影響較小,這樣系統的可擴充套件性無疑更好一些。

我們最常見的事件驅動架構類似生產者消費者模式,在大型網站中通常用利用訊息佇列實現事件驅動結構。如下圖所示:

訊息佇列使利用釋出-訂閱模式工作,訊息傳送者(生產者)釋出訊息,一個或多個訊息接受者(消費者)訂閱訊息。 從上圖可以看到訊息傳送者(生產者)和訊息接受者(消費者)之間沒有直接耦合,訊息傳送者將訊息傳送至分散式訊息佇列即結束對訊息的處理,訊息接受者從分散式訊息佇列獲取該訊息後進行後續處理,並不需要知道該訊息從何而來。對新增業務,只要對該類訊息感興趣,即可訂閱該訊息,對原有系統和業務沒有任何影響,從而實現網站業務的可擴充套件性設計。

訊息接受者對訊息進行過濾、處理、包裝後,構造成一個新的訊息型別,將訊息繼續傳送出去,等待其他訊息接受者訂閱該訊息。因此基於事件(訊息物件)驅動的業務架構可以是一系列流程。

另外為了避免訊息佇列伺服器當機造成訊息丟失,會將成功傳送到訊息佇列的訊息儲存在訊息生產者伺服器上,等訊息真正被消費者伺服器處理後才刪除訊息。在訊息佇列伺服器當機後,生產者伺服器會選擇分散式訊息佇列伺服器叢集中的其他伺服器釋出訊息。

備註: 不要認為訊息佇列只能利用釋出-訂閱模式工作,只不過在解耦這個特定業務環境下是使用釋出-訂閱模式的,比如在我們的ActiveMQ訊息佇列中還有點對點工作模式,具體的會在後面的文章給大家詳細介紹,這一篇文章主要還是讓大家對訊息佇列有一個更透徹的瞭解。

這個問題一般會在上一個問題問完之後,緊接著被問到。“使用訊息佇列會帶來什

麼問題?”這個問題要引起重視,一般我們都會考慮使用訊息佇列會帶來的好處而忽略它帶來的問題!

10. 說說自己對 CAP 定理,BASE 理論的瞭解
CAP 定理

在理論電腦科學中,CAP定理(CAP theorem),又被稱作布魯爾定理(Brewer’s theorem),它指出對於一個分散式計算系統來說,不可能同時滿足以下三點:

  • 一致性(Consistence) :所有節點訪問同一份最新的資料副本
  • 可用性(Availability):每次請求都能獲取到非錯的響應——但是不保證獲取的資料為最新資料
  • 分割槽容錯性(Partition tolerance) : 分散式系統在遇到某節點或網路分割槽故障的時候,仍然能夠對外提供滿足一致性和可用性的服務。

CAP僅適用於原子讀寫的NOSQL場景中,並不適合資料庫系統。現在的分散式系統具有更多特性比如擴充套件性、可用性等等,在進行系統設計和開發時,我們不應該僅僅侷限在CAP問題上。

注意:不是所謂的3選2(不要被網上大多數文章誤導了):

大部分人解釋這一定律時,常常簡單的表述為:“一致性、可用性、分割槽容忍性三者你只能同時達到其中兩個,不可能同時達到”。實際上這是一個非常具有誤導性質的說法,而且在CAP理論誕生12年之後,CAP之父也在2012年重寫了之前的論文。

當發生網路分割槽的時候,如果我們要繼續服務,那麼強一致性和可用性只能2選1。也就是說當網路分割槽之後P是前提,決定了P之後才有C和A的選擇。也就是說分割槽容錯性(Partition tolerance)我們是必須要實現的。

我在網上找了很多文章想看一下有沒有文章提到這個不是所謂的3選2,用百度半天沒找到了一篇,用谷歌搜尋找到一篇比較不錯的,如果想深入學習一下CAP就看這篇文章把,我這裡就不多BB了:《分散式系統之CAP理論》 : http://www.cnblogs.com/hxsyl/p/4381980.html

BASE 理論
BASE 是 Basically Available(基本可用) 、Soft-state(軟狀態) 和 Eventually Consistent(最終一致性) 三個短語的縮寫。BASE理論是對CAP中一致性和可用性權衡的結果,其來源於對大規模網際網路系統分散式實踐的總結,是基於CAP定理逐步演化而來的,它大大降低了我們對系統的要求。

BASE理論的核心思想: 即使無法做到強一致性,但每個應用都可以根據自身業務特點,採用適當的方式來使系統達到最終一致性。也就是犧牲資料的一致性來滿足系統的高可用性,系統中一部分資料不可用或者不一致時,仍需要保持系統整體“主要可用”。

BASE理論三要素:


  1. 基本可用: 基本可用是指分散式系統在出現不可預知故障的時候,允許損失部分可用性。但是,這絕不等價於系統不可用。 比如: ①響應時間上的損失:正常情況下,一個線上搜尋引擎需要在0.5秒之內返回給使用者相應的查詢結果,但由於出現故障,查詢結果的響應時間增加了1~2秒;②系統功能上的損失:正常情況下,在一個電子商務網站上進行購物的時候,消費者幾乎能夠順利完成每一筆訂單,但是在一些節日大促購物高峰的時候,由於消費者的購物行為激增,為了保護購物系統的穩定性,部分消費者可能會被引導到一個降級頁面;
  2. 軟狀態: 軟狀態指允許系統中的資料存在中間狀態,並認為該中間狀態的存在不會影響系統的整體可用性,即允許系統在不同節點的資料副本之間進行資料同步的過程存在延時;
  3. 最終一致性: 最終一致性強調的是系統中所有的資料副本,在經過一段時間的同步後,最終能夠達到一個一致的狀態。因此,最終一致性的本質是需要系統保證最終資料能夠達到一致,而不需要實時保證系統資料的強一致性。

免費Java資料領取,涵蓋了Java、Redis、MongoDB、MySQL、Zookeeper、Spring Cloud、Dubbo/Kafka、Hadoop、Hbase、Flink等高併發分散式、大資料、機器學習等技術。
傳送門:mp.weixin.qq.com/s/JzddfH-7y…


相關文章