關(guān)于分布式系統(tǒng)的數(shù)據(jù)一致性問題(四)
在前面三篇文章中,介紹了關(guān)于分布式系統(tǒng)中數(shù)據(jù)一致性的問題,這一篇主要介紹CAP定理以及自己對CAP定理的了解。
CAP定理是2000年,由 Eric Brewer 提出來的
Brewer認(rèn)為在分布式的環(huán)境下設(shè)計(jì)和部署系統(tǒng)時(shí),有3個(gè)核心的需求,以一種特殊的關(guān)系存在。這里的分布式系統(tǒng)說的是在物理上分布的系統(tǒng),比如我們常見的web系統(tǒng)。
這3個(gè)核心的需求是:Consistency,Availability和Partition Tolerance,賦予了該理論另外一個(gè)名字 - CAP。
Consistency:一致性,這個(gè)和數(shù)據(jù)庫ACID的一致性類似,但這里關(guān)注的所有數(shù)據(jù)節(jié)點(diǎn)上的數(shù)據(jù)一致性和正確性,而數(shù)據(jù)庫的ACID關(guān)注的是在在一個(gè)事務(wù)內(nèi),對數(shù)據(jù)的一些約束。
Availability:可用性,關(guān)注的在某個(gè)結(jié)點(diǎn)的數(shù)據(jù)是否可用,可以認(rèn)為某一個(gè)節(jié)點(diǎn)的系統(tǒng)是否可用,通信故障除外。
Partition Tolerance:分區(qū)容忍性,是否可以對數(shù)據(jù)進(jìn)行分區(qū)。這是考慮到性能和可伸縮性。
為什么不能完全保證這個(gè)三點(diǎn)了,個(gè)人覺得主要是因?yàn)橐坏┻M(jìn)行分區(qū)了,就說明了必須節(jié)點(diǎn)之間必須進(jìn)行通信,涉及到通信,就無法確保在有限的時(shí)間內(nèi)完成指定的行文,如果要求兩個(gè)操作之間要完整的進(jìn)行,因?yàn)樯婕暗酵ㄐ?,肯定存在某一個(gè)時(shí)刻只完成一部分的業(yè)務(wù)操作,在通信完成的這一段時(shí)間內(nèi),數(shù)據(jù)就是不一致性的。如果要求保證一致性,那么就必須在通信完成這一段時(shí)間內(nèi)保護(hù)數(shù)據(jù),使得任何訪問這些數(shù)據(jù)的操作不可用。
如果想保證一致性和可用性,那么數(shù)據(jù)就不能夠分區(qū)。一個(gè)簡單的理解就是所有的數(shù)據(jù)就必須存放在一個(gè)數(shù)據(jù)庫里面,不能進(jìn)行數(shù)據(jù)庫拆分。這個(gè)對于大數(shù)據(jù)量,高并發(fā)的互聯(lián)網(wǎng)應(yīng)用來說,是不可接受的。
我們可以拿一個(gè)簡單的例子來說明:假設(shè)一個(gè)購物系統(tǒng),賣家A和賣家B做了一筆交易100元,交易成功了,買家把錢給賣家。
這里面存在兩張表的數(shù)據(jù):Trade表Account表 ,涉及到三條數(shù)據(jù)Trade(100),Account A ,Account B
假設(shè) trade表和account表在一個(gè)數(shù)據(jù)庫,那么只需要使用數(shù)據(jù)庫的事務(wù),就可以保證一致性,同時(shí)不會(huì)影響可用性。但是隨著交易量越來越大,我們可以考慮按照業(yè)務(wù)分庫,把交易庫和account庫單獨(dú)分開,這樣就涉及到trade庫和account庫進(jìn)行通信,也就是存在了分區(qū),那么我們就不可能同時(shí)保證可用性和一致性。
我們假設(shè)初始狀態(tài)
trade(buyer,seller,tradeNo,status) = trade(A,B,20121001,I)
account(accountNo,balance) = account(A,300)
account(accountNo,balance) = account(B,10)
在理想情況下,我們期望的狀態(tài)是
trade(buyer,seller,tradeNo,status) = trade(A,B,20121001,S)
account(accountNo,balance) = account(A,200)
account(accountNo,balance) = account(B,110)
但是考慮到一些異常情況
假設(shè)在trade(20121001,S)更新完成之前,帳戶A進(jìn)行扣款之后,帳戶A進(jìn)行了另外一筆300款錢的交易,把錢消費(fèi)了,那么就存在一個(gè)狀態(tài)
trade(buyer,seller,tradeNo,status) = trade(A,B,20121001,S)
account(accountNo,balance) = account(A,0)
account(accountNo,balance) = account(B,10)
產(chǎn)生了數(shù)據(jù)不一致的狀態(tài)
由于這個(gè)涉及到資金上的問題,對資金要求比較高,我們必須保證一致性,那么怎么辦,只能在進(jìn)行trade(A,B,20121001)交易的時(shí)候,對于任何A的后續(xù)交易請求trade(A,X,X),必須等到A完成之后,才能夠進(jìn)行處理,也就是說在進(jìn)行trade(A,B,20121001)的時(shí)候,Account(A)的數(shù)據(jù)是不可用的。
任何架構(gòu)師在設(shè)計(jì)分布式的系統(tǒng)的時(shí)候,都必須在這三者之間進(jìn)行取舍。首先就是是否選擇分區(qū),由于在一個(gè)數(shù)據(jù)分區(qū)內(nèi),根據(jù)數(shù)據(jù)庫的ACID特性,是可以保證一致性的,不會(huì)存在可用性和一致性的問題,唯一需要考慮的就是性能問題。對于可用性和一致性,大多數(shù)應(yīng)用就必須保證可用性,畢竟是互聯(lián)網(wǎng)應(yīng)用,犧牲了可用性,相當(dāng)于間接的影響了用戶體驗(yàn),而唯一可以考慮就是一致性了。
犧牲一致性
對于犧牲一致性的情況最多的就是緩存和數(shù)據(jù)庫的數(shù)據(jù)同步問題,我們把緩存看做一個(gè)數(shù)據(jù)分區(qū)節(jié)點(diǎn),數(shù)據(jù)庫看作另外一個(gè)節(jié)點(diǎn),這兩個(gè)節(jié)點(diǎn)之間的數(shù)據(jù)在任何時(shí)刻都無法保證一致性的。在web2.0這樣的業(yè)務(wù),開心網(wǎng)來舉例子,訪問一個(gè)用戶的信息的時(shí)候,可以先訪問緩存的數(shù)據(jù),但是如果用戶修改了自己的一些信息,首先修改的是數(shù)據(jù)庫,然后在通知緩存進(jìn)行更新,這段期間內(nèi)就會(huì)導(dǎo)致的數(shù)據(jù)不一致,用戶可能訪問的是一個(gè)過期的緩存,而不是最新的數(shù)據(jù)。但是由于這些業(yè)務(wù)對一致性的要求比較高,不會(huì)帶來太大的影響。
異常錯(cuò)誤檢測和補(bǔ)償
還有一種犧牲一致性的方法就是通過一種錯(cuò)誤補(bǔ)償機(jī)制來進(jìn)行,可以拿上面購物的例子來說,假設(shè)我們把業(yè)務(wù)邏輯順序調(diào)整一下,先扣買家錢,然后更新交易狀態(tài),在把錢打給賣家
我們假設(shè)初始狀態(tài)
account(accountNo,balance) = account(A,300)
account(accountNo,balance) = account(B,10)
trade(buyer,seller,tradeNo,status) = trade(A,B,20121001,I)
那么有可能出現(xiàn)
account(accountNo,balance) = account(A,200)
trade(buyer,seller,tradeNo,status) = trade(A,B,20121001,S)
account(accountNo,balance) = account(B,10)
那么就出現(xiàn)了A扣款成功,交易狀態(tài)也成功了,但是錢沒有打給B,這個(gè)時(shí)候可以通過一個(gè)時(shí)候的異常恢復(fù)機(jī)制,把錢打給B,最終的情況保證了一致性,在一定時(shí)間內(nèi)數(shù)據(jù)可能是不一致的,但是不會(huì)影響太大。
兩階段提交協(xié)議
當(dāng)然,還有一種方式就是我另外一篇文章里面《X/Open DTP-分布式事務(wù)模型》里面說的,但是再第一階段和第二階段之間,數(shù)據(jù)也可不能是一致性的,也可能出現(xiàn)同樣的情況導(dǎo)致異常。而且DTP的分布式事務(wù)模型 限制太多,例如必須有實(shí)現(xiàn)其功能的相關(guān)的容器支持,并且資源管理器也必須實(shí)現(xiàn)了XA規(guī)范。限制比較多。
國外有的架構(gòu)師有兩種方案去解決CAP的限制,但是也是比較適合特定的業(yè)務(wù),而沒有通用的解決方案,
探知分區(qū)->分區(qū)內(nèi)操作->事后補(bǔ)償

就是上面介紹的異常檢測恢復(fù)機(jī)制,這種機(jī)制其實(shí)還是有限制,
首先對于分區(qū)檢測操作,不同的業(yè)務(wù)涉及到的分區(qū)操作可能不一樣
分區(qū)內(nèi)操作限制:不同的業(yè)務(wù)對應(yīng)的約束不一致
事后補(bǔ)償:由于業(yè)務(wù)約束不一樣,補(bǔ)償方式也不一樣。
所以這只能作為一種思想,不能做一個(gè)通用的解決方案
還有就是ebay使用的BASE 思想((basically available, soft state, eventually consistent),這個(gè)比較有意思,有時(shí)間在寫吧。
14年互聯(lián)網(wǎng)技術(shù)、產(chǎn)品、運(yùn)營經(jīng)驗(yàn),前支付寶技術(shù)專家,互金創(chuàng)業(yè)公司CTO,大令保事業(yè)部總經(jīng)理。
在互金領(lǐng)域有比較強(qiáng)的產(chǎn)品以及運(yùn)營經(jīng)驗(yàn),尤其擅長用戶增長、轉(zhuǎn)化、運(yùn)營上的經(jīng)驗(yàn),兼具技術(shù)、產(chǎn)品、運(yùn)營思維。
目前是云貓?jiān)鲩L實(shí)驗(yàn)室 創(chuàng)始人
團(tuán)隊(duì)成員來自阿里等國內(nèi)知名互聯(lián)網(wǎng)公司,曾在互聯(lián)網(wǎng)金融、互聯(lián)網(wǎng)保險(xiǎn)、企業(yè)級(jí)SaaS等項(xiàng)目中負(fù)責(zé)用戶增長,團(tuán)隊(duì)管理的工作,擁有豐富的一線流量增長經(jīng)驗(yàn)與實(shí)操手段。
歡迎關(guān)注我們,用技術(shù)驅(qū)動(dòng)增長
浙公網(wǎng)安備 33010602011771號(hào)