大數(shù)據(jù)存儲(chǔ):分布式系統(tǒng)的事務(wù)處理
當(dāng)我們?cè)谏a(chǎn)線上用一臺(tái)服務(wù)器來(lái)提供數(shù)據(jù)服務(wù)的時(shí)候,我會(huì)遇到如下的兩個(gè)問(wèn)題:
(1)一臺(tái)服務(wù)器的性能不足以提供足夠的能力服務(wù)于所有的網(wǎng)絡(luò)請(qǐng)求。
(2)我們總是害怕我們的這臺(tái)服務(wù)器停機(jī),造成服務(wù)不可用或是數(shù)據(jù)丟失。
于是我們不得不對(duì)我們的服務(wù)器進(jìn)行擴(kuò)展,加入更多的機(jī)器來(lái)分擔(dān)性能上的問(wèn)題,以及來(lái)解決單點(diǎn)故障問(wèn)題。 通常,我們會(huì)通過(guò)兩種手段來(lái)擴(kuò)展我們的數(shù)據(jù)服務(wù):
(1)數(shù)據(jù)分區(qū):就是把數(shù)據(jù)分塊放在不同的服務(wù)器上(如:uid % 16,一致性哈希等)。
(2)數(shù)據(jù)鏡像:讓所有的服務(wù)器都有相同的數(shù)據(jù),提供相當(dāng)?shù)姆?wù)。
對(duì)于第一種情況,我們無(wú)法解決數(shù)據(jù)丟失的問(wèn)題,單臺(tái)服務(wù)器出問(wèn)題時(shí),會(huì)有部分?jǐn)?shù)據(jù)丟失。所以,數(shù)據(jù)服務(wù)的高可用性只能通過(guò)第二種方法來(lái)完成——數(shù)據(jù)的冗余存儲(chǔ)(一般工業(yè)界認(rèn)為比較安全的備份數(shù)應(yīng)該是3份,如:Hadoop和Dynamo)。
但是,加入更多的機(jī)器,會(huì)讓我們的數(shù)據(jù)服務(wù)變得很復(fù)雜,尤其是跨服務(wù)器的事務(wù)處理,也就是跨服務(wù)器的數(shù)據(jù)一致性。這個(gè)是一個(gè)很難的問(wèn)題。 讓我們用最經(jīng)典的Use Case:“A帳號(hào)向B帳號(hào)匯錢”來(lái)說(shuō)明一下,熟悉RDBMS事務(wù)的都知道從帳號(hào)A到帳號(hào)B需要6個(gè)操作:
1)從A帳號(hào)中把余額讀出來(lái)。
2)對(duì)A帳號(hào)做減法操作。
3)把結(jié)果寫回A帳號(hào)中。
4)從B帳號(hào)中把余額讀出來(lái)。
5)對(duì)B帳號(hào)做加法操作。
6)把結(jié)果寫回B帳號(hào)中。
為了數(shù)據(jù)的一致性,這6件事,要么都成功做完,要么都不成功,而且這個(gè)操作的過(guò)程中,對(duì)A、B帳號(hào)的其它訪問(wèn)必需鎖死,所謂鎖死就是要排除其它的讀寫操作,不然會(huì)有臟數(shù)據(jù)的問(wèn)題,這就是事務(wù)。那么,我們?cè)诩尤肓烁嗟臋C(jī)器后,這個(gè)事情會(huì)變得復(fù)雜起來(lái):
1)在數(shù)據(jù)分區(qū)的方案中:如果A帳號(hào)和B帳號(hào)的數(shù)據(jù)不在同一臺(tái)服務(wù)器上怎么辦?我們需要一個(gè)跨機(jī)器的事務(wù)處理。也就是說(shuō),如果A的扣錢成功了,但B的加錢不成功,我們還要把A的操作給回滾回去。這在跨機(jī)器的情況下,就變得比較復(fù)雜了。
2)在數(shù)據(jù)鏡像的方案中:A帳號(hào)和B帳號(hào)間的匯款是可以在一臺(tái)機(jī)器上完成的,但是別忘了我們有多臺(tái)機(jī)器存在A帳號(hào)和B帳號(hào)的副本。如果對(duì)A帳號(hào)的匯錢有兩個(gè)并發(fā)操作(要匯給B和C),這兩個(gè)操作發(fā)生在不同的兩臺(tái)服務(wù)器上怎么辦?也就是說(shuō),在數(shù)據(jù)鏡像中,在不同的服務(wù)器上對(duì)同一個(gè)數(shù)據(jù)的寫操作怎么保證其一致性,保證數(shù)據(jù)不沖突?
同時(shí),我們還要考慮性能的因素,如果不考慮性能的話,事務(wù)得到保證并不困難,系統(tǒng)慢一點(diǎn)就行了。除了考慮性能外,我們還要考慮可用性,也就是說(shuō),一臺(tái)機(jī)器沒(méi)了,數(shù)據(jù)不丟失,服務(wù)可由別的機(jī)器繼續(xù)提供。 于是,我們需要重點(diǎn)考慮下面的這么幾個(gè)情況:
1)容災(zāi):數(shù)據(jù)不丟、結(jié)點(diǎn)的Failover
2)數(shù)據(jù)的一致性:事務(wù)處理
3)性能:吞吐量 、 響應(yīng)時(shí)間
前面說(shuō)過(guò),要解決數(shù)據(jù)不丟,只能通過(guò)數(shù)據(jù)冗余的方法,就算是數(shù)據(jù)分區(qū),每個(gè)區(qū)也需要進(jìn)行數(shù)據(jù)冗余處理。這就是數(shù)據(jù)副本:當(dāng)出現(xiàn)某個(gè)節(jié)點(diǎn)的數(shù)據(jù)丟失時(shí)可以從副本讀到,數(shù)據(jù)副本是分布式系統(tǒng)解決數(shù)據(jù)丟失異常的唯一手段。所以,在這篇文章中,簡(jiǎn)單起見(jiàn),我們只討論在數(shù)據(jù)冗余情況下考慮數(shù)據(jù)的一致性和性能的問(wèn)題。簡(jiǎn)單說(shuō)來(lái):
1)要想讓數(shù)據(jù)有高可用性,就得寫多份數(shù)據(jù)。
2)寫多份的問(wèn)題會(huì)導(dǎo)致數(shù)據(jù)一致性的問(wèn)題。
3)數(shù)據(jù)一致性的問(wèn)題又會(huì)引發(fā)性能問(wèn)題。
這就是軟件開(kāi)發(fā),按下了葫蘆起了瓢。