近幾年,隨著移動(dòng)互聯(lián)網(wǎng)的發(fā)展、云計(jì)算的普及和各種新業(yè)務(wù)的出現(xiàn),數(shù)據(jù)呈現(xiàn)爆發(fā)式增長(zhǎng),給整個(gè)業(yè)務(wù)系統(tǒng)帶來(lái)了越來(lái)越大的挑戰(zhàn),特別是對(duì)于底層數(shù)據(jù)存儲(chǔ)系統(tǒng)。完美的高可用系統(tǒng),是所有公司理想的追求。如果只從應(yīng)用層和緩存層看高可用問(wèn)題,是比較容易解決的。對(duì)于應(yīng)用層來(lái)說(shuō),根據(jù)業(yè)務(wù)特點(diǎn)可以很方便地設(shè)計(jì)成無(wú)狀態(tài)的服務(wù),在大多數(shù)互聯(lián)網(wǎng)公司中,在業(yè)務(wù)層的上層使用動(dòng)態(tài)DNS、LVS、HAProxy等負(fù)載均衡組件,配合Docker和Kubernetes實(shí)現(xiàn)彈性伸縮,能夠很容易實(shí)現(xiàn)應(yīng)用服務(wù)的高可用。對(duì)于緩存層來(lái)說(shuō),也有很多可選的開(kāi)源方案來(lái)幫助解決,比如Codis、Twemproxy、Redis Cluster等等,如果對(duì)緩存數(shù)據(jù)的一致性和實(shí)時(shí)性要求不高,這些方案就可以很好解決緩存層面的問(wèn)題。但對(duì)存儲(chǔ)層來(lái)說(shuō),支持高可用非常困難。
在互聯(lián)網(wǎng)架構(gòu)中,底層的核心數(shù)據(jù)存儲(chǔ)一般都會(huì)選擇關(guān)系型數(shù)據(jù)庫(kù),流行的當(dāng)屬M(fèi)ySQL。大數(shù)據(jù)時(shí)代,大家漸漸發(fā)現(xiàn)傳統(tǒng)的關(guān)系型數(shù)據(jù)庫(kù)開(kāi)始出現(xiàn)一些瓶頸:?jiǎn)螜C(jī)容量不能支撐快速增長(zhǎng)的業(yè)務(wù)需求;高并發(fā)的頻繁訪問(wèn)經(jīng)常造成服務(wù)的響應(yīng)超時(shí);主從數(shù)據(jù)同步帶來(lái)的數(shù)據(jù)不一致問(wèn)題;大數(shù)據(jù)場(chǎng)景下查詢性能大幅波動(dòng)等等。
當(dāng)前,數(shù)據(jù)庫(kù)方案有了很多不一樣的變化。首先,不同于早期的單機(jī)型數(shù)據(jù)庫(kù),在當(dāng)下數(shù)據(jù)呈現(xiàn)爆發(fā)式增長(zhǎng),數(shù)據(jù)總量也從GB級(jí)別跨越到了TB甚至PB級(jí)別,遠(yuǎn)超單機(jī)數(shù)據(jù)庫(kù)的存儲(chǔ)上限,所以只能選擇分布式的數(shù)據(jù)存儲(chǔ)方案。其次,隨著存儲(chǔ)節(jié)點(diǎn)的增加,存儲(chǔ)節(jié)點(diǎn)出問(wèn)題的可能性也大大提高,光靠人工完全不現(xiàn)實(shí),所以需要數(shù)據(jù)庫(kù)層面保證自己高效快速地實(shí)現(xiàn)故障遷移。另外,隨著存儲(chǔ)節(jié)點(diǎn)的增加,運(yùn)維成本也大大增加,對(duì)自動(dòng)化工具也提出了更高要求。后,新分布式數(shù)據(jù)庫(kù)的出現(xiàn),用戶在OLTP數(shù)據(jù)庫(kù)基本需求的基礎(chǔ)上,對(duì)大數(shù)據(jù)分析查詢的業(yè)務(wù)要求更高,在某種程度上OLTP和OLAP融合的新型數(shù)據(jù)庫(kù)會(huì)是未來(lái)極具潛力的發(fā)展方向之一。
Wikipedia的解釋中,高可用即High Availability,一般通過(guò)SLA(Service Level Agrement)來(lái)衡量。這里從CAP角度來(lái)看待高可用問(wèn)題。CAP是分布式系統(tǒng)領(lǐng)域一個(gè)非常的理論,由Berkerly的Brewer提出。該理論認(rèn)為任何基于網(wǎng)絡(luò)的分布式系統(tǒng)都具有以下三要素:
三要素不能同時(shí)滿足。但后來(lái)很多人將CAP解讀為數(shù)據(jù)一致性、可用性和分區(qū)容忍性多只能滿足兩個(gè),這種解讀本身存在一定的誤導(dǎo)性,原因就在于忽略了特定條件。假想兩個(gè)節(jié)點(diǎn)N1和N2,在某些場(chǎng)景下發(fā)生了分區(qū)(P)問(wèn)題,即N1和N2分處分區(qū)的兩側(cè)。這時(shí)對(duì)于外部的寫(xiě)操作來(lái)說(shuō),如果允許任一節(jié)點(diǎn)可寫(xiě)的話就相當(dāng)于選擇了A,喪失了C。同樣,如果為了滿足C,那么寫(xiě)入操作就會(huì)失敗,A就無(wú)法保證,所以存在分區(qū)問(wèn)題時(shí),無(wú)法同時(shí)保證A和C。雖然分區(qū)在局域網(wǎng)中出現(xiàn)的概率相對(duì)很低,但卻無(wú)法避免,所以系統(tǒng)只能在CP和AP之間做出權(quán)衡。
當(dāng)前有很多的NoSQL數(shù)據(jù)庫(kù),在CAP之間選擇了AP,比如Amazon Dynamo和Cassandra,追求可用性,適當(dāng)犧牲一致性,只實(shí)現(xiàn)終一致性。這種選擇允許短時(shí)間的數(shù)據(jù)不一致,并且可以交由用戶自己來(lái)處理寫(xiě)入沖突,但是可以隨時(shí)接受用戶的讀寫(xiě)請(qǐng)求。在這種場(chǎng)景下就需要特別注意數(shù)據(jù)不一致引起的各種奇怪問(wèn)題,對(duì)于比較嚴(yán)肅的業(yè)務(wù)場(chǎng)景,比如訂單、支付等,對(duì)事務(wù)和一致性要求比較高,這種AP類型的系統(tǒng)就不適用了。而且該系統(tǒng)放棄了SQL和ACID事務(wù),給開(kāi)發(fā)人員帶來(lái)了更多的開(kāi)發(fā)工作和額外的心智負(fù)擔(dān),很容易出現(xiàn)問(wèn)題,所以NoSQL數(shù)據(jù)庫(kù)犧牲一致性來(lái)獲取服務(wù)的可用性,并沒(méi)有徹底解決大數(shù)據(jù)時(shí)代數(shù)據(jù)庫(kù)的高可用問(wèn)題。
大數(shù)據(jù)時(shí)代,傳統(tǒng)的關(guān)系型數(shù)據(jù)庫(kù)必然會(huì)由單機(jī)擴(kuò)展到分布式,追求數(shù)據(jù)一致性,所以必然會(huì)是一個(gè)CP類型的系統(tǒng),像這種新型的、下一代的分布式關(guān)系型數(shù)據(jù)庫(kù),既具有傳統(tǒng)單機(jī)數(shù)據(jù)庫(kù)的SQL支持和ACID事務(wù)保證,又有NoSQL數(shù)據(jù)庫(kù)的Scale特點(diǎn),稱為NewSQL數(shù)據(jù)庫(kù),包括Google的Spanner/F1、PingCAP的TiDB等等。但從CAP的角度看,選擇CP并不意味著完全放棄了A,CP系統(tǒng)只是在某些產(chǎn)生分區(qū)的場(chǎng)景下不能實(shí)現(xiàn)100%的A,但完全可以通過(guò)有效的辦法來(lái)實(shí)現(xiàn)高可用(HA)。由此可見(jiàn),并不是CP系統(tǒng)就完全放棄了A,只不過(guò)在產(chǎn)生分區(qū)的場(chǎng)景下無(wú)法從理論上保證A,這是一個(gè)常見(jiàn)的誤解。
澄清了CAP的問(wèn)題,下面討論如何打造高可用的數(shù)據(jù)庫(kù)。數(shù)據(jù)庫(kù)是一個(gè)非常大的概念,從傳統(tǒng)單機(jī)SQL,到NoSQL,再到現(xiàn)在流行的NewSQL,這里面不同的實(shí)現(xiàn)方案實(shí)在太多,本文聚焦在關(guān)系型數(shù)據(jù)庫(kù),主要探討流行的MySQL數(shù)據(jù)庫(kù)及其生態(tài)。近幾年,隨著大家在分布式數(shù)據(jù)庫(kù)領(lǐng)域的探索,出現(xiàn)了很多不同類型的解決方案,比如中間件/Proxy的方案,典型的比如TDDL、Cobar、Altlas、DRDS、TDSQL、MyCAT、KingShard、Vitess、PhxSQL等,還有一種新型的NewSQL數(shù)據(jù)庫(kù),比如Google Spanner/F1、Oceanbase、TiDB等。下面看下業(yè)界在打造高可用數(shù)據(jù)庫(kù)方面新的技術(shù)進(jìn)展,以及和傳統(tǒng)方案選型的對(duì)比。
為了實(shí)現(xiàn)數(shù)據(jù)庫(kù)層面的高可用,必須要消除單點(diǎn)問(wèn)題(SPOF)。存在單點(diǎn)服務(wù)的情況下,一旦單點(diǎn)服務(wù)掛掉,整個(gè)服務(wù)就不可用。消除單點(diǎn)問(wèn)題常用的方案就是復(fù)制(Replication),通過(guò)數(shù)據(jù)冗余的方式來(lái)實(shí)現(xiàn)高可用。
為什么必須要冗余?數(shù)據(jù)庫(kù)本身是有狀態(tài)的,不會(huì)像無(wú)狀態(tài)的服務(wù)那樣掛掉就可以重啟,而數(shù)據(jù)庫(kù)本身能夠保證數(shù)據(jù)持久化,所以如果沒(méi)有冗余副本,一旦數(shù)據(jù)庫(kù)掛掉,只能等待數(shù)據(jù)庫(kù)重啟,在這段恢復(fù)時(shí)間服務(wù)完全不可用,高可用就無(wú)法保證。但如果有了額外的數(shù)據(jù)副本,高可用就變得可能了,主要能保證在檢測(cè)到服務(wù)發(fā)生問(wèn)題之后及時(shí)做服務(wù)切換。
對(duì)于MySQL來(lái)說(shuō),默認(rèn)復(fù)制方式是異步的主從復(fù)制方式,雖然這種方案被很多的互聯(lián)網(wǎng)公司所采用,但實(shí)際上這種方案存在一個(gè)致命問(wèn)題——存在丟失數(shù)據(jù)的風(fēng)險(xiǎn)。數(shù)據(jù)傳輸經(jīng)過(guò)網(wǎng)絡(luò),這也就意味著存在傳輸時(shí)延,那么對(duì)于異步復(fù)制來(lái)說(shuō),主從數(shù)據(jù)庫(kù)的數(shù)據(jù)本身是終一致性的,所以主庫(kù)一旦出現(xiàn)了問(wèn)題,切換從庫(kù)極有可能會(huì)帶來(lái)數(shù)據(jù)不一致的風(fēng)險(xiǎn)。
因?yàn)楫惒綇?fù)制方式存在更大的問(wèn)題,很多時(shí)候大家都會(huì)考慮用半同步復(fù)制方式Semi-Sync,這種數(shù)據(jù)復(fù)制方式在默認(rèn)情況下會(huì)使用同步的數(shù)據(jù)復(fù)制方式,不過(guò)在數(shù)據(jù)復(fù)制壓力較大的情況下,就會(huì)退化成異步的數(shù)據(jù)復(fù)制方式,所以依然會(huì)存在高可用問(wèn)題。當(dāng)然,也有人會(huì)選用完全同步的方式,但是這種復(fù)制方式在并發(fā)壓力下會(huì)有明顯的性能問(wèn)題,所以也不常用。
那有沒(méi)有一種數(shù)據(jù)復(fù)制方式,能同時(shí)保證數(shù)據(jù)的可靠性和性能?答案是有的,那就是近業(yè)界討論較多的分布式一致性算法,典型的是Paxos和Raft。簡(jiǎn)單來(lái)說(shuō),它們是高度自動(dòng)化、強(qiáng)一致的復(fù)制算法。以Raft為例,Raft中基數(shù)個(gè)節(jié)點(diǎn)組成一個(gè)Raft Group,在一個(gè)Raft Group內(nèi),只要滿足大多數(shù)節(jié)點(diǎn)寫(xiě)成功,就認(rèn)為可以寫(xiě)成功了,比如一個(gè)3節(jié)點(diǎn)的Raft Group,只要保證Raft Leader和任意一個(gè)Raft Follower寫(xiě)成功就可以了,所以同步寫(xiě)Leader,異步寫(xiě)兩個(gè)Follower,只要其中一個(gè)返回就可以,相比完全的同步方式,性能要好很多。所以從復(fù)制層面來(lái)看,Raft更像是一個(gè)自適應(yīng)的同步+異步復(fù)制方案,同步和異步的優(yōu)選擇通過(guò)Raft算法來(lái)保證。
慶幸的是,業(yè)界早已意識(shí)到這個(gè)問(wèn)題,從開(kāi)始的Galera Cluster探索到前段時(shí)間微信開(kāi)源的PhxSQL,再到新MySQL官方發(fā)布的MRG(MySQL Group Replication),還有我們從0到1打造的開(kāi)源分布式數(shù)據(jù)庫(kù)TiDB,都在這方面進(jìn)行了探索。大家的出發(fā)點(diǎn)基本相同,采用新的分布式一致性來(lái)替換傳統(tǒng)的Master-Slave復(fù)制方式,不同的僅僅是大家選擇的協(xié)議:TiDB選擇了Raft,而PhxSQL和MRG選擇了Paxos。
由此看出,新一代高可用的數(shù)據(jù)庫(kù)必然會(huì)使用分布式一致性算法來(lái)實(shí)現(xiàn)數(shù)據(jù)復(fù)制,這已是業(yè)界的趨勢(shì)。
有了數(shù)據(jù)復(fù)制,理論上來(lái)說(shuō),在一個(gè)數(shù)據(jù)庫(kù)節(jié)點(diǎn)出現(xiàn)問(wèn)題時(shí)就不用那么慌張,畢還有額外的數(shù)據(jù)副本存在。所以下面要做的就是盡早發(fā)現(xiàn)服務(wù)故障并快速恢復(fù),也就是常說(shuō)的Auto-failover。
從這個(gè)層面來(lái)看,目前基于主從的數(shù)據(jù)庫(kù)復(fù)制方案基本上無(wú)法脫離運(yùn)維,使用中間件/Proxy方案更會(huì)增加難度,畢人力運(yùn)維是有上限的,所以選擇這種方案,人力成本也是一個(gè)需要考慮的問(wèn)題。Google之前在廣告業(yè)務(wù)中也是使用的MySQL中間件方案,大約100個(gè)節(jié)點(diǎn)的規(guī)模,在這個(gè)量級(jí)下維護(hù)的復(fù)雜度和成本非常高。所以Google要做一個(gè)真正替換MySQL中間件的理想方案,這就有了后來(lái)的Google Spanner/F1,包括后來(lái)的TiDB,都采用了這種新的NewSQL架構(gòu),不同的是,Google選擇了Paxos,而TiDB選擇了Raft。這種分布式一致性算法,除了提供優(yōu)雅的復(fù)制方案,還可以提供高效的Auto-failover支持。
要想實(shí)現(xiàn)Auto-failover,首先需盡快檢測(cè)到Fail情況。常用方式是通過(guò)LVS或者HAProxy之類的負(fù)載均衡組件,或者通過(guò)類似的Monitor進(jìn)行遠(yuǎn)程監(jiān)控,但對(duì)于網(wǎng)絡(luò)來(lái)說(shuō),存在三種不同的狀態(tài):Success/Failure/Timeout,因?yàn)榇嬖赥imeout,Monitor的監(jiān)控不完全準(zhǔn)確,而且Monitor本身也會(huì)存在高可用問(wèn)題,所以外部監(jiān)控不一定完全靠譜,這也是需要考慮的問(wèn)題。但是以分布式一致性算法Raft為例,Raft內(nèi)部維護(hù)Raft Group,正常情況下都是Leader提供數(shù)據(jù)讀寫(xiě)服務(wù),當(dāng)Leader出現(xiàn)問(wèn)題時(shí)會(huì)自動(dòng)從Follower中選擇新的Leader出來(lái)。Raft通過(guò)內(nèi)部的心跳來(lái)感知不同節(jié)點(diǎn)的狀態(tài),并且直接完成Auto-failover,所以Raft是高度自動(dòng)化并且可以自恢復(fù)的。相比于檢測(cè)再處理的算法,這種基于分布式一致性算法的Auto-failover能力更強(qiáng),效率更高,當(dāng)然速度也更快,基本上在秒級(jí)別就可以完成Leader更新,繼續(xù)提供服務(wù),而且是完全自動(dòng)化的。
關(guān)于Auto-failover還有一個(gè)引申的跨數(shù)據(jù)中心多活問(wèn)題。這基本上是所有分布式系統(tǒng)開(kāi)發(fā)者心中的圣杯,金融級(jí)別的數(shù)據(jù)可用性和安全性。目前從純軟件方案來(lái)看,基本沒(méi)有靠譜的方案,大多數(shù)人所謂的異地多活方案實(shí)際上底層仍是同步熱備,而且很難在保證延遲的情況下同時(shí)保持一致性,但是基于Paxos/Raft的方案給多活提供了新的可能性。還是以Raft為例,只要一個(gè)Raft Group內(nèi)的大多數(shù)節(jié)點(diǎn)復(fù)制成功,并在物理節(jié)點(diǎn)層面按照特定的方式部署,就可以在軟件層面構(gòu)建一個(gè)兩地三中心的方案。舉個(gè)例子,如果這個(gè)Raft Group內(nèi)有三個(gè)節(jié)點(diǎn),分別在北京、天津和上海的三個(gè)數(shù)據(jù)中心,對(duì)于傳統(tǒng)的強(qiáng)一致方案,一個(gè)在北京發(fā)起的寫(xiě)入需要等待天津和上海的數(shù)據(jù)中心復(fù)制完畢,才能給客戶端返回成功,但是對(duì)于Raft這樣的算法,延遲僅僅在北京和天津數(shù)據(jù)中心之間,相比傳統(tǒng)方案大大降低了延遲。雖然對(duì)于帶寬的要求仍然很高,但這是未來(lái)在數(shù)據(jù)庫(kù)層面上實(shí)現(xiàn)跨數(shù)據(jù)中心多活的一個(gè)趨勢(shì)和可行方向,實(shí)際上Google分別位于美國(guó)西海岸、東海岸以及中部的Spanner數(shù)據(jù)中心,已經(jīng)做到了跨地域的數(shù)據(jù)高可用。真正實(shí)現(xiàn)跨數(shù)據(jù)中心多活,就不用擔(dān)心挖斷光纖導(dǎo)致服務(wù)不可用之類的問(wèn)題了。
隨著數(shù)據(jù)庫(kù)的數(shù)據(jù)量越來(lái)越大,Scale是不可避免的問(wèn)題。對(duì)于數(shù)據(jù)庫(kù)來(lái)說(shuō),技術(shù)層面大的追求就在于如何不停服務(wù)地對(duì)數(shù)據(jù)庫(kù)節(jié)點(diǎn)進(jìn)行Scale操作,這是非常有挑戰(zhàn)性的事情。以中間件/Proxy方案來(lái)說(shuō),很多時(shí)候不得不提前對(duì)數(shù)據(jù)量進(jìn)行規(guī)劃,把擴(kuò)容作為重要的計(jì)劃來(lái)做,從DBA到運(yùn)維到測(cè)試到開(kāi)發(fā)人員,很早之前就要做相關(guān)的準(zhǔn)備工作,真正擴(kuò)容時(shí)為了保證數(shù)據(jù)安全,經(jīng)常會(huì)選擇停服務(wù)來(lái)保證沒(méi)有新的數(shù)據(jù)寫(xiě)入,新的實(shí)例數(shù)據(jù)同步后還要做數(shù)據(jù)的一致性校驗(yàn)。當(dāng)然業(yè)界大公司有足夠雄厚的技術(shù)實(shí)力,可以采用更自動(dòng)化的方案,將擴(kuò)容停機(jī)時(shí)間盡量縮短(但很難縮減到0),但大部分中小互聯(lián)網(wǎng)公司和傳統(tǒng)企業(yè)依然無(wú)法避免較長(zhǎng)時(shí)間的停服務(wù)問(wèn)題。TiDB完全實(shí)現(xiàn)了在線的彈性擴(kuò)容,主要基于Placement Driver的調(diào)度和Raft算法。
Placement Driver是TiDB核心組件之一,時(shí)刻監(jiān)控整個(gè)系統(tǒng)的狀態(tài),包括每個(gè)機(jī)器的負(fù)載和容量等。當(dāng)加入一個(gè)新的節(jié)點(diǎn)時(shí),它會(huì)感知到這個(gè)事件,并會(huì)觸發(fā)其他負(fù)載較高的節(jié)點(diǎn)進(jìn)行Balance操作,通過(guò)Raft算法的Config Change和Leader Transfer操作來(lái)讓整個(gè)系統(tǒng)的負(fù)載平衡。對(duì)用戶來(lái)說(shuō),有了這個(gè)特性體驗(yàn)會(huì)非常好。如果是電商用戶,那么在促銷活動(dòng)之前(比如雙11),提前增加數(shù)據(jù)庫(kù)節(jié)點(diǎn)就可以支撐更高的業(yè)務(wù)壓力,而當(dāng)活動(dòng)過(guò)后又可以移除掉多余的節(jié)點(diǎn),又可以收縮回來(lái),整個(gè)彈性伸縮過(guò)程非常平滑,基本就是幾個(gè)簡(jiǎn)單的操作,其它一切都是高度自動(dòng)化的,使用成本特別低。
當(dāng)然這里面還有一個(gè)影響高可用的因素,就是對(duì)于一個(gè)Paxos或者Raft Group來(lái)說(shuō),如果數(shù)據(jù)量太大,在數(shù)據(jù)Balance或者Recover時(shí)就會(huì)有很長(zhǎng)的數(shù)據(jù)傳輸和更新時(shí)間,所以將數(shù)據(jù)在線切分成比較小的數(shù)據(jù)塊是不可或缺的操作,也就是常說(shuō)的分裂(Split)操作。其中困難的在于如何保證Split操作的原子性,并且讓路由不一致的時(shí)間窗口盡可能縮短。TiDB完整實(shí)現(xiàn)了在線Split操作,內(nèi)部處理了路由更新的重試操作,所以對(duì)于應(yīng)用層來(lái)說(shuō)基本上無(wú)感知。
數(shù)據(jù)量較大時(shí),數(shù)據(jù)庫(kù)的DDL操作也是一個(gè)需要注意的高可用問(wèn)題。以常見(jiàn)的Add Column操作為例,在表規(guī)模很大的情況下通常會(huì)造成數(shù)據(jù)庫(kù)鎖表,導(dǎo)致數(shù)據(jù)庫(kù)服務(wù)不可用。對(duì)于中間件/Proxy方案來(lái)說(shuō),因?yàn)橐劳杏诘讓拥膯螜C(jī)MySQL數(shù)據(jù)庫(kù)提供DDL支持,所以很難從根本上解決,只能依賴于第三方工具,比如Facebook和Percona的方案,當(dāng)然這些方案也有本身的局限性。近業(yè)界有了更好的進(jìn)展,比如Github數(shù)據(jù)團(tuán)隊(duì)的方案gh-ost,處理表級(jí)別的Binlog,將原表的數(shù)據(jù)同步到新的臨時(shí)表中,當(dāng)數(shù)據(jù)追平時(shí)再進(jìn)行一個(gè)數(shù)據(jù)庫(kù)操作,將臨時(shí)表命名為原表,這樣一個(gè)AddColumn操作就完成了。這種方案依然要引入額外的組件,除了學(xué)習(xí)成本之外,也要考慮額外組件的高可用問(wèn)題。但實(shí)際上Google的F1給我們提供了更好的實(shí)現(xiàn)參考,TiDB即是根據(jù)F1啟發(fā)進(jìn)行的研發(fā),簡(jiǎn)單來(lái)說(shuō),就是通過(guò)把TiDB中DDL操作的狀態(tài)設(shè)定為前向兼容的幾個(gè)不同狀態(tài),中間嚴(yán)格保證不能跨越兩個(gè)狀態(tài)。為什么這樣?因?yàn)檎麄€(gè)TiDB集群是分布式的,沒(méi)有辦法把DDL操作實(shí)時(shí)通知給所有的TiDB節(jié)點(diǎn),就會(huì)出現(xiàn)部分TiDB節(jié)點(diǎn)感知到了DDL變化,另一部分TiDB節(jié)點(diǎn)還沒(méi)有感知到的情況,這樣就可能導(dǎo)致數(shù)據(jù)不一致。比如對(duì)于一個(gè)Add Index的DDL,有一個(gè)節(jié)點(diǎn)先感知到了,然后對(duì)于插入數(shù)據(jù)就增加了一個(gè)Index,但是另外一個(gè)節(jié)點(diǎn)沒(méi)有感知到,正好這個(gè)節(jié)點(diǎn)還有一個(gè)刪除操作,所以就只把行數(shù)據(jù)刪除了,但I(xiàn)ndex還留在里面,這樣當(dāng)使用Index查詢這行時(shí)就會(huì)找不到數(shù)據(jù)。TiDB參考的算法是Google F1中一個(gè)非常經(jīng)典的算法,感興趣的可以看看這篇文章Online, Asynchronous Schema Change in F1。
本站文章版權(quán)歸原作者及原出處所有 。內(nèi)容為作者個(gè)人觀點(diǎn), 并不代表本站贊同其觀點(diǎn)和對(duì)其真實(shí)性負(fù)責(zé),本站只提供參考并不構(gòu)成任何投資及應(yīng)用建議。本站是一個(gè)個(gè)人學(xué)習(xí)交流的平臺(tái),網(wǎng)站上部分文章為轉(zhuǎn)載,并不用于任何商業(yè)目的,我們已經(jīng)盡可能的對(duì)作者和來(lái)源進(jìn)行了通告,但是能力有限或疏忽,造成漏登,請(qǐng)及時(shí)聯(lián)系我們,我們將根據(jù)著作權(quán)人的要求,立即更正或者刪除有關(guān)內(nèi)容。本站擁有對(duì)此聲明的最終解釋權(quán)。