前言
最近在工作之余看了一些分布式系統的博客和一點書本知識,從理論上了解了一些分布式系統的基本知識。給我最深的感覺就是所有的軟件技術和架構都是隨着業務的不斷發展和底層技術的更新才有機會一步步的深入。特別是學習cap和base時,了解到分布式事務與傳統DB事務ACID的區別(其實分布式事務和傳統DB事務不是一個層面的東西但是感覺思想上還是有一些共同之處的)。現在的分布式系統也都是由最初的集中式系統一步步發展過來的。
在這里總結一下最近學的一些基礎吧~~
集中式與分布式
很容易理解:
- 集中式:一台或多態住計算機組成中心節點,數據集中存儲於中心節點上,並且系統所有的業務單元都集中部署在這個中心節點上,並在其上處理系統所有功能。
- 其實我的理解就是說所有的業務和邏輯都在這個中心節點上完成,其他的客戶端就負責輸入和輸出就可以了。
- 分布式:分布式系統是一個硬件或軟件組件分布在不同的網絡計算機上,彼此之間僅僅通過消息傳遞進行通信和協調的系統。
- 這是經典的分布式著作《分布式系統概念與設計》中的定義。其實在我的理解里,就是把一個大的系統拆分成很多個業務模塊,並部署在多台網絡計算機上。就是把集中式的中心節點拆分為多個節點去完成單個中心節點的工作。
- 分布式系統的幾個特點:
- 分布性:分布式系統的多個節點或者說多個模塊在空間上是隨意分布的。
- 對等性:系統模塊的多個節點沒有主從之分。其實這里我理解的沒有主從之分並不是說完完全全沒有主節點和從節點,而是在任何時候,如果有主節點,且主節點發生了不可用的情況下,能有一定的方法讓別的節點去取代它,這樣的話系統中就沒有一個節點是所謂的特殊的,而所有的節點都是一樣的可以互相替換的,這某種程度上應該就是分布式系統中的副本的概念。而副本的話應該是分為服務副本和數據副本的,因為服務和數據都可能會出現不可用的現象,所以必須要有副本去保持系統可用。
- 並發性:很好理解,分布式系統中程序的並發性操作和對數據的並發訪問是很常見的。其實也因為並發性,如何做到高效准確也就成為了分布式系統的一個難題。
- 缺乏全局時鍾:同樣的,因為分布式系統部署在多台網絡計算機上,由於網絡的存在很難定義事務的先后順序。也就是說分布式系統缺少全局的始終順序控制。之前在學習的時候看到過分布式全局唯一ID可以解決部分問題,之后可以再看看總結一下。我目前了解的分布式全局ID的生成有UUID和SNOWFLAKE算法,但是具體的底層還不是很清楚。
- 故障總是會發生:分布式系統相較集中式系統更容易發生故障,且在系統設計時考慮到的西昌在實際中是一定會發生的,所以必須要解決。(當然,如果是業務或者需求允許的可以考慮一定程度的放寬。)
分布式系統的問題
進程或節點之間的通信異常
其實如在Zookeeper學習(一)中描述的一樣,導致分布式系統通信異常的根本罪魁禍首就在於網絡!因為網絡本身就是不可靠的。與單機系統不同的是,由於分布式系統中網絡通信的存在,會導致系統之間的調用存在相對較大的延遲(可達到內存訪問延遲的百倍)。而且網絡隨時會出現波動的情況,因此消息丟失和延遲會變得很普遍。
網絡分區
由於網絡發生異常,導致分布式系統中部分節點之間的網絡延時不斷增大,導致所有節點中只有部分節點能互相正常通信,而其他的不能。這其實就是所謂的“腦裂”。最差的情況甚至會出現多個局部小集群的情況。
三態
三態即成功,失敗,超時。
單機系統中調用服務成功失敗很明顯,但是在分布式系統中很明顯,因為存在網絡的因素,在調用服務失敗的情況下可能並不一定是因為沒有調用服務成功。
- 調用服務確實沒有成功,網絡請求沒有發送到接收方。
- 調用服務成功,但是在返回響應時出現了消息丟失。
這時候就需要針對不同的業務進行處理了。結合我們之前做的業務,我們的系統中處理辦法是回寫時會讓服務發送接收OK的標志,如果沒有收到OK,那么就會一直發,因為回寫的接收方在邏輯里支持刪除不存在的元素(其實就是不刪),只有收到了OK才會把回寫的內容從Redis里刪掉。這樣就保證了回寫一定會成功。
節點故障
很好理解,每一台機器都是會出問題的,如何保證在部分節點出現問題時整個系統仍然可用,是分布式系統里永恆不變的問題!
從ACID到CAP/BASE
ACID
ACID是傳統數據庫中事務的特征,即原子性,一致性,隔離性和持久性。
- 原子性:指事務必須是一個原子的操作單元。也就是說事務要么全部執行成功,要么不執行,如果執行過程中失敗那么就回滾到最初的狀態。
- 一致性:事務的執行不可以破壞數據庫數據的完整性和一致性。也就是說事務在執行前后,數據庫都必須處於一致性的狀態。其實當初學數據庫的時候一開始並不太理解為什么既然有原子性了,事務要么執行完要么不執行,為啥還會出現一致性的問題。后來才知道是因為多個事務並發執行的時候,很容易出現a事務做了x=1的操作,然后b事務又做了x=0的操作,就相當於b事務直接把a事務的操作給覆蓋了,這就破壞了數據庫的一致性。
- 隔離性:並發壞境中,事務是互相隔離的,一個事物的執行不能被其他事務干擾。這就是為了防止上面說的一致性的問題。而數據庫里規定了4個隔離級別:
- 讀未提交:會出現臟讀,不可重復讀,幻讀問題。隔離級別最低。
- 讀提交:解決臟讀,但不可重復讀,幻讀還是會有。
- 可重復讀:會存在幻讀問題,但前兩個問題不會有。
- 序列化:相當於事務順序執行,不會有上述問題,但並發程度最低,效率也最低。
- mysql里利用了MVCC和鎖的機制實現了隔離級別,但是這部分我也只是知道個大概,底層的實現原理還沒有來得及深究,之前看了幾篇博客記錄下,之后深入學習Mysql的時候這部分要深入學習下。
- Mysql數據庫事務的隔離級別和鎖的實現原理分析
- [MySQL的四種事務隔離級別](https://www.cnblogs.com/huanongying/p/7021555.html)
- MySQL事務隔離級別的實現原理
- Mysql鎖詳解
- 持久性:一個事物一旦提交,它對數據庫中對應數據的狀態變更應該是永久性的。也就是說事務一旦成功結束,那么它對數據庫所做的更新必須被永久保存下來。
CAP
CAP理論是針對分布式事務的一套理論。所謂分布式事務就是事物的參與者,支持十五的服務器,資源服務器以及事務管理器分別位於分布式系統的不同節點上。通常一個分布式事務會涉及對多個數據源或業務系統的操作。
CAP指的是一個分布式系統不可能同時滿足一致性,可用性和分區容錯性這三個基本要求,最多只能同時滿足其中的兩項。
- 一致性:在分布式環境中,一致性是指數據在多個副本之間是否能夠保持一致的特性。也就是說,當一個系統在數據一致的狀態下執行更新操作后,應該保證系統的數據仍然出於一致的狀態。
- 分布式系統里,如果數據副本分布在不同分布式節點上,若對第一個節點的數據進行了更新操作並且更新成功后,卻沒有使得第二個節點上的數據得到相應更新,那么如果系統是從第二個節點上讀的數據,那么就會讀到老數據,就出現了不一致的情況。
- 分布式系統的一致性和單機事務的一致性有很大的區別,之前自己一直能感覺到不一樣但是很難用理論化的語言描述出來,ACID的C與CAP的C區別這篇博客介紹的非常非常好,可以看!!!
- 可用性:系統提供的服務必須一直處於可用的狀態,對於用戶的每一個操作請求總是能夠在有限的時間內返回結果。有限的時間某種程度上指的是系統的反應時間不可以超過用戶的忍耐程度,返回結果則值得是系統對於用戶的請求必須要返回一個可以接受的結果。
- 分區容錯性:分布式系統因為是依賴網絡的,所以難免會出現遇到網絡分區故障的時候,而這個時候仍然要保證能對外提供一致性和可用性的服務,除非整個網絡癱瘓。
- 之前我一直分不清可用性和分區容錯性的區別,感覺只要高可用了不就滿足了容錯性了么。。。但是參考了很多資料之后才發現分區容錯性和可用性,一致性的關系更像是因果(不一定准確)的關系。正是因為分區的存在,所以在需要解決一致性和可用性的問題。
- CAP理論的P知乎上的這個回答是我認為解釋的最通俗易懂的一篇。
- CAP里的P ,CAP, ACID ,分布式系統設計系列 -- 基本原理及高可用策略, 分布式CAP理論的理解, 這幾篇都很好,可以參考。
BASE
BASE = Basically Available + Soft state + Eventually consistent。
- 基本可用:分布式系統出現不可預知故障時,允許損失部分可用性。
- 響應時間損失。0.5s-->2s
- 功能損失。雙十一淘寶扛不住了把評論服務先降級掉。
- 弱狀態:允許系統數據存在中間狀態,並認為該中間狀態的存在不會影響系統整體可用性,即允許系統在不同節點的數據副本之間進行數據同步的過程存在延時。
- 最終一致性:系統中所有數據副本,在經過一段時間同步后,最終能打到一個一致的狀態。
- 最終一致性實際上是一種特殊的弱一致性。
- 因果一致性(Casual Consistency):A進程更新完后通知B,那么B對該數據項的訪問應該能獲取到A更新后的最新值,且B如果要更新該數據,必須基於進程A更新后的值。
- 讀己寫(Read you writes):A更新一個數據向后,自己總是能訪問到更新過的最新值。是一種特殊的因果一致性。
- 會話一致性(Session Consistency):對系統數據的訪問過程狂頂在一個繪畫中,系統能保證在同一個有效的會話中實現Read your writes。即更新操作后,客戶端能在同一個繪畫中適中讀取到該數據項的最新值。
- 單調讀一致性(Monotonic read consistency):如果一個進程從系統中讀取出一個數據項的某一個值后,那么系統對於該進程后續的任何數據訪問都不應該返回更舊的值。
- 單調寫一致性(Monotonic write consistency):一個系統需要能夠保證同一個進程的寫操作被順序執行。
- 數據庫的主備一般都采用最終一致性的策略。有兩種方式去實現,即同步和異步。同步的方式就是事務完成后主備之間數據就會進行同步,異步的方式備數據庫的更新會有一定時間的延遲,但是效率會更高一些。
