老劉是一名即將找工做的研二學生,寫博客一方面是複習總結大數據開發的知識點,一方面是但願可以幫助和本身同樣自學編程的夥伴。因爲老劉是自學大數據開發,博客中確定會存在一些不足,還但願你們可以批評指正,讓咱們一塊兒進步!算法
今天給各位小夥伴聊聊分佈式系統的數據一致性問題,這個必定要從服務器架構部署的發展歷程講起!文章篇幅較長,請你們耐心觀看,精彩千萬不要錯過!編程
首先要講的是集中式服務,那集中式是什麼?就是事情都由一臺服務器搞定。安全
而集中式系統就是由一臺或多臺主計算機組成中心節點,數據集中存儲於這個中心節點中,而且整個系統的全部業務都在這個中心節點上,系統全部的功能都由它作。服務器
也就是說,在集中式系統中,每一個客戶端僅僅負責數據的輸入和輸出,而數據的存儲與控制處理徹底交給主機完成。網絡
那集中式服務優勢:架構
可是它的缺點也是很是明顯:併發
什麼是摩爾定律?分佈式
摩爾定律是由英特爾(Intel)創始人之一戈登·摩爾(Gordon Moore)提出來的。其內容爲:當價格不變時,集成電路上可容納的元器件的數目,約每隔18-24個月便會增長一倍,性能也將提高一倍。換言之,每一美圓所能買到的電腦性能,將每隔18-24個月翻一倍以上。摘自:百度百科高併發
摩爾定律告訴咱們:縱向擴展理論上是受限的,因此只能考慮橫向擴展,並且從理論上說,橫向擴展理論上是不受限的!性能
那既然縱向擴展受限,咱們就去嘗試橫向擴展,就有了分佈式!
分佈式意味着能夠採用更多的普通計算機(相對於昂貴的大型機)組成分佈式集羣對外提供服務。計算機越多,CPU、內存、存儲資源等也就越多,可以處理的併發訪問量也就越大。
例如一個由分佈式系統實現的電子商城,在功能上可能被拆分紅多個應用,分別提供不一樣的功能,組成一個分佈式系統對外提供服務。
因此,分佈式系統中的計算機在空間上是幾乎沒有限制的,這些計算機可能被放在不一樣的機櫃上,也可能被部署在不一樣的機房中,還可能在不一樣的城市中。
和集中式系統相比,分佈式系統的性價比更高、處理能力更強、可靠性更高、也有很好的擴展性。
可是,分佈式解決了網站的高併發問題的同時也帶來了一些其餘問題。
首先,分佈式的必要條件就是網絡,這可能對性能甚至服務能力形成必定的影響。其次,一個集羣中的服務器數量越多,服務器宕機的機率也就越大。另外,因爲服務在集羣中分佈式部署,用戶的請求只會落到其中一臺機器上,因此,一旦處理很差就很容易產生數據一致性問題。
一、通訊異常:網絡不可用(消息延遲或者丟失),會致使分佈式系統內部沒法順利進行網絡通訊,因此可能形成多個節點數據丟失和狀態不一致,還有可能形成數據亂序。
二、網絡分區:網絡不連通,但各個子網絡的內部網絡是正常的,從而致使整個系統的網絡環境被切分紅若干個孤立的區域,分佈式系統就出現了局部小集羣形成的數據不一致。
三、節點故障:服務器節點出現的宕機的現象。
四、存儲數據丟失:對於有狀態節點來講,數據丟失意味着狀態丟失,一般只能從其餘節點讀取、恢復存儲的狀態。解決方案:利用多副本機制。
一、性能:這是一個很是讓人頭疼的問題,追求高吞吐的系統,每每很難作到低延遲;系統平均響應時間較長時,也很難提升QPS。
系統的吞吐能力,指系統在某一時間能夠處理的數據總量,一般能夠用系統每秒處理的總數據量來衡量; 系統的響應延遲,指系統完成某一功能須要使用的時間; 系統的併發能力,指系統能夠同時完成某一功能的能力,一般也用QPS來衡量。
二、可用性:系統的可用性(availability)指系統在面對各類異常時能夠正確提供服務的能力。可用性是分佈式的重要指標,衡量了系統的魯棒性,是系統容錯能力的體現。
三、可擴展性:系統的可擴展性(scalability)指分佈式系統經過擴展集羣機器規模提升系統性能(吞吐、延遲、併發)、存儲容量、計算能力的特性。
四、一致性:分佈式系統爲了提升可用性,老是不可避免地使用副本的機制,從而引起副本一致性的問題。
例如,就是一份數據存在分佈式系統,存在多個不一樣的節點當中存着相同的數據。若是多個不一樣的節點存的數據不同,多個客戶端去訪問的時候就會存在這種狀況,第1個客戶端去訪問的結果爲A,第2個客戶端訪問的結果爲B,兩個客戶端訪問獲得不一樣的結果,那就是一致性作的很差。
說了這麼多,咱們若是設計一個優秀的分佈式系統,它應該具備這些特色:吞吐高、響應延遲低、併發強、可用性很高、可擴展性很強、一致性很好。但並非每一個特色都能知足,有幾個特色是相互矛盾的,須要咱們想辦法克服!
而在分佈式場景中真正複雜的是數據一致性的問題!
一致性也分不少種,這裏說說老劉瞭解的三個。
強一致性:寫操做完成以後,讀操做必定能讀到最新數據。通俗地講就是客戶端只要把結果寫進去了,何時訪問都能拿到最新的數據。可是在分佈式場景中很難實現,後續的Paxos 算法,Quorum 機制,ZAB 協議等能實現!
弱一致性:不保證拿到最新的數據,也有可能拿到舊的數據。
最終一致性:不考慮中間的任何狀態,只保證通過一段時間以後,最終系統內數據正確。在高併發場景中,它也是使用最廣的一致性模型。
說了那麼多分佈式一致性的內容,那它的做用是什麼呢?
一、爲了提升系統的可用性,通常都會使用多副本機制,多副本就會有分佈式一致性的問題,它就是爲了提升系統的可用性,防止單點節點故障引發的系統不可用。
二、提升系統的總體性能,數據分佈在集羣中多個節點上,它們都能爲用戶提供服務。
老劉說了這麼多,你們有沒有猜到想引出什麼內容呢?
上述那麼多內容只爲引出分佈式系統的數據一致性問題!咱們用來解決分佈式系統的數據一致性問題的方案有以下:
分佈式事務+事務 分佈式一致性算法 Quorum機制 CAP和BASE理論
分佈式系統中,每一個節點都能知道本身的事務操做是否成功,可是無法知道系統中的其餘節點的事務是否成功。這就有可能會形成分佈式系統中的各節點的狀態出現不一致。所以當一個事務須要跨越服務器節點,而且要保證事務的ACID特性時,就必須引入一個協調者的角色。那麼其餘的各個進行事務操做的節點就都叫作參與者。
現實生活中有兩種典型的分佈式事務的提交模式:2PC和3PC。
直接上圖:
我讓A去作一件事,讓B去作另一件事,而且這兩件事在一個分佈式事務中要保證同時成功或失敗。那如何作到數據一致呢?
2PC分兩個階段: 第一階段:執行事務,但不提交。 第二階段:當協調者收到第一階段中全部事務參與者的正反饋時(事務都執行成功了), 就去發命令讓全部參與者提交事務。
看了2PC的兩個提交階段和圖,有經驗的人一眼就會看出裏面存在的問題。
1 阻塞問題
協調者發送命令給參與者,因爲是網路發送命令,就會存在不一樣參與者收到的命令有前後、有延遲。例如參與者A很快就收到了,參與者B網絡有問題,過了好久才收到命令。參與者A很快處理完髮送反饋, 而參與者B就好久以後才發送反饋,致使協調者等待時間特別長。 這就是一個很是典型的阻塞問題,很是浪費資源,影響性能!
2 沒有容錯機制,存在單點故障問題
事務協調者是整個分佈式事務的核心,一旦協調者出現故障,看看上面那張圖,就會知道參與者就收不到 commit/rollback的通知,從而致使參與者節點一直處於事務沒法完成的中間狀態。
3 數據不一致
在第二階段,若是發生局部網絡問題,一個參與者收到提交的命令,另外一個參與者沒有收到提交的命令, 就會形成節點間數據不一致。
3PC就是三階段提交的意思,它是2階段提交的改進版,把二階段提交協議的 "提交事務請求" 一分爲二,造成了cancommit,precommit,docommit 三個階段。
除了在 2PC 的基礎上增長了CanCommit階段,還引入了超時機制。一旦事務參與者在指定時間內沒有收到協調者的 commit/rollback 指令,就會自動本地 commit,這樣能夠解決協調者單點故障的問題。
第一階段:CanCommit階段
在第一階段準備的時候,先問一下各個參與者是否能夠進行事務操做以及超時機制,參與者在必定時間沒 收到協調者的指令會自動提交。
第二階段:PreCommit階段
一、若是每一個參與者返回的都是贊成,協調者則向全部參與者發送預提交請求,並進入預提交階段; 二、參與者收到預提交請求後,執行事務操做。 三、參與者執行完本地事務以後,會向協調者發出Ack表示已準備好提交,並等待協調者下一步指令。 四、若是協調者收到預提交響應爲拒絕或者超時,則執行中斷事務操做,通知各參與者中斷事務。 五、參與者收到中斷事務或者等待超時,都會主動中斷事務/直接提交
第三階段:doCommit階段
一、協調者收到全部參與 的Ack,則從預提交入提交段,並向各參與者發送提交請求。 二、參與者收到提交請求,正式提交事務(commit),並向協調者反饋提交結果Y/N。 三、協調者收到全部反饋消息,完成分佈式事務。 四、若是協調者超時沒有收到反饋,則發送中斷事務指令。 五、參與者收到中斷事務指令後,利用事務日誌進行rollback。 六、參與者反饋回滾結果,協調者接收反饋結果或者超時,完成中斷事務。
3PC也可能出現數據不一致,第三階段讓全部參與者回滾事務,但有一個參與者在規定的時間內沒有收到,它會默認進行提交操做,就會出現數據不一致。因爲網絡問題,第二階段到第三階段之間特別容易出現數據不一致問題。
在2PC和3PC的原理上,優秀的開發者們實現了分佈式一致性算法,這裏老劉先大體講講Poxos算法和ZAB協議的相關概念。若是想詳細瞭解Paxos算法和ZAB協議,等老劉找完工做後,專門寫一篇Zookeeper源碼文章。
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 進行提交。
ZooKeeper的底層工做機制,就是依靠 ZAB 實現的。它實現了崩潰回覆和消息廣播兩個主要功能。
ZAB協議保證數據一致性的兩個重要特色就是:
一、ZAB協議須要確保那些已經在 leader 服務器上提交的事務最終被全部服務器都提交。
二、ZAB協議須要確保丟棄那些只在 leader 服務器上被提出的事務。
爲了解決單點故障,有leader選舉算法。在leader選舉中,若是讓 leader 選舉算法可以保證新選舉出來的 leader 服務器擁有集羣中全部機器最高事務編號(ZXID)的事務proposal,那麼就能夠保證這個新選舉出來的 leader 必定具備全部已經提交的提案。
由於事務的每次執行都會有一個編號,最高事務編號表明着最新的事務,即最新的數據。 根據上述ZAB協議內容,ZooKeeper實現了分佈式系統數據的一致性!
簡單描述:如有n個籠子和n+1只鴿子,全部的鴿子都被關在鴿籠裏,那麼至少有一個籠子有至少2只鴿子 。
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就是這麼幹的!採用了第三種狀況!
根據上述說的,作到強一致性了,就難作到高可用,二者是很是矛盾的。因此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理論。
多數狀況下,其實咱們也並不是必定要求強一致性,部分業務能夠容忍必定程度的延遲一致,因此爲了兼顧效率,發展出來了最終一致性理論 BASE,它的核心思想是:即便沒法作到強一致性,但每一個應用均可以根據自身業務特色,採用適當的方式來使系統達到最終一致性。
一句話就是作事別走極端,BASE 是對 CAP 理論中的 C 和 A 進行權衡獲得的結果。
BASE理論作到的不是強一致,而是最終一致;不是高可用,而是基本可用。
Basically Available(基本可用):基本可用是指分佈式系統在出現故障的時候,容許損失部分可用性,保證核心可用。 例如:淘寶雙11,爲保護系統穩定性,正常下單,其餘邊緣服務可暫時不可用。
Eventually Consistent(最終一致):最終一致性是指系統中的全部數據副本通過必定時間後,最終可以達到一致的狀態。
之後開發分佈式系統,就能夠根據業務來決定到底追求高可用仍是追求強一致性!
好啦,分佈式系統的數據一致性問題大體聊得差很少了,老劉主要給你們講了講分佈式系統一致性的背景以及實現。儘管當前水平可能不及各位大佬,但老劉仍是但願可以變得更加優秀,可以幫助更多自學編程的夥伴。
若是有相關問題,請聯繫公衆號:努力的老劉,和老劉進行愉快的交流,若是以爲幫到了您,不妨點贊關注支持一波!