帶你瞭解分佈式系統的數據一致性問題

老劉是一名即將找工做的研二學生,寫博客一方面是複習總結大數據開發的知識點,一方面是但願可以幫助和本身同樣自學編程的夥伴。因爲老劉是自學大數據開發,博客中確定會存在一些不足,還但願你們可以批評指正,讓咱們一塊兒進步!算法


今天給各位小夥伴聊聊分佈式系統的數據一致性問題,這個必定要從服務器架構部署的發展歷程講起!文章篇幅較長,請你們耐心觀看,精彩千萬不要錯過!編程

1. 背景

1.1. 集中式服務

首先要講的是集中式服務,那集中式是什麼?就是事情都由一臺服務器搞定。安全

而集中式系統就是由一臺或多臺主計算機組成中心節點,數據集中存儲於這個中心節點中,而且整個系統的全部業務都在這個中心節點上,系統全部的功能都由它作。服務器

也就是說,在集中式系統中,每一個客戶端僅僅負責數據的輸入和輸出,而數據的存儲與控制處理徹底交給主機完成。網絡

那集中式服務優勢:架構

  1. 結構簡單
  2. 部署簡單
  3. 項目架構簡單

可是它的缺點也是很是明顯:併發

  1. 大型主機的研發和維護成本很是高
  2. 大型主機很是昂貴
  3. 存在單點故障問題,主機一掛,全部服務終止
  4. 大型主機的性能擴展受限於摩爾定律

什麼是摩爾定律?分佈式

摩爾定律是由英特爾(Intel)創始人之一戈登·摩爾(Gordon Moore)提出來的。其內容爲:當價格不變時,集成電路上可容納的元器件的數目,約每隔18-24個月便會增長一倍,性能也將提高一倍。換言之,每一美圓所能買到的電腦性能,將每隔18-24個月翻一倍以上。摘自:百度百科高併發

摩爾定律告訴咱們:縱向擴展理論上是受限的,因此只能考慮橫向擴展,並且從理論上說,橫向擴展理論上是不受限的!性能

那既然縱向擴展受限,咱們就去嘗試橫向擴展,就有了分佈式!

1.2. 分佈式服務

分佈式意味着能夠採用更多的普通計算機(相對於昂貴的大型機)組成分佈式集羣對外提供服務。計算機越多,CPU、內存、存儲資源等也就越多,可以處理的併發訪問量也就越大。

例如一個由分佈式系統實現的電子商城,在功能上可能被拆分紅多個應用,分別提供不一樣的功能,組成一個分佈式系統對外提供服務。

因此,分佈式系統中的計算機在空間上是幾乎沒有限制的,這些計算機可能被放在不一樣的機櫃上,也可能被部署在不一樣的機房中,還可能在不一樣的城市中。

和集中式系統相比,分佈式系統的性價比更高、處理能力更強、可靠性更高、也有很好的擴展性。

可是,分佈式解決了網站的高併發問題的同時也帶來了一些其餘問題。

首先,分佈式的必要條件就是網絡,這可能對性能甚至服務能力形成必定的影響。其次,一個集羣中的服務器數量越多,服務器宕機的機率也就越大。另外,因爲服務在集羣中分佈式部署,用戶的請求只會落到其中一臺機器上,因此,一旦處理很差就很容易產生數據一致性問題。

1.3. 分佈式存在的異常

一、通訊異常:網絡不可用(消息延遲或者丟失),會致使分佈式系統內部沒法順利進行網絡通訊,因此可能形成多個節點數據丟失和狀態不一致,還有可能形成數據亂序。

二、網絡分區:網絡不連通,但各個子網絡的內部網絡是正常的,從而致使整個系統的網絡環境被切分紅若干個孤立的區域,分佈式系統就出現了局部小集羣形成的數據不一致。

三、節點故障:服務器節點出現的宕機的現象。

四、存儲數據丟失:對於有狀態節點來講,數據丟失意味着狀態丟失,一般只能從其餘節點讀取、恢復存儲的狀態。解決方案:利用多副本機制。

1.4. 衡量分佈式系統的性能指標

一、性能:這是一個很是讓人頭疼的問題,追求高吞吐的系統,每每很難作到低延遲;系統平均響應時間較長時,也很難提升QPS。

系統的吞吐能力,指系統在某一時間能夠處理的數據總量,一般能夠用系統每秒處理的總數據量來衡量; 系統的響應延遲,指系統完成某一功能須要使用的時間; 系統的併發能力,指系統能夠同時完成某一功能的能力,一般也用QPS來衡量。

二、可用性:系統的可用性(availability)指系統在面對各類異常時能夠正確提供服務的能力。可用性是分佈式的重要指標,衡量了系統的魯棒性,是系統容錯能力的體現。

三、可擴展性:系統的可擴展性(scalability)指分佈式系統經過擴展集羣機器規模提升系統性能(吞吐、延遲、併發)、存儲容量、計算能力的特性。

四、一致性:分佈式系統爲了提升可用性,老是不可避免地使用副本的機制,從而引起副本一致性的問題。

例如,就是一份數據存在分佈式系統,存在多個不一樣的節點當中存着相同的數據。若是多個不一樣的節點存的數據不同,多個客戶端去訪問的時候就會存在這種狀況,第1個客戶端去訪問的結果爲A,第2個客戶端訪問的結果爲B,兩個客戶端訪問獲得不一樣的結果,那就是一致性作的很差。

說了這麼多,咱們若是設計一個優秀的分佈式系統,它應該具備這些特色:吞吐高、響應延遲低、併發強、可用性很高、可擴展性很強、一致性很好。但並非每一個特色都能知足,有幾個特色是相互矛盾的,須要咱們想辦法克服!

而在分佈式場景中真正複雜的是數據一致性的問題!

1.5. 一致性理解

一致性也分不少種,這裏說說老劉瞭解的三個。

強一致性:寫操做完成以後,讀操做必定能讀到最新數據。通俗地講就是客戶端只要把結果寫進去了,何時訪問都能拿到最新的數據。可是在分佈式場景中很難實現,後續的Paxos 算法,Quorum 機制,ZAB 協議等能實現!

弱一致性:不保證拿到最新的數據,也有可能拿到舊的數據。

最終一致性:不考慮中間的任何狀態,只保證通過一段時間以後,最終系統內數據正確。在高併發場景中,它也是使用最廣的一致性模型。

1.6. 分佈式一致性的做用

說了那麼多分佈式一致性的內容,那它的做用是什麼呢?

一、爲了提升系統的可用性,通常都會使用多副本機制,多副本就會有分佈式一致性的問題,它就是爲了提升系統的可用性,防止單點節點故障引發的系統不可用。

二、提升系統的總體性能,數據分佈在集羣中多個節點上,它們都能爲用戶提供服務。

老劉說了這麼多,你們有沒有猜到想引出什麼內容呢?

上述那麼多內容只爲引出分佈式系統的數據一致性問題!咱們用來解決分佈式系統的數據一致性問題的方案有以下:

分佈式事務+事務 分佈式一致性算法 Quorum機制 CAP和BASE理論

2. 分佈式事務

分佈式系統中,每一個節點都能知道本身的事務操做是否成功,可是無法知道系統中的其餘節點的事務是否成功。這就有可能會形成分佈式系統中的各節點的狀態出現不一致。所以當一個事務須要跨越服務器節點,而且要保證事務的ACID特性時,就必須引入一個協調者的角色。那麼其餘的各個進行事務操做的節點就都叫作參與者。

現實生活中有兩種典型的分佈式事務的提交模式:2PC和3PC。

2.1. 2PC提交過程

直接上圖:

我讓A去作一件事,讓B去作另一件事,而且這兩件事在一個分佈式事務中要保證同時成功或失敗。那如何作到數據一致呢?

2PC分兩個階段: 第一階段:執行事務,但不提交。 第二階段:當協調者收到第一階段中全部事務參與者的正反饋時(事務都執行成功了), 就去發命令讓全部參與者提交事務。

 

2.2. 2PC的問題

看了2PC的兩個提交階段和圖,有經驗的人一眼就會看出裏面存在的問題。

1 阻塞問題

協調者發送命令給參與者,因爲是網路發送命令,就會存在不一樣參與者收到的命令有前後、有延遲。例如參與者A很快就收到了,參與者B網絡有問題,過了好久才收到命令。參與者A很快處理完髮送反饋, 而參與者B就好久以後才發送反饋,致使協調者等待時間特別長。 這就是一個很是典型的阻塞問題,很是浪費資源,影響性能!

2 沒有容錯機制,存在單點故障問題

事務協調者是整個分佈式事務的核心,一旦協調者出現故障,看看上面那張圖,就會知道參與者就收不到 commit/rollback的通知,從而致使參與者節點一直處於事務沒法完成的中間狀態。

3 數據不一致

在第二階段,若是發生局部網絡問題,一個參與者收到提交的命令,另外一個參與者沒有收到提交的命令, 就會形成節點間數據不一致。

2.3. 3PC

3PC就是三階段提交的意思,它是2階段提交的改進版,把二階段提交協議的 "提交事務請求" 一分爲二,造成了cancommit,precommit,docommit 三個階段。

除了在 2PC 的基礎上增長了CanCommit階段,還引入了超時機制。一旦事務參與者在指定時間內沒有收到協調者的 commit/rollback 指令,就會自動本地 commit,這樣能夠解決協調者單點故障的問題。

2.4. 執行過程解析

第一階段:CanCommit階段

在第一階段準備的時候,先問一下各個參與者是否能夠進行事務操做以及超時機制,參與者在必定時間沒 收到協調者的指令會自動提交。

第二階段:PreCommit階段

一、若是每一個參與者返回的都是贊成,協調者則向全部參與者發送預提交請求,並進入預提交階段; 二、參與者收到預提交請求後,執行事務操做。 三、參與者執行完本地事務以後,會向協調者發出Ack表示已準備好提交,並等待協調者下一步指令。 四、若是協調者收到預提交響應爲拒絕或者超時,則執行中斷事務操做,通知各參與者中斷事務。 五、參與者收到中斷事務或者等待超時,都會主動中斷事務/直接提交

第三階段:doCommit階段

一、協調者收到全部參與 的Ack,則從預提交入提交段,並向各參與者發送提交請求。 二、參與者收到提交請求,正式提交事務(commit),並向協調者反饋提交結果Y/N。 三、協調者收到全部反饋消息,完成分佈式事務。 四、若是協調者超時沒有收到反饋,則發送中斷事務指令。 五、參與者收到中斷事務指令後,利用事務日誌進行rollback。 六、參與者反饋回滾結果,協調者接收反饋結果或者超時,完成中斷事務。

2.5. 3PC的問題

3PC也可能出現數據不一致,第三階段讓全部參與者回滾事務,但有一個參與者在規定的時間內沒有收到,它會默認進行提交操做,就會出現數據不一致。因爲網絡問題,第二階段到第三階段之間特別容易出現數據不一致問題。

3. 分佈式一致性算法

在2PC和3PC的原理上,優秀的開發者們實現了分佈式一致性算法,這裏老劉先大體講講Poxos算法和ZAB協議的相關概念。若是想詳細瞭解Paxos算法和ZAB協議,等老劉找完工做後,專門寫一篇Zookeeper源碼文章。

3.1. Paxos算法

Paxos 算法使用一個希臘故事來描述,在 Paxos 中,存在三種角色,分別爲

一、Proposer(提議者,用來發出提案proposal), 二、Acceptor(接受者,能夠接受或拒絕提案), 三、Learner(學習者,學習被選定的提案,當提案被超過半數的Acceptor接受後爲被批准)。

映射到 zookeeper 集羣:

leader:發起提案 主席(單點故障的解決辦法是leader選舉機制) follower:參與投票 人大表明 observer:被動接受 全國全部人

以及有一個特別出名的機制:議會制

保證超過半數達成一致性便可的協議

總結下Paxos算法,它就是全部事務請求必須由一個全局惟一的服務器來協調處理,這樣的服務器被稱爲 leader 服務器,而餘下的其餘服務器則成爲 follower 服務器。

leader 服務器負責將一個客戶端事務請求轉換成一個事務proposal,並將該 proposal 分發給集羣中全部的follower 服務器。以後 leader 服務器須要等待全部follower 服務器的反饋,一旦超過半數的 follower 服務器進行了正確的反饋後,那麼 leader 就會再次向全部的 follower 服務器分發 commit 消息,要求其將前一個 proposal 進行提交。

3.2. ZAB協議

ZooKeeper的底層工做機制,就是依靠 ZAB 實現的。它實現了崩潰回覆和消息廣播兩個主要功能。

ZAB協議保證數據一致性的兩個重要特色就是:

一、ZAB協議須要確保那些已經在 leader 服務器上提交的事務最終被全部服務器都提交。

二、ZAB協議須要確保丟棄那些只在 leader 服務器上被提出的事務。

爲了解決單點故障,有leader選舉算法。在leader選舉中,若是讓 leader 選舉算法可以保證新選舉出來的 leader 服務器擁有集羣中全部機器最高事務編號(ZXID)的事務proposal,那麼就能夠保證這個新選舉出來的 leader 必定具備全部已經提交的提案。

由於事務的每次執行都會有一個編號,最高事務編號表明着最新的事務,即最新的數據。 根據上述ZAB協議內容,ZooKeeper實現了分佈式系統數據的一致性!

4. 鴿巢原理

簡單描述:如有n個籠子和n+1只鴿子,全部的鴿子都被關在鴿籠裏,那麼至少有一個籠子有至少2只鴿子 。

5. Quorum NWR機制

Quorum NWR:Quorum 機制是分佈式場景中經常使用的,用來保證數據安全,而且在分佈式環境中實現最終一致性的投票算法。這種算法的主要原理來源於鴿巢原理。它最大的優點,既能實現強一致性,並且還能自定義一致性級別!

N:總節點數

W:總寫入成功數

R:總讀取數

當W+R>N時,必定能保證讀到最新的數據,即強一致性! 爲何這樣說?

如上圖,有4個箱子,3個箱子裏面有東西,那如何保證必定能拿到有數據的箱子?最起碼拿2個箱子就能拿到有東西的箱子!

就是利用這種原理,只要保證(W + R > N)就必定能讀取到最新的數據,數據一致性級別徹底能夠根據讀寫副本數的約束來達到強一致性!

那如今分如下三種狀況討論:前提是N已經肯定不改了!

W = 1, R = N,Write Once Read All

在分佈式環境中,寫一份,至關於只有只有一個箱子有東西,那麼若是要讀取到最新數據,即拿到有東西的箱子,就必需要讀取全部節點,而後取最新版本的值了。寫操做高效,可是讀操做效率低。一致性高,但分區容錯性差,可用性低。

W = N,R = 1, Read Only Write All

在分佈式環境中,全部節點都同步完畢,才能讀取,因此只要讀取任意一個節點就能夠讀取到最新數據。讀操做高效,可是寫操做效率低。分區容錯性好,一致性差,實現難度更高,可用性高 。

W = Q, R = Q where Q = N/2 + 1

能夠簡單理解爲寫超過一半節點,那麼讀也超過一半節點,取得讀寫性能平衡。通常應用適用,讀寫性能之間取得平衡。如 N=3, W=2, R=2,分區容錯性,可用性,一致性取得一個平衡。

ZooKeeper就是這麼幹的!採用了第三種狀況!

6. CAP理論

根據上述說的,作到強一致性了,就難作到高可用,二者是很是矛盾的。因此CAP理論就告訴咱們,一個分佈式系統不可能同時知足C,A,P三個需求。

C:Consistency,強一致性

分佈式環境中多個數據副本保持一致

A:Availability,高可用性

系統提供的服務必須一直處於可用,對於用戶的每個操做請求老是能在有限時間內返回結果

P:Partiton Tolerance 分區容錯性

分佈式系統在遇到任何網絡分區故障時,仍然須要可以保證對外提供知足一致性和可用性的服務

既然一個分佈式系統不能同時知足C,A,P三個需求,那麼如何選擇?

CAP只能3選2,由於在分佈式系統中,容錯性P確定是必須有的,因此這時候無非就兩種狀況,網絡問題致使要麼錯誤返回,要麼阻塞等待,前者犧牲了一致性,後者犧牲了可用性。

對於單機軟件,由於不一樣考慮P,因此確定是CA型,好比MySQL。

對於分佈式軟件,由於必定會考慮P,因此又不能兼顧A和C的狀況下,只能在A和C作權衡,好比HBase、Redis等。作到服務基本可用,而且數據最終一致性便可。 因此,就產生了BASE理論。

7. BASE理論

多數狀況下,其實咱們也並不是必定要求強一致性,部分業務能夠容忍必定程度的延遲一致,因此爲了兼顧效率,發展出來了最終一致性理論 BASE,它的核心思想是:即便沒法作到強一致性,但每一個應用均可以根據自身業務特色,採用適當的方式來使系統達到最終一致性。

一句話就是作事別走極端,BASE 是對 CAP 理論中的 C 和 A 進行權衡獲得的結果。

BASE理論作到的不是強一致,而是最終一致;不是高可用,而是基本可用。

Basically Available(基本可用):基本可用是指分佈式系統在出現故障的時候,容許損失部分可用性,保證核心可用。 例如:淘寶雙11,爲保護系統穩定性,正常下單,其餘邊緣服務可暫時不可用。

Eventually Consistent(最終一致):最終一致性是指系統中的全部數據副本通過必定時間後,最終可以達到一致的狀態。

之後開發分佈式系統,就能夠根據業務來決定到底追求高可用仍是追求強一致性!

8. 總結

好啦,分佈式系統的數據一致性問題大體聊得差很少了,老劉主要給你們講了講分佈式系統一致性的背景以及實現。儘管當前水平可能不及各位大佬,但老劉仍是但願可以變得更加優秀,可以幫助更多自學編程的夥伴。

若是有相關問題,請聯繫公衆號:努力的老劉,和老劉進行愉快的交流,若是以爲幫到了您,不妨點贊關注支持一波!

相關文章
相關標籤/搜索