首先,受益于第三代分布式共享存儲(chǔ)架構(gòu),使POLARDB實(shí)現(xiàn)了計(jì)算節(jié)點(diǎn)(主要做SQL解析以及存儲(chǔ)引擎計(jì)算的服務(wù)器)與存儲(chǔ)節(jié)點(diǎn)(主要做數(shù)據(jù)塊存儲(chǔ),數(shù)據(jù)庫(kù)快照的服務(wù)器)的分離,提供了即時(shí)生效的可擴(kuò)展能力和運(yùn)維能力。
眾所周知,在傳統(tǒng)數(shù)據(jù)庫(kù)上做擴(kuò)容、備份和遷移等操作,花費(fèi)的時(shí)間和數(shù)據(jù)庫(kù)的容量成正比,往往上TB的數(shù)據(jù)庫(kù)容量加個(gè)只讀副本就需要一到兩天時(shí)間。POLARDB的存儲(chǔ)容量可以實(shí)現(xiàn)無(wú)縫擴(kuò)展,不管數(shù)據(jù)量有多大,2分鐘內(nèi)即可實(shí)現(xiàn)只讀副本擴(kuò)容,1分鐘內(nèi)即可實(shí)現(xiàn)全量備份,為企業(yè)的快速業(yè)務(wù)發(fā)展提供了彈性擴(kuò)展能力。
其次,與傳統(tǒng)云數(shù)據(jù)庫(kù)一個(gè)實(shí)例一份數(shù)據(jù)拷貝不同,POLARDB同一個(gè)實(shí)例的所有節(jié)點(diǎn)(包括讀寫(xiě)節(jié)點(diǎn)和只讀節(jié)點(diǎn))都實(shí)現(xiàn)訪問(wèn)存儲(chǔ)節(jié)點(diǎn)上的同一份數(shù)據(jù),使得POLARDB的數(shù)據(jù)備份耗時(shí)實(shí)現(xiàn)秒級(jí)響應(yīng)。(備份時(shí)間與底層數(shù)據(jù)量無(wú)關(guān))
最后,借助優(yōu)秀的RDMA網(wǎng)絡(luò)以及最新的塊存儲(chǔ)技術(shù),實(shí)現(xiàn)服務(wù)器宕機(jī)后無(wú)需搬運(yùn)數(shù)據(jù)重啟進(jìn)程即可服務(wù),滿足了互聯(lián)網(wǎng)環(huán)境下企業(yè)對(duì)數(shù)據(jù)庫(kù)服務(wù)器高可用的需求。
為什么POLARDB能做到6倍于MySQL的性能?
這里我們將分別以存儲(chǔ)性能、計(jì)算性能來(lái)進(jìn)行解讀詮釋。
1.POLARDB的存儲(chǔ)引擎性能優(yōu)化
眾所周知,關(guān)系型數(shù)據(jù)庫(kù)是IO密集型的應(yīng)用,IO性能的提高對(duì)數(shù)據(jù)庫(kù)的性能提升至關(guān)重要。過(guò)去十年我們看到在數(shù)據(jù)庫(kù)領(lǐng)域,SSD替換HDD的過(guò)程給數(shù)據(jù)庫(kù)數(shù)據(jù)處理的吞吐能力帶來(lái)了數(shù)量級(jí)的提升。
POLARDB采用了領(lǐng)先的硬件技術(shù):包括使用3DXpoint存儲(chǔ)介質(zhì)的Optane存儲(chǔ)卡、NVMe SSD和RoCE RDMA網(wǎng)絡(luò)。同時(shí)面向新硬件架構(gòu)實(shí)現(xiàn)軟硬一體優(yōu)化:從數(shù)據(jù)庫(kù)、文件系統(tǒng)到網(wǎng)絡(luò)通訊協(xié)議、分布式存儲(chǔ)系統(tǒng)和設(shè)備驅(qū)動(dòng),POLARDB實(shí)現(xiàn)縱貫軟件棧各層次的整個(gè)IO鏈條的深度優(yōu)化。
為了將3DXpoint顆粒的高性能和3D NAND顆粒的低成本結(jié)合起來(lái),POLARDB創(chuàng)新的在軟件層實(shí)現(xiàn)對(duì)高速的Optane卡和大容量高吞吐的NVMe SSD進(jìn)行組合,實(shí)現(xiàn)一個(gè)名為混合存儲(chǔ)層。既保證數(shù)據(jù)寫(xiě)入的低延遲、高吞吐、高QoS,又使整體方案兼具較高的性價(jià)比。
在POLARDB里,為了追求更高的性能、更低的延遲,阿里云數(shù)據(jù)庫(kù)團(tuán)隊(duì)大膽的拋棄了Linux內(nèi)核提供的各種機(jī)制,比如塊設(shè)備、各種文件系統(tǒng)例如ext4,以及TCP/IP協(xié)議棧和socket編程接口而選擇了另起爐灶。最終,POLARDB實(shí)現(xiàn)了一整套在用戶態(tài)運(yùn)行的IO和網(wǎng)絡(luò)協(xié)議棧。
POLARDB用戶態(tài)協(xié)議棧解決了內(nèi)核IO協(xié)議棧慢的問(wèn)題。用戶程序在用戶態(tài)直接通過(guò)DMA操作硬件設(shè)備,通過(guò)輪詢的方式監(jiān)聽(tīng)硬件設(shè)備完成IO事件,消除了上下文切換和中斷的開(kāi)銷。用戶程序還可以將IO處理線程和cpu進(jìn)行一一映射,每個(gè)IO處理線程獨(dú)占CPU,相互之間處理不同的IO請(qǐng)求,綁定不同的IO設(shè)備硬件隊(duì)列,一個(gè)IO請(qǐng)求生命周期從頭到尾都在一個(gè)線程一顆CPU上處理,不需要鎖進(jìn)行互斥。這種技術(shù)實(shí)現(xiàn)最大化的和高速設(shè)備進(jìn)行性能交互,實(shí)現(xiàn)一顆CPU達(dá)每秒約20萬(wàn)次IO處理的能力,并且保持線性的擴(kuò)展能力,也就意味著4顆CPU可以達(dá)到每秒80萬(wàn)次IO處理的能力,在性能和經(jīng)濟(jì)型上遠(yuǎn)高于內(nèi)核。
網(wǎng)絡(luò)也是類似的情況。過(guò)去傳統(tǒng)的以太網(wǎng),網(wǎng)卡發(fā)一個(gè)報(bào)文到另一臺(tái)機(jī)器,中間通過(guò)一跳交換機(jī),大概需要一百到兩百微秒。POLARDB支持ROCE以太網(wǎng),應(yīng)用程序通過(guò)RDMA網(wǎng)絡(luò),直接將本機(jī)的內(nèi)存寫(xiě)入另一臺(tái)機(jī)器的內(nèi)存地址,或者從另一臺(tái)機(jī)器的內(nèi)存讀一塊數(shù)據(jù)到本機(jī),中間的通訊協(xié)議編解碼、重傳機(jī)制都由RDMA網(wǎng)卡來(lái)完成,不需要CPU參與,使性能獲得極大提升,傳輸一個(gè)4k大小報(bào)文只需要6、7微秒的時(shí)間。如同內(nèi)核的IO協(xié)議棧跟不上高速存儲(chǔ)設(shè)備能力,再一次的,內(nèi)核的TCP/IP協(xié)議棧跟不上高速網(wǎng)絡(luò)設(shè)備能力,被POLARDB的用戶態(tài)網(wǎng)絡(luò)協(xié)議棧代替。
大家都知道關(guān)系型數(shù)據(jù)庫(kù)的重要特性歸納起來(lái)是“ACID”,其中A是原子性,C是約束,I是隔離性,D是持久性。
POLARDB將從兩個(gè)維度出發(fā),從根本上改進(jìn)多副本復(fù)制。一個(gè)是保證數(shù)據(jù)庫(kù)ACID中的D(Durable),把網(wǎng)絡(luò)、存儲(chǔ)硬件提供的DMA能力串起,用硬件通道高性能的把主庫(kù)的日志數(shù)據(jù)持久化到三個(gè)存儲(chǔ)節(jié)點(diǎn)的磁盤中;另一個(gè)是實(shí)現(xiàn)了高效的只讀節(jié)點(diǎn),在主庫(kù)和只讀節(jié)點(diǎn)之間通過(guò)物理復(fù)制同步數(shù)據(jù),直接更新到只讀節(jié)點(diǎn)的內(nèi)存里。 如何實(shí)現(xiàn)?
POLARDB實(shí)現(xiàn)日志數(shù)據(jù)持久化到三個(gè)存儲(chǔ)節(jié)點(diǎn)的磁盤中。主庫(kù)通過(guò)RDMA將日志數(shù)據(jù)發(fā)送到存儲(chǔ)節(jié)點(diǎn)的內(nèi)存中,存儲(chǔ)節(jié)點(diǎn)之間再通過(guò)RDMA互相復(fù)制,每個(gè)存儲(chǔ)節(jié)點(diǎn)用SPDK將數(shù)據(jù)寫(xiě)入NVMe接口的存儲(chǔ)介質(zhì)里,整個(gè)過(guò)程CPU不用訪問(wèn)被同步的數(shù)據(jù)塊(Payload),實(shí)現(xiàn)數(shù)據(jù)零拷貝。
同時(shí)由RDMA網(wǎng)卡和NVMe控制器完成數(shù)據(jù)傳輸和持久化,CPU僅做狀態(tài)機(jī)的維護(hù),在一致性協(xié)議的協(xié)調(diào)下,把網(wǎng)卡和存儲(chǔ)卡兩塊硬件串起來(lái),存儲(chǔ)節(jié)點(diǎn)之間數(shù)據(jù)同步采用并發(fā)Raft(Parallel Raft)協(xié)議,和Raft協(xié)議一樣,決議在leader節(jié)點(diǎn)上是串行生成和提交的,但并發(fā)Raft協(xié)議可以允許主從之間亂序同步,簡(jiǎn)單的說(shuō),允許follower節(jié)點(diǎn)在漏掉若干條日志的情況先commit并apply后面過(guò)來(lái)的日志,并異步的去補(bǔ)之前漏掉的日志,數(shù)據(jù)同步的性能和穩(wěn)定性都顯著優(yōu)于Raft協(xié)議。
POLARDB在主庫(kù)和只讀實(shí)例之間的數(shù)據(jù)流上,放棄了基于binlog的邏輯復(fù)制,而是基于innodb的redolog實(shí)現(xiàn)了物理復(fù)制,從邏輯復(fù)制到物理復(fù)制對(duì)主庫(kù)和從庫(kù)性能帶來(lái)的提升都非常明顯。
在主庫(kù)上,原本引擎需要和binlog做XA事務(wù),事務(wù)要等到binlog和redolog同時(shí)寫(xiě)盤后才能返回,去掉binlog后,XA事務(wù)可以去掉,事務(wù)的執(zhí)行路徑更短,IO開(kāi)銷也更小。在從庫(kù)上,redolog由于是物理復(fù)制,僅需比對(duì)頁(yè)面的LSN就可以決定是否回放,天然可以多線程執(zhí)行,數(shù)據(jù)的正確性也更有保證,此外,POLARDB的從庫(kù)收到redolog后只需要更新緩存里的頁(yè)面,并不需要寫(xiě)盤和IO操作,開(kāi)銷遠(yuǎn)低于傳統(tǒng)多副本復(fù)制里的從庫(kù)。
POLARDB的存儲(chǔ)節(jié)點(diǎn)針對(duì)數(shù)據(jù)庫(kù)的IO workload進(jìn)行了一些針對(duì)性的優(yōu)化。
IO優(yōu)先級(jí)優(yōu)化:POLARDB在文件系統(tǒng)和存儲(chǔ)節(jié)點(diǎn)兩層都開(kāi)了綠色通道,對(duì)redolog文件的更新進(jìn)行優(yōu)待處理,減少排隊(duì),提高IO的優(yōu)先級(jí)。redolog也從512對(duì)齊調(diào)整為4k對(duì)齊,對(duì)SSD性能更加友好。
double write優(yōu)化:POLARDB存儲(chǔ)節(jié)點(diǎn)原生支持1MB的原子寫(xiě),因此可以安全關(guān)閉double write,從而節(jié)省了近一倍的IO開(kāi)銷。
group commit優(yōu)化:POLARDB里一次group commit可以產(chǎn)生寫(xiě)入幾百KB的單個(gè)大IO。對(duì)于單個(gè)SSD,延遲和IO的大小是呈線性的,而POLARDB從文件系統(tǒng)到存儲(chǔ)節(jié)點(diǎn)都進(jìn)行一系列優(yōu)化來(lái)保證這種類型的IO能盡快刷下去,針對(duì)redolog文件進(jìn)行條帶化,將一個(gè)上百KB的大IO切割為一批16KB的較小IO,分發(fā)到多個(gè)存儲(chǔ)節(jié)點(diǎn)和不同的磁盤上去執(zhí)行,進(jìn)一步的降低關(guān)鍵IO路徑的延遲。
2.POLARDB的計(jì)算引擎性能優(yōu)化
由于POLARDB使用共享存儲(chǔ)和物理復(fù)制,實(shí)例的備份恢復(fù)也做到完全依賴redolog,因此去掉了binlog。使得單個(gè)事務(wù)對(duì)io的消耗減少,有效減少語(yǔ)句響應(yīng)時(shí)間,提升吞吐量。同時(shí)避免了引擎需要與binlog做的XA事務(wù)邏輯,事務(wù)語(yǔ)句的執(zhí)行路徑更短。
POLARDB針對(duì)高并發(fā)場(chǎng)景,對(duì)引擎內(nèi)部鎖做了大量?jī)?yōu)化,比如把latch分解成粒度更小的鎖,或者把latch改成引用計(jì)數(shù)的方式從而避免鎖競(jìng)爭(zhēng),例如Undo segment mutex, log system mutex等等。PolarDB還把部分熱點(diǎn)的數(shù)據(jù)結(jié)構(gòu)改成了Lock Free的結(jié)構(gòu),例如Server層的MDL鎖。
Redolog的順序?qū)懶阅軐?duì)數(shù)據(jù)庫(kù)性能的影響很大,為了減少Redolog切換時(shí)對(duì)性能的影響,我們后臺(tái)采用類似Fallocate的方式預(yù)先分配日志文件,此外,現(xiàn)代的SSD硬盤很多都是4K對(duì)齊,而MySQL代碼還是按照早期磁盤512字節(jié)對(duì)齊的方式刷日志的,這樣會(huì)導(dǎo)致磁盤做很多不必要的讀操作,不能發(fā)揮出SSD盤的性能,我們?cè)谶@方面也做了優(yōu)化。我們對(duì)日志提交時(shí)Group Commit進(jìn)行優(yōu)化,同時(shí)采用Double RedoLog Buffer提升并行度。
POLARDB中物理復(fù)制的性能至關(guān)重要,我們不僅通過(guò)基于數(shù)據(jù)頁(yè)維度的并行提高了性能,還對(duì)復(fù)制中的必要流程進(jìn)行了優(yōu)化,例如在MTR日志中增加了一個(gè)長(zhǎng)度字段,從而減少了日志Parse階段的CPU開(kāi)銷,這個(gè)簡(jiǎn)單的優(yōu)化就能減少60%的日志Parse時(shí)間。我們還通過(guò)復(fù)用Dummy Index的內(nèi)存數(shù)據(jù)結(jié)構(gòu),減少了其在Malloc/Free上的開(kāi)銷,進(jìn)一步提高復(fù)制性能。
POLARDB的Replica節(jié)點(diǎn),日志目前是一批一批應(yīng)用的,因此當(dāng)新的一批日志被應(yīng)用之前,Replica上的讀請(qǐng)求不需要重復(fù)創(chuàng)建新的ReadView,可以使用上次緩存下來(lái)的。這個(gè)優(yōu)化也能提高Replica上的讀性能。
為什么POLARDB能做到遠(yuǎn)低于商業(yè)數(shù)據(jù)庫(kù)的成本
POLARDB采用了一種計(jì)算和存儲(chǔ)分離的架構(gòu),DB運(yùn)行在計(jì)算節(jié)點(diǎn),計(jì)算節(jié)點(diǎn)組成了一個(gè)計(jì)算資源池,數(shù)據(jù)都放在存儲(chǔ)節(jié)點(diǎn)上,存儲(chǔ)節(jié)點(diǎn)組成了一個(gè)存儲(chǔ)資源池。如果CPU和內(nèi)存不夠了,就擴(kuò)充計(jì)算資源池,如果容量或者IOPS不夠了,就擴(kuò)充存儲(chǔ)資源池,兩個(gè)池子都是按需擴(kuò)容。而且存儲(chǔ)節(jié)點(diǎn)和計(jì)算節(jié)點(diǎn)可以分別向兩個(gè)方向優(yōu)化,存儲(chǔ)節(jié)點(diǎn)會(huì)選擇低配的CPU和內(nèi)存,提高存儲(chǔ)密度,而計(jì)算節(jié)點(diǎn)可以選擇小容量、低配的SSD作為操作系統(tǒng)和日志盤,上多路服務(wù)器增加CPU的核數(shù)。
而傳統(tǒng)的數(shù)據(jù)庫(kù)部署模型則是一種煙囪模型,一臺(tái)主機(jī)既跑數(shù)據(jù)庫(kù)又存數(shù)據(jù),這帶來(lái)兩個(gè)問(wèn)題。一個(gè)是機(jī)型難以選擇,CPU和磁盤的配比主要取決于實(shí)際業(yè)務(wù)的需求,很難提前找到最優(yōu)比例。第二是磁盤碎片問(wèn)題,一個(gè)生產(chǎn)集群里,總有部分機(jī)器磁盤使用率是很低的,有的還不到10%,但出于業(yè)務(wù)穩(wěn)定性要求,會(huì)要求獨(dú)占主機(jī)的CPU,這些機(jī)器上的SSD其實(shí)是被浪費(fèi)的。通過(guò)存儲(chǔ)資源池化,這兩個(gè)問(wèn)題都能得到解決,SSD的利用率得到提高,成本自然也降低下來(lái)。
POLARDB的存儲(chǔ)節(jié)點(diǎn)除了對(duì)ibd文件提供1MB的原子寫(xiě),消除double write的開(kāi)銷,還支持對(duì)ibd文件的數(shù)據(jù)塊進(jìn)行透明壓縮,壓縮率可以達(dá)到2.4倍,進(jìn)一步降低了存儲(chǔ)成本。
而傳統(tǒng)數(shù)據(jù)庫(kù)在DB內(nèi)進(jìn)行壓縮的方案相比,存儲(chǔ)節(jié)點(diǎn)實(shí)現(xiàn)透明壓縮不消耗計(jì)算節(jié)點(diǎn)的CPU,不影響DB的性能,利用QAT卡進(jìn)行加速,以及在IO路徑上用FPGA進(jìn)行加速。POLARDB的存儲(chǔ)節(jié)點(diǎn)還支持快照去重(dedup)功能,數(shù)據(jù)庫(kù)的相鄰快照之間,如果頁(yè)面沒(méi)有發(fā)生修改,會(huì)鏈接到同一份只讀頁(yè)面上,物理上只會(huì)存儲(chǔ)一份。
傳統(tǒng)數(shù)據(jù)庫(kù)做只讀實(shí)例,實(shí)施一寫(xiě)多讀方案,是通過(guò)搭建只讀副本的方案,先拷貝一個(gè)最近的全量備份恢復(fù)一個(gè)臨時(shí)實(shí)例,再讓這個(gè)臨時(shí)實(shí)例連接主庫(kù)或者其他binlog源同步增量數(shù)據(jù),增量追上后,把這個(gè)臨時(shí)實(shí)例加到線上升級(jí)為一個(gè)只讀副本。這種方法一個(gè)是耗時(shí),搭建一個(gè)只讀實(shí)例需要的時(shí)間與數(shù)據(jù)量成正比;另一方面也很昂貴,需要增加一份存儲(chǔ)成本,比如用戶購(gòu)買一個(gè)主實(shí)例加上五個(gè)只讀實(shí)例,需要付7~8份存儲(chǔ)的錢(7份還是8份取決于主實(shí)例是兩副本還是三副本)。
而在PolarDB架構(gòu)中,這兩個(gè)問(wèn)題都得到解決,一方面新增只讀實(shí)例不需要拷貝數(shù)據(jù),不管數(shù)據(jù)量有多大都可以在2分鐘內(nèi)創(chuàng)建出來(lái);另一方面,主實(shí)例和只讀實(shí)例共享同一份存儲(chǔ)資源,通過(guò)這種架構(gòu)去增加只讀副本,可以做到零新增存儲(chǔ)成本,用戶只需要支付只讀實(shí)例消耗的CPU和內(nèi)存的費(fèi)用。
POLARDB是未來(lái)云數(shù)據(jù)庫(kù)的雛形(All in one),一個(gè)數(shù)據(jù)庫(kù)即可滿足現(xiàn)時(shí)多類數(shù)據(jù)庫(kù)混合使用效果。阿里云發(fā)揮自身自研能力優(yōu)勢(shì),以POLARDB為產(chǎn)品契機(jī),實(shí)現(xiàn)數(shù)據(jù)庫(kù)OLTP與OLAP的一體化設(shè)計(jì),為企業(yè)的數(shù)字化升級(jí)所需的IT設(shè)施架構(gòu)實(shí)現(xiàn)革命性進(jìn)化。
【本文作者系阿里云資深技術(shù)專家曹偉、林曉斌】