分布式事務(wù)
分布式事務(wù)是個(gè)歷久彌新的話(huà)題,對(duì)分庫(kù)分表,分布式事務(wù)的目的是保障分庫(kù)數(shù)據(jù)一致性,而跨庫(kù)事務(wù)會(huì)遇到各種不可控制的問(wèn)題,如個(gè)別節(jié)點(diǎn)永久性宕機(jī),如此像單機(jī)事務(wù)一樣的ACID是無(wú)法奢望的。另外,業(yè)界著名的CAP理論也告訴我們,對(duì)分布式系統(tǒng),需要將數(shù)據(jù)一致性和系統(tǒng)可用性,分區(qū)容忍性放在天平上一起考慮。
兩階段提交協(xié)議(簡(jiǎn)稱(chēng)2PC)是實(shí)現(xiàn)分布式事務(wù)較為經(jīng)典的方案,適用于中間件這種數(shù)據(jù)節(jié)點(diǎn)無(wú)耦合的場(chǎng)景。2PC的核心原理是通過(guò)提交分階段和記日志的方式,記錄下事務(wù)提交所處的階段狀態(tài),在組件宕機(jī)重啟后,可通過(guò)日志恢復(fù)事務(wù)提交的階段狀態(tài),并在這個(gè)狀態(tài)節(jié)點(diǎn)重試,如coordinator重啟后,通過(guò)日志可以確定提交處于prepare還是prepareAll狀態(tài),若是前者,說(shuō)明有節(jié)點(diǎn)可能沒(méi)有prepare成功,或所有節(jié)點(diǎn)prepare成功但是還沒(méi)有下發(fā)commit,狀態(tài)恢復(fù)后給所有節(jié)點(diǎn)下發(fā)rollback;若是prepareAll狀態(tài),需要給所有節(jié)點(diǎn)下發(fā)commit,數(shù)據(jù)庫(kù)節(jié)點(diǎn)需要保證commit冪等。與很多其他一致性協(xié)議相同,2PC保障的是最終一致性。
2PC整個(gè)過(guò)程如下圖所示:
2PC過(guò)程
在DDB中,DBI和Proxy組件都作為coordinator存在,2PC實(shí)現(xiàn)時(shí),記錄prepare和prepareAll的日志必須sync,以保障重啟后恢復(fù)的狀態(tài)是正確的,而coordinator最后的commit日志主要作用是回收之前日志,可異步執(zhí)行。
由于2PC要求coordinator記日志,事務(wù)吞吐率受到磁盤(pán)IO性能的約束,為此DDB實(shí)現(xiàn)了group io優(yōu)化,可極大程度提升2P C的吞吐率。2PC本質(zhì)上說(shuō)是一種阻塞式協(xié)議,兩階段提交過(guò)程需要大量線程資源,因此CPU和磁盤(pán)都有額外消耗,與單機(jī)事務(wù)相比,2PC在響應(yīng)時(shí)間和吞吐率上會(huì)相差很多,從CAP的角度出發(fā),可以認(rèn)為2PC在一定程度上成全了C,犧牲了A。
另外,目前MySQL最流行的5.5和5.6版本中,XA事務(wù)日志無(wú)法replicate到從節(jié)點(diǎn),這意外著主庫(kù)一旦宕機(jī),切換到從庫(kù)后,XA的狀態(tài)會(huì)丟失,可能造成數(shù)據(jù)不一致,這方面MySQL 5.7已經(jīng)有所改善。
雖然2PC有諸多不足,我們依然認(rèn)為在DDB中有實(shí)現(xiàn)價(jià)值,DDB作為中間件,其迭代周期要比數(shù)據(jù)庫(kù)這種底層服務(wù)頻繁很多,若沒(méi)有2PC,一次更新或重啟就可能造成應(yīng)用數(shù)據(jù)不一致。從應(yīng)用角度看,分布式事務(wù)的現(xiàn)實(shí)場(chǎng)景常常是無(wú)法規(guī)避的,在有能力給出其他解決方案前,2PC也是一個(gè)不錯(cuò)的選擇。
對(duì)購(gòu)物轉(zhuǎn)賬等電商和金融業(yè)務(wù),中間件層的2PC最大的問(wèn)題在于業(yè)務(wù)不可見(jiàn),一旦出現(xiàn)不可抗力或意想不到的一致性破壞,如數(shù)據(jù)節(jié)點(diǎn)永久性宕機(jī),業(yè)務(wù)難以根據(jù)2PC的日志進(jìn)行補(bǔ)償。金融場(chǎng)景下,數(shù)據(jù)一致性是命根,業(yè)務(wù)需要對(duì)數(shù)據(jù)有百分之百的掌控力,建議使用TCC這類(lèi)分布式事務(wù)模型,或基于消息隊(duì)列的柔性事務(wù)框架,這兩種方案都實(shí)現(xiàn)在業(yè)務(wù)層,業(yè)務(wù)開(kāi)發(fā)者具有足夠掌控力,可以結(jié)合SOA框架來(lái)架構(gòu)。原理上說(shuō),這兩種方案都是大事務(wù)拆小事務(wù),小事務(wù)變本地事務(wù),最后通過(guò)冪等的retry來(lái)保障最終一致性。
彈性擴(kuò)縮容
分庫(kù)分表數(shù)據(jù)庫(kù)中,在線數(shù)據(jù)遷移也是核心需求,會(huì)用在以下兩種場(chǎng)景:
- 數(shù)據(jù)節(jié)點(diǎn)彈性擴(kuò)容
隨著應(yīng)用規(guī)模不斷增長(zhǎng),DDB現(xiàn)有的分庫(kù)可能有一天不足以支撐更多數(shù)據(jù),要求DDB的數(shù)據(jù)節(jié)點(diǎn)具有在線彈性擴(kuò)容的能力,而新節(jié)點(diǎn)加入集群后,按照不同的sharding策略,可能需要將原有一些數(shù)據(jù)遷入新節(jié)點(diǎn),如hash分區(qū),也有可能不需要在線數(shù)據(jù)遷移,如一些場(chǎng)景下的range分區(qū)。無(wú)論如何,具備在線數(shù)據(jù)遷移是DDB支持彈性擴(kuò)容的前提。
- 數(shù)據(jù)重分布
開(kāi)發(fā)者在使用DDB過(guò)程中,有時(shí)會(huì)陷入困局,比如一些表的分區(qū)字段一開(kāi)始沒(méi)考慮清楚,在業(yè)務(wù)已經(jīng)初具規(guī)模后才明確應(yīng)該選擇其他字段。又如一些表一開(kāi)始認(rèn)為數(shù)據(jù)量很小,單節(jié)點(diǎn)分布足以,而隨著業(yè)務(wù)變化,需要轉(zhuǎn)變?yōu)槎喙?jié)點(diǎn)sharding。這兩種場(chǎng)景都體現(xiàn)了開(kāi)發(fā)者對(duì)DDB在線數(shù)據(jù)遷移功能的潛在需求。
無(wú)論是彈性擴(kuò)容,還是表重分布,都可當(dāng)做DDB以表或庫(kù)為單位的一次完整在線數(shù)據(jù)遷移??煞譃閮蓚€(gè)階段:全量遷移和增量遷移,全量遷移是將原庫(kù)或原表中需要遷移的數(shù)據(jù)dump出來(lái),并使用工具按照分區(qū)策略 apply到新庫(kù)新表中。增量遷移是要將全量遷移過(guò)程中產(chǎn)生的增量數(shù)據(jù)更新按照分區(qū)策略apply到新庫(kù)新表。