1. 程式人生 > >【分布式系統設計】基礎概念

【分布式系統設計】基礎概念

由於 數量 width 工作 提供服務 height imp alt 應該

在設計分布式系統時,通常要考慮到 數據的一致性(consistency)系統的可用性(availability)、以及分區容忍性( partition tolerance)。即CAP定理。

概念

我們知道,分布式系統有多個節點。 數據一致性是指, 對每個節點,在同一時刻,讀寫的數據是相同的。 舉例:用戶User1的賬戶余額是100,在節點Node1我們更改了User1的賬戶余額,改成了200,此時在節點Node1讀User1余額一定是200。如果保證了一致性,那麽 在節點Node2、Node3等其他節點,讀到User1的余額都是200。 系統的可用性:即使分布式系統中的一個節點掛掉了,對於請求,依然能夠響應。 分區容忍性:
即使系統中出現了 一個節點與其他節點無法通信的情況,系統依然能夠工作。 舉例:分布式系統中兩節點間無法傳遞數據或數據丟失,此時這個分布式系統依然可以工作。 通過了解以上概念,我們知道,分區容忍性是要保證的。當系統中的出現節點Node1和Node2無法同步數據的情況時,數據一致性和可用性是無法同時保證的,需要 有取舍。 保證數據的一致性以及分區容忍性(CP):所有節點數據一致,當 出現 一個節點與其他節點失去聯系,此時系統服務不可用。 保證系統的可用性以及分區容忍性(AP):即便出現一個節點與其他節點無法通信的情況,該節點也提供服務,此時不保證改節點的數據與其他節點的數據一致; 當該節點可以通信時,同步數據。

舉例

假設我們的服務是博客系統。 最初系統服務的訪問量並不大,單個服務節點足以支撐。 隨著用戶數量的發展,單個節點支撐不住了,於是考慮做水平擴展。我們的服務節點由一個擴展到了兩個,並且,每個服務節點都保存一份數據。由於我們有兩個服務 節點,所以在這兩個節點前,增加了Load Balancer用於做調度,如圖1                   技術分享圖片                              圖1 對於讀請求不做描述。 對於寫請求,過程如下 1. 請求到達Load Balancer 2. Load Balancer做判斷,將請求分配給某一個節點,如Node1 3. Node1執行寫操作。如果此時返回處理結果給客戶端,那麽 假如有相同的請求,但是落到了Node2時,數據時不一致的,所以我們要做數據同步。我們先做 一個假設,數據同步一定成功且耗時很短很短
。 我們可以有兩種方式同步。 第一種,直到Node2的數據同步了,Node1才返回。第二種,Node1執行同步數據操作,不等待同步完成,立即返回結果。 現在假設Node1和Node2的通信斷開了,如圖2           技術分享圖片                           圖2 無論以上哪種同步方式都行不通,那麽我們要做出抉擇,是要保證數據的一致性好,還是保證可用性。因為我們的服務是博客服務,即便數據暫時性地不一致也是可以 忍受的,並且,如果長時間用戶得不到內容會導致用戶流失,所以我們傾向保證可用性。即 修改第三部處理,當Node1和Node2的通信斷開時,暫時不做數據同步, 直接返回結果。 這種處理方式,當通信斷開時,Node1和Node2的數據在處理寫請求後是不一致的。 現在假設Node1和Node2的數據同步過程會耗時會很長。我們依舊傾向保證可用性。因為第一種同步方法會讓用戶等待較長的時間,我們采用第二種同步方法。 第二種方法,會保證經過一段時間後,數據是一致的。這是所謂的最終一致性。 下面,我們再考慮這樣的問題,依舊假設Node1和Node2的數據同步過程會耗時很長。來了一個寫請求,Load balancer將其分配給了Node1;很快又來了一個寫請求,Load Balancer將其分配給了Node2。此時數據該怎麽同步呢?假如修改的都是同一個文章ID所對應的內容呢? 可以考慮將Node1 和 Node2 的同步請求加入到一個公共的隊列中。即 節點在進行寫操作後,將同步操作加入到公共隊列中,然後 節點返回結果給用戶。 我們可以實時地消費這個隊列,也可以定時地消費這個隊列。 消費這個隊列時,將數據寫到Node1和Node2中,如圖3               技術分享圖片                                  圖3 這個方案依舊不夠好,因為多寫了一次數據。 假如寫數據的操作很耗時,為了避免多寫一次,我們也可以在Node1和Node2上設置緩存(偏向可用性),即寫時 不寫數據而是寫緩存。但設置緩存又會引發Node1 與Node2緩存不一致的情況發生(需要處理數據一致性)。 好了,偏向可用性的討論先到此為止。 假設我們做的系統不是博客系統是交易系統。 我們的系統需要的是強一致性。即無論從Node1還是Node2讀寫數據,得到的結果都是一樣的。因為是交易系統,所以需要做到的是數據是強一致性的,即每時每刻 數據一致。 假設寫請求到了Node1,此時Node1需要寫數據並將數據同步到Node2。假如Node1與Node2的通信斷開了,那麽我們應該給用戶返回一個請等待的頁面。此時數據既沒有 寫入Node1也沒有寫入Node2。 假如通信沒斷開的話,怎樣保證寫入了Node1數據,也會寫入Node2數據呢? 可以使用兩段提交的算法。兩段提交需要 一個協調者,比如Node3,而所有待更新節點數據作為參與者。 第一階段,請求階段:協調者Node3 請求 Node1和Node2是否對User1的賬戶進行更新,參與者Node1 回復可以更新,參與者Node2 回復不可以更新(比如正在有 讀操作) 第二階段,提交階段:只有所有參與者都同意才會提交事務。Node3根據Node1和Node2的回復,做出是否提交事務的判斷,不提交。 參考 http://ksat.me/a-plain-english-introduction-to-cap-theorem/ https://stackoverflow.com/questions/12346326/cap-theorem-availability-and-partition-tolerance http://www.importnew.com/20633.html

【分布式系統設計】基礎概念