硬核干貨!TDSQL全局一致性讀技術(shù)詳解

來(lái)源: 騰訊云數(shù)據(jù)庫(kù)
作者:騰訊云數(shù)據(jù)庫(kù)
時(shí)間:2021-11-04
16280
分布式場(chǎng)景下如何進(jìn)行快照讀是一個(gè)很常見(jiàn)的問(wèn)題,因?yàn)樵谶@種場(chǎng)景下極易讀取到分布式事務(wù)的“中間狀態(tài)”。針對(duì)這一點(diǎn),騰訊云數(shù)據(jù)庫(kù)TDSQL設(shè)計(jì)了全局一致性讀方案,解決了分布式節(jié)點(diǎn)間數(shù)據(jù)的讀一致性問(wèn)題。

分布式場(chǎng)景下如何進(jìn)行快照讀是一個(gè)很常見(jiàn)的問(wèn)題,因?yàn)樵谶@種場(chǎng)景下極易讀取到分布式事務(wù)的“中間狀態(tài)”。針對(duì)這一點(diǎn),騰訊云數(shù)據(jù)庫(kù)TDSQL設(shè)計(jì)了全局一致性讀方案,解決了分布式節(jié)點(diǎn)間數(shù)據(jù)的讀一致性問(wèn)題。

近日騰訊云數(shù)據(jù)庫(kù)專家工程師張文在第十二屆中國(guó)數(shù)據(jù)庫(kù)技術(shù)大會(huì)上為大家分享了“TDSQL全局一致性讀技術(shù)”。以下是分享實(shí)錄:

分布式下一致性讀問(wèn)題

近年來(lái)很多企業(yè)都會(huì)發(fā)展自己的分布式數(shù)據(jù)庫(kù)應(yīng)用,一種常見(jiàn)的發(fā)展路線是基于開(kāi)源MySQL,典型方案有共享存儲(chǔ)方案、分表方案,TDSQL架構(gòu)是一種典型的分區(qū)表方案。

以圖例的銀行場(chǎng)景為例,是一種典型的基于MySQL分布式架構(gòu),前端為SQL引擎,后端以MySQL作為存儲(chǔ)引擎,整體上計(jì)算與存儲(chǔ)相分離,各自實(shí)現(xiàn)橫向擴(kuò)展。

銀行的轉(zhuǎn)賬業(yè)務(wù)一般是先扣款再加余額,整個(gè)交易為一個(gè)分布式事務(wù)。分布式事務(wù)基于兩階段提交,保證了交易的最終一致性,但無(wú)法保證讀一致性。

轉(zhuǎn)賬操作先給A賬戶扣款再給B賬戶增加余額,這兩個(gè)操作要么都成功,要么都不成功,不會(huì)出現(xiàn)一個(gè)成功一個(gè)不成功,這就是分布式事務(wù)。在分布式數(shù)據(jù)庫(kù)下,各節(jié)點(diǎn)相對(duì)獨(dú)立,一邊做扣款的同時(shí)另一邊可能已經(jīng)增加余額成功。在某個(gè)節(jié)點(diǎn)的存儲(chǔ)引擎內(nèi)部,如果事務(wù)沒(méi)有完成提交,那么SQL引擎對(duì)于前端仍是阻塞狀態(tài),只有所有子事務(wù)全部完成之后才會(huì)返回客戶端成功,這是分布式事務(wù)的最終一致性原理。但是,如果該分布式事務(wù)在返回給前端成功之前,即子事務(wù)還在執(zhí)行過(guò)程中,此時(shí),剛好有查詢操作,正好查到這樣的狀態(tài),即A賬戶扣款還沒(méi)有成功,但B賬戶余額已經(jīng)增加成功,這便出現(xiàn)了分布式場(chǎng)景下的讀一致性的問(wèn)題。

部分銀行對(duì)這種場(chǎng)景沒(méi)有苛刻的要求,出報(bào)表的時(shí)候如果有數(shù)據(jù)處于這種“中間”狀態(tài),一般通過(guò)業(yè)務(wù)流水或其他方式補(bǔ)償,使數(shù)據(jù)達(dá)到平衡狀態(tài)。但部分敏感型業(yè)務(wù)對(duì)這種讀一致性有強(qiáng)依賴,認(rèn)為補(bǔ)償操作的代價(jià)太高,同時(shí)對(duì)業(yè)務(wù)的容錯(cuò)性要求過(guò)高。所以,這類銀行業(yè)務(wù)希望依賴數(shù)據(jù)庫(kù)本身獲取一個(gè)平衡的數(shù)據(jù)鏡像,即要么讀到事務(wù)操作數(shù)據(jù)前的原始狀態(tài),要么讀取到數(shù)據(jù)被分布式事務(wù)修改后的最終狀態(tài)。

640.webp.jpg

針對(duì)分布式場(chǎng)景下的一致性讀問(wèn)題,早期可以通過(guò)加鎖讀,即查詢時(shí)強(qiáng)制顯示加排他鎖的方式。加鎖讀在高并發(fā)場(chǎng)景下會(huì)有明顯的性能瓶頸,還容易產(chǎn)生死鎖。所以,在分布式下,我們希望以一種輕量的方式實(shí)現(xiàn)RR隔離級(jí)別,即快照讀的能力。一致性讀即快照讀,讀取到的數(shù)據(jù)一定是“平衡”的數(shù)據(jù),不是處于“中間狀態(tài)”的數(shù)據(jù)。對(duì)于業(yè)務(wù)來(lái)說(shuō),無(wú)論是集中式數(shù)據(jù)庫(kù)還是分布式數(shù)據(jù)庫(kù),都應(yīng)該做到對(duì)業(yè)務(wù)透明且無(wú)感知。即集中式可以看到的數(shù)據(jù),分布式也同樣能看到,即都要滿足可重復(fù)讀。

在解決這個(gè)問(wèn)題前,我們首先需要關(guān)注基于MySQL這種分布式架構(gòu)的數(shù)據(jù)庫(kù),在單節(jié)點(diǎn)下的事務(wù)一致性和可見(jiàn)性的原理。

下圖是典型的MVCC模型,活躍事務(wù)鏈表會(huì)形成高低水位線,高低水位線決定哪些事務(wù)可見(jiàn)或不可見(jiàn)。如果事務(wù)ID比高水位線還要小,該事務(wù)屬于在構(gòu)建可見(jiàn)性視圖之前就已經(jīng)提交的,那么一定可見(jiàn)。而對(duì)于低水位線對(duì)應(yīng)的事務(wù)ID,如果數(shù)據(jù)行的事務(wù)ID比低水位線大,那么代表該數(shù)據(jù)行在當(dāng)前可見(jiàn)性視圖創(chuàng)建后才生成的,一定不可見(jiàn)。每個(gè)事務(wù)ID都是獨(dú)立的序列并且是線性增長(zhǎng),每個(gè)數(shù)據(jù)行都會(huì)綁定一個(gè)事務(wù)ID。當(dāng)查詢操作掃描到對(duì)應(yīng)的記錄行時(shí),需要結(jié)合查詢時(shí)創(chuàng)建的可見(jiàn)性視圖中的高低水位線來(lái)判斷可見(jiàn)性。

640.webp (1).jpg

圖中兩種隔離級(jí)別,RC隔離級(jí)別可以看到事務(wù)ID為1、3、5的事務(wù),因?yàn)?、3、5現(xiàn)在是活躍狀態(tài),后面變成提交狀態(tài)后,提交狀態(tài)是對(duì)當(dāng)前查詢可見(jiàn)。而對(duì)于RR級(jí)別,未來(lái)提交是不可見(jiàn),因?yàn)榭芍貜?fù)讀要求可見(jiàn)性視圖構(gòu)建后數(shù)據(jù)的可見(jiàn)性唯一且不變。即原來(lái)可見(jiàn)現(xiàn)在仍可見(jiàn),原來(lái)不可見(jiàn)的現(xiàn)在仍不可見(jiàn),這是Innodb存儲(chǔ)引擎的MVCC原理。我們先要了解單節(jié)點(diǎn)是怎么做的,然后才清楚如何在分布式下對(duì)其進(jìn)行改造。

在下面的這個(gè)轉(zhuǎn)賬操作中,A賬戶扣款,B賬戶增加余額,A、B兩個(gè)節(jié)點(diǎn)分別是節(jié)點(diǎn)1和節(jié)點(diǎn)2,節(jié)點(diǎn)1原來(lái)的數(shù)據(jù)是0,轉(zhuǎn)賬后變?yōu)?0,A節(jié)點(diǎn)之前的事務(wù)ID是18,轉(zhuǎn)賬后變成22,每個(gè)節(jié)點(diǎn)的數(shù)據(jù)都有歷史版本的鏈接,事務(wù)ID隨著新事務(wù)的提交而變大。對(duì)B節(jié)點(diǎn)來(lái)說(shuō),原來(lái)存儲(chǔ)的這行數(shù)據(jù)的事務(wù)ID是33,事務(wù)提交后變成了37。A、B兩個(gè)節(jié)點(diǎn)之間的事務(wù)ID是毫無(wú)關(guān)聯(lián)的,各自按照獨(dú)立的規(guī)則生成。

640.webp (2).jpg

所以,此時(shí)一筆讀事務(wù)發(fā)起查詢操作,也是相對(duì)獨(dú)立的。查詢操作發(fā)往計(jì)算節(jié)點(diǎn)后,計(jì)算節(jié)點(diǎn)會(huì)同時(shí)發(fā)往A、B兩個(gè)MySQL節(jié)點(diǎn)。這個(gè)“同時(shí)”也是相對(duì)的,不可能達(dá)到絕對(duì)同時(shí)。此時(shí),查詢操作對(duì)第一個(gè)節(jié)點(diǎn)得到的低水位線是23,23大于22,所以當(dāng)前事務(wù)對(duì)22可見(jiàn)。查詢發(fā)往第二個(gè)節(jié)點(diǎn)時(shí)得到的低水位線是37,事務(wù)ID 37的數(shù)據(jù)行對(duì)當(dāng)前事務(wù)也可見(jiàn),這是比較好的結(jié)果,我們看到數(shù)據(jù)是平的,查到的都是最新的數(shù)據(jù)。

然而,如果查詢操作創(chuàng)建可見(jiàn)性視圖時(shí)產(chǎn)生的低水位線為36,此時(shí)就無(wú)法看到事務(wù)ID為37的數(shù)據(jù)行,只能看到事務(wù)ID為33的上一個(gè)版本的數(shù)據(jù)。站在業(yè)務(wù)的角度,同時(shí)進(jìn)行了兩個(gè)操作一筆轉(zhuǎn)賬一筆查詢,到達(dá)存儲(chǔ)引擎的時(shí)機(jī)未必是轉(zhuǎn)賬在前查詢?cè)诤?,一定概率上存在時(shí)序上的錯(cuò)位,比如:查詢操作發(fā)生在轉(zhuǎn)賬的過(guò)程中。如果發(fā)生錯(cuò)位又沒(méi)有任何干預(yù)和保護(hù),查詢操作很有可能讀到數(shù)據(jù)的“中間狀態(tài)”,即不平的數(shù)據(jù),比如讀取到總賬是20,總賬是0。

目前面對(duì)這類問(wèn)題的思路基本一致,即采用一定的串行化規(guī)則讓其一致。首先,如果涉及分布式事務(wù)的兩個(gè)節(jié)點(diǎn)數(shù)據(jù)平衡,首先要統(tǒng)一各節(jié)點(diǎn)的高低水位線,即用一個(gè)統(tǒng)一標(biāo)尺才能達(dá)到統(tǒng)一的可見(jiàn)性判斷效果。然后,由于事務(wù)ID在各個(gè)節(jié)點(diǎn)間相互獨(dú)立,這也會(huì)造成可見(jiàn)性判斷的不一致,所以事務(wù)ID也要做串行化處理。

640.webp (3).jpg

在確立串行化的基本思路后,即可構(gòu)造整體的事務(wù)模型。比如:A和B兩個(gè)賬戶分別分布在兩個(gè)MySQL節(jié)點(diǎn),節(jié)點(diǎn)1和節(jié)點(diǎn)2。每個(gè)節(jié)點(diǎn)的事務(wù)ID強(qiáng)制保持一致,即節(jié)點(diǎn)1、2在事務(wù)執(zhí)行前對(duì)應(yīng)的數(shù)據(jù)行綁定的事務(wù)ID都為88,事務(wù)執(zhí)行后綁定的ID都為92。然后,保持可見(jiàn)性視圖的“水位線”一致。

此時(shí),對(duì)于查詢來(lái)說(shuō)要么查到的都是舊的數(shù)據(jù),要么查到的都是新的數(shù)據(jù),不會(huì)出現(xiàn)“一半是舊的數(shù)據(jù),一半是新的數(shù)據(jù)”這種情況。到這里我們會(huì)發(fā)現(xiàn),解決問(wèn)題的根本:1、統(tǒng)一事務(wù)ID;2、統(tǒng)一查詢的評(píng)判標(biāo)準(zhǔn)即“水位線”。當(dāng)然,這里的“事務(wù)ID”已經(jīng)不是單節(jié)點(diǎn)的事務(wù)ID,而是“全局事務(wù)ID”,所以整體思路就是從局部到全局的過(guò)程。

TDSQL全局一致性讀方案

剛剛介紹了為什么分布式下會(huì)存在一致性讀的問(wèn)題,接下來(lái)分享TDSQL一致性讀的解決方案:

640.webp (4).jpg

首先引入了全局的時(shí)間戳服務(wù),它用來(lái)對(duì)每一筆事務(wù)進(jìn)行標(biāo)記,即每一筆分布式事務(wù)綁定一個(gè)全局遞增的序列號(hào)。然后,在事務(wù)開(kāi)始的時(shí)候獲取時(shí)間戳,提交的時(shí)候再獲取時(shí)間戳,各個(gè)節(jié)點(diǎn)內(nèi)部維護(hù)事務(wù)ID到全局時(shí)間戳的映射關(guān)系。原有的事務(wù)ID不受影響,只是會(huì)新產(chǎn)生一種映射關(guān)系:每個(gè)ID會(huì)映射到一個(gè)全局的GTS。

通過(guò)修改innodb存儲(chǔ)引擎,我們實(shí)現(xiàn)從局部事務(wù)ID到全局GTS的映射,每行數(shù)據(jù)都可以找到唯一的GTS。如果A節(jié)點(diǎn)有100個(gè)GTS,B節(jié)點(diǎn)也應(yīng)該有100個(gè)GTS,此外分布式事務(wù)開(kāi)啟的時(shí)候都會(huì)做一次獲取時(shí)間戳的操作。整個(gè)過(guò)程對(duì)原有事務(wù)的影響不大,新增了在事務(wù)提交時(shí)遞增并獲取一次時(shí)間戳,事務(wù)啟動(dòng)時(shí)獲取一次當(dāng)前時(shí)間戳的邏輯。

建立這樣的機(jī)制后,再來(lái)看分布式事務(wù)的執(zhí)行過(guò)程,比如一筆轉(zhuǎn)賬操作,A節(jié)點(diǎn)和B節(jié)點(diǎn)首先在開(kāi)啟事務(wù)的時(shí)候獲取一遍GTS:500,提交的時(shí)候由于間隔一段時(shí)間GTS可能發(fā)生了變化,因而重新獲取一次GTS:700。查詢操作也是一個(gè)獨(dú)立的事務(wù),開(kāi)啟后獲取到全局GTS,比如500或者700,此時(shí)查詢到的數(shù)據(jù)一定是平衡的數(shù)據(jù),不可能查到中間狀態(tài)的數(shù)據(jù)。

640.webp (5).jpg

看似方案已經(jīng)完整,但是還有個(gè)問(wèn)題:即分布式事務(wù)都存在兩階段提交的情況,prepare階段做了99%以上的工作,commit做剩余不到1%的部分,這是經(jīng)典的兩階段提交理論。A、B兩個(gè)節(jié)點(diǎn)雖然都可以綁定全局GTS,但有可能A節(jié)點(diǎn)網(wǎng)絡(luò)較慢,prepare后沒(méi)有馬上commit。由于A節(jié)點(diǎn)對(duì)應(yīng)的記錄行沒(méi)有完成commit,還處于prepare狀態(tài),導(dǎo)致代表其全局事務(wù)狀態(tài)的全局GTS還未綁定。此時(shí)查詢操作此時(shí)必須等待,直到commit后才能獲取到GTS后進(jìn)而做可見(jiàn)性判斷。因?yàn)槿绻鸄節(jié)點(diǎn)的數(shù)據(jù)沒(méi)有提交就沒(méi)辦法獲取其全局GTS,進(jìn)而無(wú)法知道該記錄行對(duì)當(dāng)前讀事務(wù)是否可見(jiàn)。所以,在查詢中會(huì)有一個(gè)遇到prepare等待的過(guò)程,這是全局一致性讀最大的性能瓶頸。

640.webp (6).jpg

當(dāng)然,優(yōu)化的策略和思路就是減少等待,這個(gè)下一章會(huì)詳細(xì)分析。至此,我們有了全局一致性讀的基本思路和方案,下一步就是針對(duì)優(yōu)化項(xiàng)的考慮了。

一致性讀下的性能優(yōu)化

這部分內(nèi)容的是在上述解決方案的基礎(chǔ)上進(jìn)行的優(yōu)化。

經(jīng)過(guò)實(shí)踐后,我們發(fā)現(xiàn)全局一致性讀帶來(lái)了三個(gè)問(wèn)題:

第一個(gè)問(wèn)題是映射關(guān)系帶來(lái)的開(kāi)銷。引入映射關(guān)系后,映射一定非常高頻的操作,幾乎掃描每一行都需要做映射,如果有一千萬(wàn)行記錄需要掃描,在極端情況下很可能要進(jìn)行一千萬(wàn)次映射。

第二個(gè)問(wèn)題是事務(wù)等待的開(kāi)銷。在兩階段提交中的prepare階段,事務(wù)沒(méi)有辦法獲取最終提交的GTS,而GTS是未來(lái)不可預(yù)知的值,必須等待prepare狀態(tài)變?yōu)閏ommit后才可以判斷。

第三個(gè)問(wèn)題是針對(duì)非分布式事務(wù)的考慮。針對(duì)非分布式事務(wù)是否也要無(wú)差別的進(jìn)行GTS綁定,包括在事務(wù)提交時(shí)綁定全局時(shí)間戳、在查詢時(shí)做判斷等操作。如果采用和分布式事務(wù)一樣的機(jī)制一定會(huì)帶來(lái)開(kāi)銷,但如果不加干涉會(huì)不會(huì)有其他問(wèn)題?

640.webp (7).jpg

針對(duì)這三個(gè)問(wèn)題,我們接下來(lái)依次展開(kāi)分析。

3.1 prepare等待問(wèn)題

首先,針對(duì)prepare記錄需要等待其commit的開(kāi)銷問(wèn)題,由于事務(wù)在沒(méi)有commit時(shí),無(wú)法確定其最終GTS,需要進(jìn)行等待其commit。仔細(xì)分析prepare等待的過(guò)程,就可以發(fā)現(xiàn)其中的優(yōu)化空間。

下圖中,在當(dāng)前用戶表里的四條數(shù)據(jù),A、B兩條數(shù)據(jù)是上一次修改的目前已經(jīng)commit,而C、D數(shù)據(jù)最近修改且處于prepare狀態(tài),上一個(gè)版本commit記錄也可以通過(guò)undo鏈找到,其事務(wù)ID為63。這個(gè)事務(wù)開(kāi)始時(shí)GTS是150,最終提交后變?yōu)?81。這個(gè)181是已經(jīng)提交的最終狀態(tài),我們回退到中間狀態(tài),即還沒(méi)有提交時(shí)的狀態(tài)。

如果按照正常邏輯,prepare一定要等,但這時(shí)有個(gè)問(wèn)題,這個(gè)prepare將來(lái)肯定會(huì)被commit,雖然現(xiàn)在不知道它的具體值時(shí)多少,但是它“將來(lái)”提交后一定比當(dāng)前已經(jīng)commit最大的ID還要大,即將來(lái)commit時(shí)的GTS一定會(huì)比179大。此時(shí),如果一筆查詢的GTS小于等于179,可以認(rèn)為就算C、D記錄將來(lái)提交,也一定對(duì)當(dāng)前這筆小于等于179的查詢不可見(jiàn),因此可以直接跳過(guò)對(duì)C、D的等待,通過(guò)undo鏈追溯上一個(gè)版本的記錄。這就是對(duì)prepare的優(yōu)化的核心思想,并不是只要遇到prepare就等待,而是要跟當(dāng)前緩存最大已經(jīng)提交的GTS來(lái)做比較判斷,如果查詢的GTS比當(dāng)前節(jié)點(diǎn)上已經(jīng)提交的最大GTS還要大則需要等待prepare變?yōu)閏ommit。但如果查詢的GTS比當(dāng)前節(jié)點(diǎn)已經(jīng)提交的最大GTS小,則直接通過(guò)undo鏈獲取當(dāng)前prepare記錄的上一個(gè)版本,無(wú)需等待其commit。這個(gè)優(yōu)化對(duì)整個(gè)prepare吞吐量和等待時(shí)長(zhǎng)的影響非常大,可以做到50%~60%的性能提升。

640.webp (8).jpg

3.2非分布式事務(wù)問(wèn)題

針對(duì)非分布式事務(wù)的一致性讀是我們需要考慮的另外一個(gè)問(wèn)題。由于非分布式事務(wù)走的路線不是兩階段提交,事務(wù)涉及的數(shù)據(jù)節(jié)點(diǎn)不存在跨節(jié)點(diǎn)、跨分片現(xiàn)象。按照我們前面的分析,一致性讀是在分布式事務(wù)場(chǎng)景下的問(wèn)題。所以,針對(duì)分布式場(chǎng)景下的非分布式事務(wù),是否可以直接放棄對(duì)它的特殊處理,而是采用原生的事務(wù)提交方式。

如果放棄處理是否會(huì)產(chǎn)生其他問(wèn)題,我們繼續(xù)分析。下圖在銀行金融機(jī)構(gòu)中是常見(jiàn)的交易模型,交易啟動(dòng)時(shí)記錄交易日志,交易結(jié)束后更新交易日志的狀態(tài)。交易日志為單獨(dú)的記錄行,對(duì)其的更新可能是非分布式事務(wù),而真正的交易又是分布式事務(wù)。如果在交易的過(guò)程中伴隨有查詢操作,則查詢邏輯中里很可能會(huì)出現(xiàn)這種狀態(tài):即交易已經(jīng)開(kāi)始了但交易日志還查不到,對(duì)于業(yè)務(wù)來(lái)說(shuō)如果查不到的話就會(huì)認(rèn)為沒(méi)有啟動(dòng),那么矛盾的問(wèn)題就產(chǎn)生了。

如果要保持業(yè)務(wù)語(yǔ)義連續(xù)性,即針對(duì)非分布式事務(wù),即使在分布式場(chǎng)景下一筆交易只涉及一個(gè)節(jié)點(diǎn),也需要像分布式事務(wù)那樣做標(biāo)記、處理。雖然說(shuō)針對(duì)非分布式事務(wù)需要綁定GTS,但是我們希望盡可能簡(jiǎn)化和輕量,相比于分布式事務(wù)不需要在每筆commit提交時(shí)都訪問(wèn)一遍全局時(shí)間戳組件請(qǐng)求GTS。所以,我們也希望借鑒對(duì)prepare的處理方式,可以用節(jié)點(diǎn)內(nèi)部緩存的GTS來(lái)在引擎層做綁定。

640.webp (9).jpg

受prepare優(yōu)化思路的啟發(fā),是否也可以拿最大提交的GTS做緩存。但是如果拿最大已提交GTS做緩存會(huì)產(chǎn)生兩個(gè)比較明顯的問(wèn)題:第一,不可重復(fù)讀;第二,數(shù)據(jù)行“永遠(yuǎn)不可見(jiàn)”。這兩個(gè)問(wèn)題會(huì)給業(yè)務(wù)帶來(lái)更嚴(yán)重的影響。

首先是不可重復(fù)讀問(wèn)題。T1是非分布式事務(wù),T2是查詢事務(wù)。當(dāng)T1沒(méi)有提交的時(shí)候,查詢無(wú)法看到T1對(duì)數(shù)據(jù)的修改。如果T1從啟動(dòng)到提交的間隔時(shí)間較長(zhǎng)(沒(méi)有經(jīng)過(guò)prepare階段),且這段時(shí)間沒(méi)有其他分布式事務(wù)在當(dāng)前節(jié)點(diǎn)上提交。所以,當(dāng)T1提交后當(dāng)前的最大commit GTS沒(méi)有發(fā)生變化仍為100,此時(shí)綁定T1事務(wù)的GTS為100,但由于查詢類事務(wù)的GTS也是100,所以導(dǎo)致T1提交后會(huì)被T2看得到,出現(xiàn)不可重復(fù)讀問(wèn)題。

其次是不可見(jiàn)的問(wèn)題。接著上一個(gè)問(wèn)題,如果用最大已提交的GTS遞增值加1是否可以解決上一個(gè)不可重復(fù)讀問(wèn)題,看似可以解決但是會(huì)帶來(lái)另外一個(gè)更嚴(yán)重的問(wèn)題:該事務(wù)修改的數(shù)據(jù)行可能“永遠(yuǎn)”不可見(jiàn)。假如T1非分布式事務(wù)提交之后,系統(tǒng)內(nèi)再無(wú)寫(xiě)事務(wù),導(dǎo)致“一段時(shí)間”內(nèi),查詢類事務(wù)的GTS永遠(yuǎn)小于T1修改數(shù)據(jù)會(huì)綁定的GTS,進(jìn)而演變?yōu)門1修改的數(shù)據(jù)行“一段時(shí)間內(nèi)”對(duì)所有查詢操作都不可見(jiàn)。

640.webp (10).jpg

這時(shí)我們就需要考慮,在非分布式場(chǎng)景下需要緩存怎樣的GTS。在下圖的事務(wù)模型中,T1時(shí)刻有三筆活躍事務(wù):事務(wù)1、事務(wù)2、事務(wù)3。事務(wù)2是非分布式事務(wù),它的提交我們希望對(duì)事務(wù)3永遠(yuǎn)不可見(jiàn)。如果對(duì)事務(wù)3不可見(jiàn)的話,就必須要比事務(wù)3開(kāi)啟的GTS大。所以,我們就需要在非分布式事務(wù)提交時(shí),綁定當(dāng)前活躍事務(wù)里“快照最大GTS加1”,即綁定GTS為106后,由于查詢的GTS為105,無(wú)論中間開(kāi)啟后執(zhí)行多少次,一定對(duì)前面不可見(jiàn),這樣就得以保證。

再看第二個(gè)時(shí)刻,在事務(wù)4和事務(wù)5中,隨著GTS的遞增,事務(wù)5的啟動(dòng)GTS已經(jīng)到達(dá)到106,106大于等于上一次非分布式事務(wù)提交的GTS值106,所以事務(wù)2對(duì)事務(wù)5始終可見(jiàn),滿足事務(wù)可見(jiàn)性,不會(huì)導(dǎo)致事務(wù)不可見(jiàn)。

通過(guò)前述優(yōu)化,形成了分布式場(chǎng)景下事務(wù)提交的最終方案:事務(wù)啟動(dòng)時(shí)獲取當(dāng)前全局GTS,當(dāng)事務(wù)提交時(shí)進(jìn)行二次判斷。首先判斷它是不是一階段提交的非分布式事務(wù),如果是則需要獲取當(dāng)前節(jié)點(diǎn)的最大快照GTS并加1;如果是分布式事務(wù)則需要走兩階段提交,在commit時(shí)重新獲取一遍全局GTS遞增值,綁定到當(dāng)前事務(wù)中。這樣的機(jī)制下除了性能上的提升,在查詢數(shù)據(jù)時(shí)更能保證數(shù)據(jù)不丟不錯(cuò),事務(wù)可見(jiàn)性不受影響。

640.webp (11).jpg

3.3高性能映射問(wèn)題

最后是事務(wù)ID和全局GTS的映射問(wèn)題。這里為什么沒(méi)有采用隱藏列而是使用映射關(guān)系呢?因?yàn)槿绻捎秒[藏列會(huì)對(duì)業(yè)務(wù)有很強(qiáng)的入侵,同時(shí)讓業(yè)務(wù)對(duì)全局時(shí)間戳組件產(chǎn)生過(guò)度依賴。比如:若使用一致性讀特性,那么必須引入全局的時(shí)間戳,每一筆事務(wù)的提交都會(huì)將全局時(shí)間戳和事務(wù)相綁定,因此,全局時(shí)間戳的可靠性就非常關(guān)鍵,如果稍微有抖動(dòng),就會(huì)影響到業(yè)務(wù)的連續(xù)性。所以我們希望這種特性做到可配置、可動(dòng)態(tài)開(kāi)關(guān),適時(shí)啟用。所以,做成這種映射方式能夠使上層對(duì)底層沒(méi)有任何依賴以及影響。

640.webp (12).jpg

全局映射還需要考慮映射關(guān)系高性能、可持久性,當(dāng)MySQL異常宕機(jī)時(shí)能夠自動(dòng)恢復(fù)。因此,我們引入了新的系統(tǒng)表空間Tlog,按照GTS時(shí)間戳和事務(wù)ID的方式做映射,內(nèi)部按頁(yè)組織管理。通過(guò)這種方式對(duì)每一個(gè)事務(wù)ID都能找到對(duì)應(yīng)映射關(guān)系的GTS。

那么怎樣整合到Innodb存儲(chǔ)引擎并實(shí)現(xiàn)高性能,即如何把映射文件嵌入到存儲(chǔ)引擎里?下圖中可以看到,改造后對(duì)GTS的映射訪問(wèn)是純內(nèi)存的,即GTS修改直接在內(nèi)存中操作,Tlog在加載以及擴(kuò)展都是映射到Innodb的緩沖池中。對(duì)于映射關(guān)系的修改,往往是事務(wù)提交的時(shí)候,此時(shí)直接在內(nèi)存中修改映射關(guān)系,內(nèi)存中Tlog關(guān)聯(lián)的數(shù)據(jù)頁(yè)變?yōu)榕K頁(yè),同時(shí)在redo日志里增加對(duì)GTS的映射操作,定期通過(guò)刷臟來(lái)維護(hù)磁盤和內(nèi)存中映射關(guān)系的一致性。由于內(nèi)存修改的開(kāi)銷較小,而在redo中也僅僅增加幾十字節(jié),所以整體的寫(xiě)開(kāi)銷可以忽略不計(jì)。

640.webp (13).jpg

這種優(yōu)化的作用下,對(duì)于寫(xiě)事務(wù)的影響不到3%,而對(duì)讀事務(wù)的影響能夠控制在10%以內(nèi)。此外,還需要對(duì)undo頁(yè)清理機(jī)制做改造,將原有的基于最老可見(jiàn)性視圖的刪除方式改為以最小活躍GTS的方式刪除。

GTS和事務(wù)ID的映射是有開(kāi)關(guān)的,打開(kāi)可以做映射,關(guān)閉后退化為單節(jié)點(diǎn)模式。即TDSQL可以提供兩種一致性服務(wù),一種是全局一致性讀,即基于全局GTS串行化實(shí)現(xiàn),另外一種是關(guān)閉這個(gè)開(kāi)關(guān),只保證事務(wù)最終一致性。由于任何改造都是有代價(jià),并不是全局一致性讀特性打開(kāi)比不打開(kāi)更好,而是要根據(jù)業(yè)務(wù)場(chǎng)景做判斷。

開(kāi)啟一致性讀特性雖然能夠解決分布式場(chǎng)景下的可重復(fù)讀問(wèn)題,但是由于新引入了全局GTS組件,該組件一定程度上屬于關(guān)鍵路徑組件,如果其故障業(yè)務(wù)會(huì)受到短暫影響。除此之外,全局一致性讀對(duì)性能也有一定影響。所以,建議業(yè)務(wù)結(jié)合自身場(chǎng)景評(píng)估是否有分布式快照讀需求,若有則打開(kāi),否則關(guān)閉。

立即登錄,閱讀全文
版權(quán)說(shuō)明:
本文內(nèi)容來(lái)自于騰訊云數(shù)據(jù)庫(kù),本站不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。文章內(nèi)容系作者個(gè)人觀點(diǎn),不代表快出海對(duì)觀點(diǎn)贊同或支持。如有侵權(quán),請(qǐng)聯(lián)系管理員(zzx@kchuhai.com)刪除!
相關(guān)文章
騰訊云數(shù)據(jù)庫(kù)PostgreSQL全面支持PG 17
騰訊云數(shù)據(jù)庫(kù)PostgreSQL全面支持PG 17
即日起,騰訊云PostgreSQL全面支持PostgreSQL 17.0。所有用戶可使用大版本升級(jí)能力升級(jí)至最新的PostgreSQL 17.0進(jìn)行體驗(yàn),也可以在產(chǎn)品購(gòu)買頁(yè)直接購(gòu)買。
騰訊云
云服務(wù)
2024-12-152024-12-15
高可用這個(gè)問(wèn)題,加機(jī)器就能解決?
高可用這個(gè)問(wèn)題,加機(jī)器就能解決?
互聯(lián)網(wǎng)服務(wù)的可用性問(wèn)題是困擾企業(yè)IT人員的達(dá)摩克利斯之劍:防于未然,體現(xiàn)不出價(jià)值。已然發(fā)生,又面臨P0危機(jī)。就更別提穩(wěn)定性建設(shè)背后顯性的IT預(yù)算問(wèn)題與隱性的人員成本問(wèn)題。
騰訊云
云服務(wù)
2024-11-252024-11-25
TDSQL TDStore引擎版替換HBase:在歷史庫(kù)場(chǎng)景中的成本與性能優(yōu)勢(shì)
TDSQL TDStore引擎版替換HBase:在歷史庫(kù)場(chǎng)景中的成本與性能優(yōu)勢(shì)
HBase憑借其高可用性、高擴(kuò)展性和強(qiáng)一致性,以及在廉價(jià)PC服務(wù)器上的低部署成本,廣泛應(yīng)用于大規(guī)模數(shù)據(jù)分析。
騰訊云
云服務(wù)
2024-11-042024-11-04
復(fù)雜查詢性能弱,只讀分析引擎來(lái)幫忙
復(fù)雜查詢性能弱,只讀分析引擎來(lái)幫忙
隨著當(dāng)今業(yè)務(wù)的高速發(fā)展,復(fù)雜多表關(guān)聯(lián)的場(chǎng)景越來(lái)越普遍。但基于行式存儲(chǔ)的數(shù)據(jù)庫(kù)在進(jìn)行復(fù)雜查詢時(shí)性能相對(duì)較弱。
騰訊云
云服務(wù)
2024-11-022024-11-02
掃碼登錄
打開(kāi)掃一掃, 關(guān)注公眾號(hào)后即可登錄/注冊(cè)
加載中
二維碼已失效 請(qǐng)重試
刷新
賬號(hào)登錄/注冊(cè)
個(gè)人VIP
小程序
快出海小程序
公眾號(hào)
快出海公眾號(hào)
商務(wù)合作
商務(wù)合作
投稿采訪
投稿采訪
出海管家
出海管家