定義 在一個分散式系統(指系統中的節點互相連接並共用數據)中,當涉及讀寫操作時,只能保證一致性 (Consistency)、可用性 (Availability)、分區容錯性 (Partition Tolerance)三者中的兩個,另外一個必須被犧牲。 一致性:CAP中的C和ACID 中的C不是一個含 ...
定義
在一個分散式系統(指系統中的節點互相連接並共用數據)中,當涉及讀寫操作時,只能保證一致性 (Consistency)、可用性 (Availability)、分區容錯性 (Partition Tolerance)三者中的兩個,另外一個必須被犧牲。
- 一致性:CAP中的C和ACID 中的C不是一個含義,ACID 中的C是指資料庫中的數據滿足一定的約束條件。而CAP中的C是指線性一致性,即:客戶端向系統寫入什麼,那麼讀出來的也會是什麼。也就是要保證客戶端讀取到的數據一定是上次寫入的最新數據。
- 可用性:指系統中的部分節點出現故障後,系統能否還能對外提供完全可用的服務;
- 分區容錯性:指是否允許系統中的節點之間無法通信,也就是無法互相連接;
適用場景
那麼什麼樣的分散式系統是節點之間互聯並共用數據呢?
典型的場景就是資料庫的主從集群,一個資料庫集群有一個主,多個從,主從之間會進行數據複製。所以適用於CAP原理。
那麼如果我現在是一個Redis的集群,集群中每台機器存儲不同的數據,集群中每台機器不需要複製和傳遞數據,那麼就不屬於CAP原理的討論範圍。同理,如果是A,B兩個不同的業務系統,比如招行賬號A給工行賬號B轉賬100元,由於招行和工行是兩個不同的業務系統,業務上隔離,且他們之間也沒有共用的數據,從而也不屬於CAP原理的討論範圍。
場景方案選擇
- 傳統資料庫主從集群:如果當前是一個現在是一個主從複製的資料庫集群,同一條數據會在主從資料庫上都存儲,那麼當存在主從資料庫之間網路斷開時,我們確實只能要麼選擇A放棄C,要麼選擇C放棄A。選擇A放棄C,就是客戶端讀取到的可能不是最新的數據,但是系統持續可用;選擇C放棄A,就是讓系統服務不可用,客戶端自然就不會認為數據不一致了。
- 分散式資料庫,如阿裡的OceanBase,這種資料庫也是一個主從的集群,但是主從節點往往使用Paxos/Raft等副本一致性協議,做到整個資料庫系統,在部分節點發生故障時,也能在很短的時間內自動重新選主,選出一個新的主從集群的資料庫系統。在重新選主的過程中,系統不可用,相當於放棄了A,而一旦選出新的主之後,系統又繼續可用,且數據對外是線性一致的。相比傳統的資料庫主從集群,分散式資料庫由於可以在遇到網路分區導致資料庫主從節點之間無法互聯時,可以快速選出新的主,然後快速恢復,所以架構設計上和用戶體驗上,要好很多。但是系統設計的複雜度也非常高。
分散式事務
通過上面的分析,我們知道CAP中的數據一致性,本質上是為了維護同一個數據的不同副本之間的一致性。而更多的時候,我們要解決的是不同業務系統之間的數據一致性,即數據之間總是應該滿足規定的業務規則。典型的場景比如有跨行轉賬、訂單和減庫存。這種場景,由於沒有數據共用的特征,所以不適用於CAP。比如A銀行的賬戶給B銀行的賬戶轉賬100元,那麼轉賬前後,兩個賬戶的錢加起來應該不變。也就是A扣款了,B就必須加款。那麼這種場景如何解決呢?一般的做法是採用分散式事務,常見的分散式事務的解決方案有:2PC\3PC、TCC、基於分散式MQ+本地消息、分散式MQ事務消息、Sagas。