寫在前面:2020年面試必備的Java後端進階面試題總結了一份複習指南在Github上,內容詳細,圖文並茂,有須要學習的朋友能夠Star一下!
GitHub地址:https://github.com/abel-max/Java-Study-Note/tree/mastergit
分佈式系統(distributed system)正變得愈來愈重要,大型網站幾乎都是分佈式的。 分佈式系統的最大難點,就是各個節點的狀態如何同步。CAP 定理是這方面的基本定理,也是理解分佈式系統的起點。github
通常來說,在高併發狀況下,cap三者選其二,但實際上只有兩種選擇,一種爲cp,一種爲ap。面試
先看 Partition tolerance,中文叫作"分區容錯"。sql
系統若是不能在時限內達成數據一致性,意味着發生了分區的狀況,須要在C和A做選擇.數據庫
大多數分佈式系統都分佈在多個子網絡。每一個子網絡就叫作一個區(partition)。分區容錯的意思是,區間通訊可能失敗。好比,一臺服務器放在中國,另外一臺服務器放在美國,這就是兩個區,它們之間可能沒法通訊。後端
上圖中,G1 和 G2 是兩臺跨區的服務器。G1 向G2 發送一條消息,G2 可能沒法收到。系統設計的時候,必須考慮到這種狀況。緩存
通常來講,分區容錯沒法避免,所以能夠認爲 CAP 的 P 老是成立。CAP 定理告訴咱們,剩下的 C 和 A 沒法同時作到。服務器
Consistency中文叫作"一致性"。意思是,寫操做以後的讀操做,必須返回該值。舉例來講,某條記錄是 v0,用戶向 G1 發起一個寫操做,將其改成 v1。網絡
全部節點訪問同一份最新數據副本併發
接下來,用戶的讀操做就會獲得 v1。這就叫一致性。
問題是,用戶有可能向 G2 發起讀操做,因爲 G2 的值沒有發生變化,所以返回的是 v0。G1 和 G2 讀操做的結果不一致,這就不知足一致性了。
爲了讓 G2 也能變爲 v1,就要在 G1 寫操做的時候,讓 G1 向 G2 發送一條消息,要求G2 也改爲 v1。
這樣的話,用戶向 G2 發起讀操做,也能獲得 v1。
Availability中文叫作"可用性",意思是隻要收到用戶的請求,服務器就必須給出迴應。
對數據更新具有高可用性
用戶能夠選擇向 G1 或G2 發起讀操做。不論是哪臺服務器,只要收到請求,就必須告訴用戶,究竟是 v0 仍是 v1,不然就不知足可用性。
一致性和可用性,爲何不可能同時成立?答案很簡單,由於可能通訊失敗(即出現分區容錯)。
若是保證 G2 的一致性,那麼 G1 必須在寫操做時,鎖定 G2 的讀操做和寫操做。只有數據同步後,才能從新開放讀寫。鎖按期間,G2 不能讀寫,沒有可用性不。
若是保證 G2 的可用性,那麼勢必不能鎖定 G2,因此一致性不成立。
綜上所述,G2 沒法同時作到一致性和可用性。系統設計時只能選擇一個目標。若是追求一致性,那麼沒法保證全部節點的可用性;若是追求全部節點的可用性,那就無法作到一致性。
舉例來講,發佈一張網頁到 CDN,多個服務器有這張網頁的副本。後來發現一個錯誤,須要更新網頁,這時只能每一個服務器都更新一遍。
通常來講,網頁的更新不是特別強調一致性。短時期內,一些用戶拿到老版本,另外一些用戶拿到新版本,問題不會特別大。可是每一個用戶訪問之後,必須馬上有返回值,固然,全部人最終都會看到新版本。因此,這個場合就是可用性高於一致性。
目前看來,在分佈式系統中,p是基本會存在的,就是網絡間同步數據的延遲,而c也就是一致性保證的是特定時間內數據的一致性,就忽略了性能問題,而a也就是可用性,強調的是馬上返回結果,強調的是性能,那麼一定會出現數據不一致,根據不一樣的業務場景進行設計,要充分利用三者特性。