日前,Distributed Cloud|2021全球分布式云大會·上海站隆重召開。騰訊云憑借其信息技術系統(tǒng)的安全可控性和前沿技術的創(chuàng)新性,在一眾企業(yè)中脫穎而出,榮獲“分布式數(shù)據(jù)庫創(chuàng)新技術獎”。這是繼騰訊云數(shù)據(jù)庫TDSQL獲第四屆中國保險大數(shù)據(jù)分析與人工智能創(chuàng)新國際峰會年度“保險創(chuàng)新者大獎”之后再次獲評。
在云原生專題論壇上,騰訊云數(shù)據(jù)庫產品專家梁文燦先生就騰訊云企業(yè)級分布式數(shù)據(jù)庫TDSQL生態(tài)發(fā)展戰(zhàn)略、落地應用案例做出了詳細介紹。同時騰訊云數(shù)據(jù)庫專家工程師張遠先生對云原生數(shù)據(jù)庫TDSQL-C的內核關鍵技術進行了深入解讀。
TDSQL-C基于全新計算存儲分離的分布式數(shù)據(jù)庫架構,融合傳統(tǒng)數(shù)據(jù)庫和云計算技術優(yōu)勢,100%兼容MySQL和PostgreSQL,極致計算能力突破千核,存儲容量達PB級別,使得性能和安全性媲美商用數(shù)據(jù)庫。并且TDSQL-C支持集群和Serverless靈活彈性部署,克服傳統(tǒng)架構下的存儲量受限、擴展難、主從延遲高等缺點,充分釋放領先技術的成本效益,最高可為企業(yè)節(jié)省90%的成本。
下面帶來騰訊云數(shù)據(jù)庫專家工程師張遠老師主題為《騰訊云TDSQL-C云原生數(shù)據(jù)庫技術》的文字版。
TDSQL-C簡介
張遠介紹說,TDSQL-C是騰訊云自研的新一代企業(yè)級云原生分布式數(shù)據(jù)庫,經過五年的打磨,在總體架構上,TDSQL-C是基于共享存儲的存儲和計算分離的架構。
與傳統(tǒng)的MySQL主備架構對比,可以看到傳統(tǒng)的MySQL主備通過binlog進行邏輯復制,而TDSQL-C是通過redo日志進行的物理復制;傳統(tǒng)的MySQL需要向存儲寫多份數(shù)據(jù)包括data,binlog,redo log等,而TDSQL-C只需向存儲寫一份redo日志即可;傳統(tǒng)的MySQL主備各存儲一份數(shù)據(jù),而TDSQL-C基于共享存儲只有一份數(shù)據(jù)。
TDSQL-C具有以下幾個關鍵的特性:
(1)可靠性。TDSQL-C基于共享存儲的云原生架構,存儲是多副本的,能夠保證數(shù)據(jù)可靠性。同時能夠做到即時回滾,任意時間數(shù)據(jù)都可靠。
(2)極致性能。騰訊云對主備機讀寫性能做了全面優(yōu)化,同時也根據(jù)不同規(guī)格做針對性優(yōu)化。
(3)可用性。TDSQL-C可以做到秒級的RTO,故障幾乎無感知,同時主備延遲可以做到毫秒級。此外,基于共享內存,數(shù)據(jù)能夠快速恢復、快速預熱。
(4)彈性擴展。數(shù)據(jù)能夠快速透明拓展,而且容量最大可以達到1PB,滿足大的需求。
TDSQL-C內核關鍵技術
張遠演講的第二部分圍繞關鍵特性展開,詳細介紹了TDSQL-C特性背后的技術原理和細節(jié)。
1、TDSQL-C之高性能
(1)TDSQL-C高性能-plan cache
TDSQL-C高性能的一個重要優(yōu)化是實現(xiàn)了查詢計劃緩存,稱之為plan cache。
圖中展示了一條SQL在數(shù)據(jù)庫中的執(zhí)行過程,會經過以下幾個階段:
首先MySQL server接受到用戶的SQL請求,在parse階段解析為邏輯的執(zhí)行計劃樹,接下來在查詢優(yōu)化階段生成物理的查詢計劃,然后執(zhí)行器從存儲引擎獲取數(shù)據(jù)進行計算。
經過plan cache優(yōu)化后,一條SQL執(zhí)行過程省略了前面的解析和查詢優(yōu)化階段,SQL的執(zhí)行時間大大縮短了。
=優(yōu)化效果以sysbench場景為例,不同顏色代表不同階段的耗時,可以看到經過plan cache優(yōu)化后,parse和查詢優(yōu)化時間減少了,性能提升了70%左右。
(2)TDSQL-C高性能-異步組提交
TDSQL-C是計算和存儲分離的架構,因此計算節(jié)點和存儲節(jié)點之間的網絡IO存在一定時延。而寫事務提交時需要保證redo先刷盤才能完成提交,因此Redo日志刷盤存在網絡IO。TDSQL-C在線程池的基礎上進行了異步組提交優(yōu)化,事務提交交給后臺線程異步完成,將線程池資源提前釋放從而能夠去處理更多的請求。優(yōu)化后整體的讀寫事務QPS有70%的提升。
(3)TDSQL-C高性能-Log Compaction
TDSQL-C是基于日志的數(shù)據(jù)庫,計算機節(jié)點和存儲節(jié)點之間有日志的傳輸,同時Master節(jié)點和TXStore存儲之間也有redo日志傳輸,TDSQL-C將redo日志進行了壓縮。
下圖是redo日志的結構,一條普通的redo日志包括日志頭和日志內容,日志頭主要包括日志類型以及Space ID和pageno等信息。通常情況下日志頭占了日志的較大一部分。TDSQL-C對redo日志進行壓縮存儲,對于同一頁面進行修改的多條redo日志可以共享一個日志頭。優(yōu)化后redo日志量減少了30%。
2、TDSQL-C之高可用
(1)TDSQL-C高可用-物理復制
傳統(tǒng)的MySQL的是通過binlog進行復制的。Binlog復制是在MySQL server層進行的,binlog記錄的是邏輯的修改記錄,binlog在備庫apply需要經過server層的parser,optimizer后再經過engine的btree查找才能修改到對應的記錄。這個路徑比較長,復制速度慢。
而騰訊云TDSQL-C采用的是redo物理復制。Redo日志記錄的是頁面物理修改記錄,redo復制是在engine層進行的,備庫apply redo日志不需要查找就可以直接定位到頁面,在內存中完成頁面的修改,因此復制速度快。
更重要的一點是,TDSQL-C是基于共享存儲的,主備數(shù)據(jù)物理上是一致的,而binlog復制只能保證邏輯一致。
(2)TDSQL-C高可用-備庫延遲優(yōu)化
TDSQL-C高可用另一個優(yōu)化是備庫延遲優(yōu)化,TDSQL-C最多支持16個備庫提供讀服務,備庫延遲可以達到毫秒級別。其中一個優(yōu)化就是備庫讀寫IO沖突優(yōu)化。TDSQL-C備庫是提供讀服務的,同時備庫也會apply主庫傳來的redo日志。
張遠以場景舉例說,首先用戶讀取pageA,pageA不在buffer pool中,那么會從TXStore中請求pageA,TXStore中請求pageA就存在網絡和IO的開銷。同時redo日志回放線程上有l(wèi)og1/log2/log3正在等待回放到pageA上。也就是說,用戶發(fā)起的讀操作可能阻塞redo日志回放線程,從而導致主備延遲。
優(yōu)化方案是將pageA上的redo日志緩存到page上的鏈表中,pageA IO完成以后再將鏈表中的redo日志回放到pageA上。這樣pageA的IO過程就不阻塞redo的回放了。
(3)TDSQL-C高可用-獨立buffer pool
TDSQL-C高可用的另一個優(yōu)化是獨立buffer pool。Buffer pool是InnoDB數(shù)據(jù)頁的緩存。計算節(jié)點HA重啟后,buffer pool需要重新加載進行預熱,持續(xù)時間比較長,期間業(yè)務會受到較大影響。
TDSQL-C將buffer pool從計算節(jié)點獨立出來放到共享內存中,計算節(jié)點crash后buffer pool可以獨立存在。這樣一來,Buffer pool不需要預熱,重啟時間也縮短了。
(4)TDSQL-C高可用-秒級RTO
TDSQL-C在基于redo日志的架構下,計算節(jié)點crash recovery不需要apply redo,redo的apply由存儲節(jié)點來完成。從而crash recovery時間相比傳統(tǒng)MySQL要快很多。在此基礎上,TDSQL-C做了更多的優(yōu)化,可以做到秒級RTO。例如經過測試,大規(guī)格實例重啟速度比較慢。
例如buffer pool為500G的大實例重啟,初始化buffer pool耗時23秒,這對于用戶來說是不可接受的。優(yōu)化方案是并行初始化加pag上的mutex延遲初始化。并行初始化是指按InnoDB buffer pool instance來并行初始化。而page mutex延遲初始化,是指當page首次使用時才初始化,而不是在啟動時全部都初始化。優(yōu)化后buffer pool初始化速度提升近20倍,而且騰訊云將這個方案也貢獻給了MySQL官方。另外回滾段并行初始化也貢獻給了MySQL官方。
TDSQL-C之彈性擴展
TDSQL-C備庫可以提供讀服務。為了提供更好的讀服務,騰訊云做了許多讀優(yōu)化。Btree一致性讀優(yōu)化就是其中一個。
Btree在數(shù)據(jù)的更新過程中會發(fā)生SMO操作,即btree的分裂或合并。
如圖所示,Btree發(fā)現(xiàn)分裂,page B分裂為pageB和pageC。Btree分裂時,用戶查詢pageB可能導致數(shù)據(jù)不一致甚至crash。但主庫在Btree發(fā)生分裂時會通過index鎖和page lock的方式保證正在發(fā)生分裂的page不被其他用戶訪問。但對于備庫來說,備庫通過redo日志不能感知Btree的SMO操作,SMO操作所產生的日志只有頁面修改的信息,redo日志中沒有index lock上鎖信息。因此備庫在SMO過程是沒有被保護的,備庫的查詢可能異常。
這里有一個可選方案就是將SMO操作index lock記錄到日志中,備庫解析index lock日志對整個btree加index lock。但index lock會鎖整個btree導致并發(fā)查詢性能比較差。
TDSQL-C對此進行了優(yōu)化,MySQL的SMO操作是原子的,所有產生的redo日志都在一個mini-transaction中。引入新的日志類型來標記redo日志中SMO操作的邊界。這樣用戶在查詢btree過程遇到page在SMO操作重新掃描btree即可。例如用戶訪問page A時會判斷一下page是否在SMO,如果A在,則會在mtr start和end之間則重試。
這樣優(yōu)化后,備庫讀不會被主庫更新產生的SMO操作所阻塞。
TDSQL-C其它特性
TDSQL-C秒改列(instant modify column)
在官方MySQL8.0支持instant add column后,修改列類型操作便順勢成為MySQL中最不友好的DDL類型,修改列類型既不是inplace的同時也需要rebuild table。而在我們用戶實踐中,修改列類型也是用戶執(zhí)行比較頻繁的DDL之一,而此操作會長時間阻塞用戶的讀寫請求,對業(yè)務的影響非常大。
TDSQL-C創(chuàng)新的支持了instant modify column功能,達到了秒級修改列的效果。
具體的實現(xiàn)方式是:
a.元數(shù)據(jù)多版本化,表元數(shù)據(jù)保存列的多個版本信息,用戶只能看到的總是最新的表元數(shù)據(jù)。
b.行記錄增加版本信息對應到不同版本的表元數(shù)據(jù)上。
c.修改列只修改元數(shù)據(jù),修改列的過程中不修改實際的行記錄。
d.行記錄讀取時,老版本記錄會自動轉換為最新版本的記錄。
e.行記錄更新時,老版本記錄會自動更新為最新版本的記錄。
值得注意的是,這是業(yè)界首創(chuàng)的方案。
TDSQL-C purge預讀
Undo空間膨脹問題是MySQL歷史老大難問題,TDSQL-C創(chuàng)新的通過purge預讀解決了此問題。Purge會讀取undo page并清理delete mark的記錄,清理完成后會釋放undo page,從而最終釋放undo表空間。IO bound場景,purge時讀取undo page更容易出現(xiàn)remote IO。而remote IO時占用時間比較長,導致purge不及時undo日志空間膨脹。
解決方法是實現(xiàn)purge預讀機制:
a.根據(jù)事務提交順序在內存中保存undo page的purge順序用于預讀。
b.Purge coordinator異步預讀這些page。
TDSQL-C展望
展望TDSQL-C的未來發(fā)展,張遠表示,未來TDSQL-C會進一步加強查詢優(yōu)化的能力,比如增加新的join類型如SMJ,以及在parallel query上做一些拓展。同時TDSQL在支持多寫方面會進一步探索,未來TDSQL-C也會向HTAP方向演進,TDSQL-C會同時具備OLTP和OLAP的能力。