一個事務(transaction)中的全部操做,要麼所有完成,要麼所有不完成,不會結束在中間某個環節。事務在執行過程當中發生錯誤,會被回滾(Rollback)到事務開始前的狀態,就像這個事務歷來沒有執行過同樣。數據庫
一個事務執行以前和執行以後數據庫都必須處於一致性狀態。若是事務成功地完成,那麼系統中全部變化將正確地應用,系統處於有效狀態。若是在事務中出現錯誤,那麼系統中的全部變化將自動地回滾,系統返回到原始狀態。服務器
在併發環境中,當不一樣的事務同時操縱相同的數據時,每一個事務都有各自的完整數據空間。由併發事務所作的修改必須與任何其餘併發事務所作的修改隔離。事務查看數據更新時,數據所處的狀態要麼是另外一事務修改它以前的狀態,要麼是另外一事務修改它以後的狀態,事務不會查看到中間狀態的數據。網絡
只要事務成功結束,它對數據庫所作的更新就必須永久保存下來。即便發生系統崩潰,從新啓動數據庫系統後,數據庫還能恢復到事務成功結束時的狀態。併發
一個分佈式系統最多隻能同時知足一致性(Consistency)、可用性(Availability)和分區容錯性(Partition tolerance)這三項中的兩項。該一致性指的是強一致性。負載均衡
數據一致性。即更新操做成功並返回客戶端完成後,全部節點在同一時間的數據徹底一致。分佈式
對於一致性,能夠分爲從客戶端和服務端兩個不一樣的視角。從客戶端來看,一致性主要指的是多併發訪問時更新過的數據如何獲取的問題。從服務端來看,則是更新如何複製分佈到整個系統,以保證數據最終一致。性能
當更新操做完成以後,任何多個後續進程或者線程的訪問都會返回最新的更新過的值。這種是對用戶最友好的,就是用戶上一次寫什麼,下一次就保證能讀到什麼。可是這種實現對性能影響較大,由於這意味着,只要上次的操做沒有處理完,就不能讓用戶讀取數據。網站
系統並不保證進程或者線程的訪問都會返回最新的更新過的值。系統在數據寫入成功以後,不承諾當即能夠讀到最新寫入的值,也不會具體的承諾多久以後能夠讀到。但會盡量保證在某個時間級別(好比秒級別)以後,可讓數據達到一致性狀態。線程
弱一致性的特定形式。系統保證在沒有後續更新的前提下,系統最終返回上一次更新操做的值。在沒有故障發生的前提下,不一致窗口的時間主要受通訊延遲,系統負載和複製副本的個數影響。設計
服務一直可用,並且是正常響應時間。
對於一個可用性的分佈式系統,每個非故障的節點必須對每個請求做出響應。因此,通常咱們在衡量一個系統的可用性的時候,都是經過停機時間來計算的。可用性主要是指系統可以很好的爲用戶服務,不出現用戶操做失敗或者訪問超時等用戶體驗很差的狀況。一個分佈式系統,上下游設計不少系統如負載均衡、WEB服務器、應用代碼、數據庫服務器等,任何一個節點的不穩定均可以影響可用性。
分佈式系統在遇到某節點或網絡分區故障的時候,仍然可以對外提供知足一致性和可用性的服務。
分區容錯性和擴展性緊密相關。在分佈式應用中,可能由於一些分佈式的緣由致使系統沒法正常運轉。好的分區容錯性要求可以使應用雖然是一個分佈式系統,而看上去卻好像是在一個能夠運轉正常的總體。好比如今的分佈式系統中有某一個或者幾個機器宕掉了,其餘剩下的機器還可以正常運轉知足系統需求,或者是機器之間有網絡異常,將分佈式系統分隔未獨立的幾個部分,各個部分還能維持分佈式系統的運做,這樣就具備好的分區容錯性。簡單點說,就是在網絡中斷,消息丟失的狀況下,系統若是還能正常工做,就是有比較好的分區容錯性。
如上圖,是分佈式系統正常運轉的流程,用戶向N1機器請求數據更新,程序A更新數據庫Vo爲V1,分佈式系統將數據進行同步操做M,將V1同步的N2中V0,使得N2中的數據V0也更新爲V1,N2中的數據再響應N2的請求。
這裏,能夠定義N1和N2的數據庫V之間的數據是否同樣爲一致性;外部對N1和N2的請求響應爲可用行;N1和N2之間的網絡環境爲分區容錯性。這是正常運做的場景,也是理想的場景,然而現實是殘酷的,當錯誤發生的時候,一致性和可用性還有分區容錯性,是否能同時知足,仍是說要進行取捨呢?
做爲一個分佈式系統,它和單機系統的最大區別,就在於網絡,如今假設一種極端狀況,N1和N2之間的網絡斷開了,咱們要支持這種網絡異常,至關於要知足分區容錯性,能不能同時知足一致性和響應性呢?仍是說要對他們進行取捨。
假設在N1和N2之間網絡斷開的時候,有用戶向N1發送數據更新請求,那N1中的數據V0將被更新爲V1,因爲網絡是斷開的,因此分佈式系統同步操做M,因此N2中的數據依舊是V0;這個時候,有用戶向N2發送數據讀取請求,因爲數據尚未進行同步,應用程序沒辦法當即給用戶返回最新的數據V1,怎麼辦呢?
有二種選擇,第一,犧牲數據一致性,保證可用性。響應舊的數據V0給用戶;
第二,犧牲可用性,保證數據一致性。阻塞等待,直到網絡鏈接恢復,數據更新操做M完成以後,再給用戶響應最新的數據V1。
這個過程,證實了要知足分區容錯性的分佈式系統,只能在一致性和可用性二者中,選擇其中一個。
這種狀況在分佈式系統中幾乎是不存在的。首先在分佈式環境下,網絡分區是一個天然的事實。由於分區是必然的,因此若是捨棄P,意味着要捨棄分佈式系統。那也就沒有必要再討論CAP理論了。這也是爲何在前面的CAP證實中,咱們以系統知足P爲前提論述了沒法同時知足C和A。
好比咱們熟知的關係型數據庫,如My Sql和Oracle就是保證了可用性和數據一致性,可是他並非個分佈式系統。一旦關係型數據庫要考慮主備同步、集羣部署等就必需要把P也考慮進來。
若是一個分佈式系統不要求強的可用性,即允許系統停機或者長時間無響應的話,就能夠在CAP三者中保障CP而捨棄A。一個保證了CP而一個捨棄了A的分佈式系統,一旦發生網絡故障或者消息丟失等狀況,就要犧牲用戶的體驗,等待全部數據所有一致了以後再讓用戶訪問系統。
設計成CP的系統其實也很多,其中最典型的就是不少分佈式數據庫,他們都是設計成CP的。在發生極端狀況時,優先保證數據的強一致性,代價就是捨棄系統的可用性。如Redis、HBase等,還有分佈式系統中經常使用的Zookeeper也是在CAP三者之中選擇優先保證CP的。
要高可用並容許分區,則需放棄一致性。一旦網絡問題發生,節點之間可能會失去聯繫。爲了保證高可用,須要在用戶訪問時能夠立刻獲得返回,則每一個節點只能用本地數據提供服務,而這樣會致使全局數據的不一致性。
這種捨棄強一致性而保證系統的分區容錯性和可用性的場景和案例很是多。前面咱們介紹可用性的時候說到過,不少系統在可用性方面會作不少事情來保證系統的整年可用性能夠達到N個9,因此,對於不少業務系統來講,好比淘寶的購物,12306的買票。都是在可用性和一致性之間捨棄了一致性而選擇可用性。
你在12306買票的時候確定遇到過這種場景,當你購買的時候提示你是有票的(可是可能實際已經沒票了),你也正常的去輸入驗證碼,下單了。可是過了一會系統提示你下單失敗,餘票不足。這其實就是先在可用性方面保證系統能夠正常的服務,而後在數據的一致性方面作了些犧牲,會影響一些用戶體驗,可是也不至於形成用戶流程的嚴重阻塞。
可是,咱們說不少網站犧牲了一致性,選擇了可用性,這其實也不許確的。就好比上面的買票的例子,其實捨棄的只是強一致性。退而求其次保證了最終一致性。也就是說,雖然下單的瞬間,關於車票的庫存可能存在數據不一致的狀況,可是過了一段時間,仍是要保證最終一致性的。
對於多數大型互聯網應用的場景,主機衆多、部署分散,並且如今的集羣規模愈來愈大,因此節點故障、網絡故障是常態,並且要保證服務可用性達到N個9,即保證P和A,捨棄C(退而求其次保證最終一致性)。雖然某些地方會影響客戶體驗,但沒達到形成用戶流程的嚴重程度。
出現故障時,容許損失部分可用功能,保證核心功能可用。
容許系統中存在中間狀態,這個狀態不影響系統可用性。
通過一段時間後,全部節點數據都將會達到一致。
原文連接1:https://www.hollischuang.com/archives/663