分散式面試題不用怕,帶你征服面試管

程式碼全靠copy發表於2018-03-26


  • 一、談談業務中使用分散式的場景

  • 二、分散式事務

  • 產生原因

  • 應用場景

  • 解決方案

  • 三、負載均衡的演算法與實現

  • 演算法

  • 實現

  • 四、分散式鎖

  • 使用場景

  • 實現方式

  • 五、分散式 Session

  • 1. 粘性 Session

  • 2. 伺服器 Session 複製

  • 3. Session 共享機制

  • 4. Session 持久化到資料庫

  • 5. Terracotta 實現 Session 複製

  • 六、分庫與分錶帶來的分散式困境與應對之策

  • 事務問題

  • 查詢問題

  • ID 唯一性

  • 參考資料

一、談談業務中使用分散式的場景

分散式主要是為了提供可擴充套件性以及高可用性,業務中使用分散式的場景主要有分散式儲存以及分散式計算。

分散式儲存中可以將資料分片到多個節點上,不僅可以提高效能(可擴充套件性),同時也可以使用多個節點對同一份資料進行備份。

至於分散式計算,就是將一個大的計算任務分解成小任務分配到多臺節點上去執行,再彙總每個小任務的執行結果得到最終結果。MapReduce 是分散式計算的最好例子。

二、分散式事務

指事務的操作位於不同的節點上,需要保證事務的 AICD 特性。

產生原因

  • 資料庫分庫分表;

  • SOA 架構,比如一個電商網站將訂單業務和庫存業務分離出來放到不同的節點上。

應用場景

  • 下單:減少庫存、更新訂單狀態。庫存和訂單不在不同一個資料庫,因此涉及分散式事務。

  • 支付:買家賬戶扣款、賣家賬戶入賬。買家和賣家賬戶資訊不在同一個資料庫,因此涉及分散式事務。

解決方案

1. 兩階段提交協議

兩階段提交

兩階段提交協議可以很好得解決分散式事務問題,它可以使用 XA 來實現,XA 它包含兩個部分:事務管理器和本地資源管理器。其中本地資源管理器往往由資料庫實現,比如 Oracle、DB2 這些商業資料庫都實現了 XA 介面;而事務管理器作為全域性的協調者,負責各個本地資源的提交和回滾。

2. 訊息中介軟體

訊息中介軟體也可稱作訊息系統 (MQ),它本質上是一個暫存轉發訊息的一箇中介軟體。在分散式應用當中,我們可以把一個業務操作轉換成一個訊息,比如支付寶的餘額轉入餘額寶操作,支付寶系統執行減少餘額操作之後向訊息系統傳送一個訊息,餘額寶系統訂閱這條訊息然後進行增加餘額寶操作。

(一)訊息處理模型

點對點

分散式面試題不用怕,帶你征服面試管

釋出/訂閱

分散式面試題不用怕,帶你征服面試管

(二)訊息的可靠性

訊息的傳送端的可靠性:傳送端完成操作後一定能將訊息成功傳送到訊息系統。

訊息的接收端的可靠性:接收端僅且能夠從訊息中介軟體成功消費一次訊息。

傳送端的可靠性

在本地資料建一張訊息表,將訊息資料與業務資料儲存在同一資料庫例項裡,這樣就可以利用本地資料庫的事務機制。事務提交成功後,將訊息表中的訊息轉移到訊息中介軟體,若轉移訊息成功則刪除訊息表中的資料,否則繼續重傳。

接收端的可靠性

保證接收端處理訊息的業務邏輯具有冪等性:只要具有冪等性,那麼消費多少次訊息,最後處理的結果都是一樣的。

保證訊息具有唯一編號,並使用一張日誌表來記錄已經消費的訊息編號。

三、負載均衡的演算法與實現

演算法

1. 輪詢(Round Robin)

輪詢演算法把每個請求輪流傳送到每個伺服器上。下圖中,一共有 6 個客戶端產生了 6 個請求,這 6 個請求按 (1, 2, 3, 4, 5, 6) 的順序傳送。最後,(1, 3, 5) 的請求會被髮送到伺服器 1,(2, 4, 6) 的請求會被髮送到伺服器 2。

分散式面試題不用怕,帶你征服面試管

該演算法比較適合每個伺服器的效能差不多的場景,如果有效能存在差異的情況下,那麼效能較差的伺服器可能無法承擔多大的負載。下圖中,伺服器 2 的效能比伺服器 1 差,那麼伺服器 2 可能無法承擔多大的負載。

分散式面試題不用怕,帶你征服面試管

2. 加權輪詢(Weighted Round Robbin)

加權輪詢是在輪詢的基礎上,根據伺服器的效能差異,為伺服器賦予一定的權值。例如下圖中,伺服器 1 被賦予的權值為 5,伺服器 2 被賦予的權值為 1,那麼 (1, 2, 3, 4, 5) 請求會被髮送到伺服器 1,(6) 請求會被髮送到伺服器 2。

分散式面試題不用怕,帶你征服面試管

3. 最少連線(least Connections)

由於每個請求的連線時間不一樣,使用輪詢或者加權輪詢演算法的話,可能會讓一臺伺服器當前連線數多大,而另一臺伺服器的連線多小,造成負載不均衡。例如下圖中,(1, 3, 5) 請求會被髮送到伺服器 1,但是 (1, 3) 很快就斷開連線,此時只有 (5) 請求連線伺服器 1;(2, 4, 6) 請求被髮送到伺服器 2,只有 (2) 的連線斷開。該系統繼續執行時,伺服器 2 會承擔多大的負載。

分散式面試題不用怕,帶你征服面試管

最少連線演算法就是將請求傳送給當前最少連線數的伺服器上。例如下圖中,伺服器 1 當前連線數最小,那麼新到來的請求 6 就會被髮送到伺服器 1 上。

分散式面試題不用怕,帶你征服面試管

4. 加權最小連線(Weighted Least Connection)

在最小連線的基礎上,根據伺服器的效能為每臺伺服器分配權重,根據權重計算出每臺伺服器能處理的連線數。

分散式面試題不用怕,帶你征服面試管

5. 隨機演算法(Random)

把請求隨機傳送到伺服器上。和輪詢演算法類似,該演算法比較適合伺服器效能差不多的場景。

分散式面試題不用怕,帶你征服面試管

實現

1. DNS 解析

使用 DNS 作為負載均衡器,根據負載情況返回不同伺服器的 IP 地址。大型網站基本使用了這種方式最為第一級負載均衡手段,然後在內部使用其它方式做第二級負載均衡。

分散式面試題不用怕,帶你征服面試管

2. 修改 MAC 地址

使用 LVS(Linux Virtual Server)這種鏈路層負載均衡器,根據負載情況修改請求的 MAC 地址。

分散式面試題不用怕,帶你征服面試管

3. 修改 IP 地址

在網路層修改請求的目的 IP 地址。

分散式面試題不用怕,帶你征服面試管

4. HTTP 重定向

HTTP 重定向負載均衡伺服器收到 HTTP 請求之後會返回伺服器的地址,並將該地址寫入 HTTP 重定向響應中返回給瀏覽器,瀏覽器收到後需要再次傳送請求。

分散式面試題不用怕,帶你征服面試管

5. 反向代理

正向代理:發生在客戶端,是由使用者主動發起的。比如翻牆,客戶端通過主動訪問代理伺服器,讓代理伺服器獲得需要的外網資料,然後轉發回客戶端。

反向代理:發生在伺服器端,使用者不知道代理的存在。

分散式面試題不用怕,帶你征服面試管

四、分散式鎖

Java 提供了兩種內建的鎖的實現,一種是由 JVM 實現的 synchronized 和 JDK 提供的 Lock,當你的應用是單機或者說單程式應用時,可以使用 synchronized 或 Lock 來實現鎖。當應用涉及到多機、多程式共同完成時,那麼這時候就需要一個全域性鎖來實現多個程式之間的同步。

使用場景

例如一個應用有手機 APP 端和 Web 端,如果在兩個客戶端同時進行一項操作時,那麼就會導致這項操作重複進行。

實現方式

1. 資料庫分散式鎖

(一)基於 MySQL 鎖表

該實現方式完全依靠資料庫唯一索引來實現。當想要獲得鎖時,就向資料庫中插入一條記錄,釋放鎖時就刪除這條記錄。如果記錄具有唯一索引,就不會同時插入同一條記錄。這種方式存在以下幾個問題:

  1. 鎖沒有失效時間,解鎖失敗會導致死鎖,其他執行緒無法再獲得鎖。

  2. 只能是非阻塞鎖,插入失敗直接就報錯了,無法重試。

  3. 不可重入,同一執行緒在沒有釋放鎖之前無法再獲得鎖。

(二)採用樂觀鎖增加版本號

根據版本號來判斷更新之前有沒有其他執行緒更新過,如果被更新過,則獲取鎖失敗。

2. Redis 分散式鎖

(一)基於 SETNX、EXPIRE

使用 SETNX(set if not exist)命令插入一個鍵值對時,如果 Key 已經存在,那麼會返回 False,否則插入成功並返回 True。因此客戶端在嘗試獲得鎖時,先使用 SETNX 向 Redis 中插入一個記錄,如果返回 True 表示獲得鎖,返回 False 表示已經有客戶端佔用鎖。

EXPIRE 可以為一個鍵值對設定一個過期時間,從而避免了死鎖的發生。

(二)RedLock 演算法

ReadLock 演算法使用了多個 Redis 例項來實現分散式鎖,這是為了保證在發生單點故障時還可用。

  1. 嘗試從 N 個相互獨立 Redis 例項獲取鎖,如果一個例項不可用,應該儘快嘗試下一個。

  2. 計算獲取鎖消耗的時間,只有當這個時間小於鎖的過期時間,並且從大多數(N/2+1)例項上獲取了鎖,那麼就認為鎖獲取成功了。

  3. 如果鎖獲取失敗,會到每個例項上釋放鎖。

3. Zookeeper 分散式鎖

Zookeeper 是一個為分散式應用提供一致性服務的軟體,例如配置管理、分散式協同以及命名的中心化等,這些都是分散式系統中非常底層而且是必不可少的基本功能,但是如果自己實現這些功能而且要達到高吞吐、低延遲同時還要保持一致性和可用性,實際上非常困難。

(一)抽象模型

Zookeeper 提供了一種樹形結構級的名稱空間,/app1/p_1 節點表示它的父節點為 /app1。

分散式面試題不用怕,帶你征服面試管

(二)節點型別

  • 永久節點:不會因為會話結束或者超時而消失;

  • 臨時節點:如果會話結束或者超時就會消失;

  • 有序節點:會在節點名的後面加一個數字字尾,並且是有序的,例如生成的有序節點為 /lock/node-0000000000,它的下一個有序節點則為 /lock/node-0000000001,依次類推。

(三)監聽器

為一個節點註冊監聽器,在節點狀態發生改變時,會給客戶端傳送訊息。

(四)分散式鎖實現

  1. 建立一個鎖目錄 /lock。

  2. 在 /lock 下建立臨時的且有序的子節點,第一個客戶端對應的子節點為 /lock/lock-0000000000,第二個為 /lock/lock-0000000001,以此類推。

  3. 客戶端獲取 /lock 下的子節點列表,判斷自己建立的子節點是否為當前子節點列表中序號最小的子節點,如果是則認為獲得鎖,否則監聽自己的前一個子節點,獲得子節點的變更通知後重復此步驟直至獲得鎖;

  4. 執行業務程式碼,完成後,刪除對應的子節點。

(五)會話超時

如果一個已經獲得鎖的會話超時了,因為建立的是臨時節點,因此該會話對應的臨時節點會被刪除,其它會話就可以獲得鎖了。可以看到,Zookeeper 分散式鎖不會出現資料庫分散式鎖的死鎖問題。

(六)羊群效應

在步驟二,一個節點未獲得鎖,需要監聽監聽自己的前一個子節點,這是因為如果監聽所有的子節點,那麼任意一個子節點狀態改變,其它所有子節點都會收到通知,而我們只希望它的下一個子節點收到通知。

五、分散式 Session

如果不做任何處理的話,使用者將出現頻繁登入的現象,比如叢集中存在 A、B 兩臺伺服器,使用者在第一次訪問網站時,Nginx 通過其負載均衡機制將使用者請求轉發到 A 伺服器,這時 A 伺服器就會給使用者建立一個 Session。當使用者第二次傳送請求時,Nginx 將其負載均衡到 B 伺服器,而這時候 B 伺服器並不存在 Session,所以就會將使用者踢到登入頁面。這將大大降低使用者體驗度,導致使用者的流失,這種情況是專案絕不應該出現的。

1. 粘性 Session

原理

粘性 Session 是指將使用者鎖定到某一個伺服器上,比如上面說的例子,使用者第一次請求時,負載均衡器將使用者的請求轉發到了 A 伺服器上,如果負載均衡器設定了粘性 Session 的話,那麼使用者以後的每次請求都會轉發到 A 伺服器上,相當於把使用者和 A 伺服器粘到了一塊,這就是粘性 Session 機制。

優點

簡單,不需要對 Session 做任何處理。

缺點

缺乏容錯性,如果當前訪問的伺服器發生故障,使用者被轉移到第二個伺服器上時,他的 Session 資訊都將失效。

適用場景

  • 發生故障對客戶產生的影響較小;

  • 伺服器發生故障是低概率事件。

2. 伺服器 Session 複製

原理

任何一個伺服器上的 Session 發生改變,該節點會把這個 Session 的所有內容序列化,然後廣播給所有其它節點,不管其他伺服器需不需要 Session,以此來保證 Session 同步。

優點

可容錯,各個伺服器間 Session 能夠實時響應。

缺點

會對網路負荷造成一定壓力,如果 Session 量大的話可能會造成網路堵塞,拖慢伺服器效能。

實現方式

  1. 設定 Tomcat 的 server.xml 開啟 tomcat 叢集功能。

  2. 在應用裡增加資訊:通知應用當前處於叢集環境中,支援分散式,即在 web.xml 中新增<distributable/> 選項。

3. Session 共享機制

使用分散式快取方案比如 Memcached、Redis,但是要求 Memcached 或 Redis 必須是叢集。

使用 Session 共享也分兩種機制,兩種情況如下:

3.1 粘性 Session 共享機制

和粘性 Session 一樣,一個使用者的 Session 會繫結到一個 Tomcat 上。Memcached 只是起到備份作用。

分散式面試題不用怕,帶你征服面試管

3.2 非粘性 Session 共享機制

原理

Tomcat 本身不儲存 Session,而是存入 Memcached 中。Memcached 叢集構建主從複製架構。

分散式面試題不用怕,帶你征服面試管

優點

可容錯,Session 實時響應。

實現方式

用開源的 msm 外掛解決 Tomcat 之間的 Session 共享:Memcached_Session_Manager(MSM)

4. Session 持久化到資料庫

原理

拿出一個資料庫,專門用來儲存 Session 資訊。保證 Session 的持久化。

優點

伺服器出現問題,Session 不會丟失

缺點

如果網站的訪問量很大,把 Session 儲存到資料庫中,會對資料庫造成很大壓力,還需要增加額外的開銷維護資料庫。

5. Terracotta 實現 Session 複製

原理

Terracotta 的基本原理是對於叢集間共享的資料,當在一個節點發生變化的時候,Terracotta 只把變化的部分傳送給 Terracotta 伺服器,然後由伺服器把它轉發給真正需要這個資料的節點。它是伺服器 Session 複製的優化。

分散式面試題不用怕,帶你征服面試管

優點

這樣對網路的壓力就非常小,各個節點也不必浪費 CPU 時間和記憶體進行大量的序列化操作。把這種叢集間資料共享的機制應用在 Session 同步上,既避免了對資料庫的依賴,又能達到負載均衡和災難恢復的效果。

六、分庫與分錶帶來的分散式困境與應對之策

分散式面試題不用怕,帶你征服面試管

事務問題

使用分散式事務。

查詢問題

使用匯總表。

ID 唯一性

  • 使用全域性唯一 ID:GUID;

  • 為每個分片指定一個 ID 範圍。

如果你也想在IT行業拿高薪,可以參加我們的訓練營課程,選擇最適合自己的課程學習,技術大牛親授,7個月後,進入名企拿高薪。我們的課程內容有:Java工程化、高效能及分散式、高效能、深入淺出。高架構。效能調優、Spring,MyBatis,Netty原始碼分析和大資料等多個知識點。如果你想拿高薪的,想學習的,想就業前景好的,想跟別人競爭能取得優勢的,想進阿里面試但擔心面試不過的,你都可以來,群號為: 454377428

注:加群要求

1、具有1-5工作經驗的,面對目前流行的技術不知從何下手,需要突破技術瓶頸的可以加。

2、在公司待久了,過得很安逸,但跳槽時面試碰壁。需要在短時間內進修、跳槽拿高薪的可以加。

3、如果沒有工作經驗,但基礎非常紮實,對java工作機制,常用設計思想,常用java開發框架掌握熟練的,可以加。

4、覺得自己很牛B,一般需求都能搞定。但是所學的知識點沒有系統化,很難在技術領域繼續突破的可以加。

5.阿里Java高階大牛直播講解知識點,分享知識,多年工作經驗的梳理和總結,帶著大家全面、科學地建立自己的技術體系和技術認知!

6.小號或者小白之類加群一律不給過,謝謝。

目標已經有了,下面就看行動了!記住:學習永遠是自己的事情,你不學時間也不會多,你學了有時候卻能夠使用自己學到的知識換得更多自由自在的美好時光!時間是生命的基本組成部分,也是萬物存在的根本尺度,我們的時間在那裡我們的生活就在那裡!我們價值也將在那裡提升或消弭!Java程式設計師,加油吧


相關文章