云數(shù)據(jù)庫實(shí)現(xiàn)計(jì)算存儲(chǔ)分離,支持計(jì)算與存儲(chǔ)的獨(dú)立擴(kuò)展,其用戶還可以享受按量付費(fèi)等特性。這使得基于云數(shù)據(jù)庫的系統(tǒng)更加高效、靈活。因此,構(gòu)建并使用云原生數(shù)據(jù)庫的勢(shì)頭愈演愈烈。另一方面,云化存儲(chǔ)服務(wù)已經(jīng)是云的標(biāo)準(zhǔn)能力,存儲(chǔ)側(cè)提供兼容通用的文件接口,并且不對(duì)外暴露持久化、容錯(cuò)處理等復(fù)雜細(xì)節(jié),其易用性和規(guī)模化帶來的高性價(jià)比使得云存儲(chǔ)成為了云上系統(tǒng)的第一選擇。在通用云存儲(chǔ)服務(wù)上構(gòu)建云數(shù)據(jù)庫,無疑是一種既能夠享受規(guī)模化云存儲(chǔ)紅利,又能夠通過可靠云存儲(chǔ)服務(wù)實(shí)現(xiàn)降低維護(hù)成本、加速數(shù)據(jù)庫開發(fā)周期的方案。 然而,考慮到云存儲(chǔ)和本地存儲(chǔ)之間的特性差異,在將本地?cái)?shù)據(jù)庫遷移到云上構(gòu)建云數(shù)據(jù)庫時(shí),如何有效使用云存儲(chǔ)面臨了許多挑戰(zhàn)。對(duì)此,我們?cè)谡撐睦锓治隽嘶贐-tree和LSM-tree的存儲(chǔ)引擎在云存儲(chǔ)上部署時(shí)面臨的挑戰(zhàn),并提出了一個(gè)優(yōu)化框架CloudJump,以希望能夠幫助數(shù)據(jù)庫開發(fā)人員在基于云存儲(chǔ)構(gòu)建數(shù)據(jù)庫時(shí)使系統(tǒng)更為高效。我們以云原生數(shù)據(jù)庫PolarDB為案例,展示了一系列針對(duì)性優(yōu)化,并將部分工作擴(kuò)展應(yīng)用到基于云存儲(chǔ)的RocksDB上,以此來演示CloudJump的可用性。
背景 我們討論的云存儲(chǔ)主要基于彈性分布式塊存儲(chǔ),云中其他類型的存儲(chǔ)服務(wù),例如基于對(duì)象的存儲(chǔ),不在本文的討論范圍內(nèi)。共享云存儲(chǔ)(如分布式塊存儲(chǔ)服務(wù)加分布式文件系統(tǒng))可以作為多個(gè)計(jì)算節(jié)點(diǎn)的共享存儲(chǔ)層,提供QoS(服務(wù)質(zhì)量)保證、大容量、彈性和按量付費(fèi)定價(jià)模型。對(duì)于大多數(shù)云廠商和云用戶來說,擁有云存儲(chǔ)服務(wù)比構(gòu)建和維護(hù)裸機(jī)SSD集群更有吸引力。因此,與其為云本機(jī)數(shù)據(jù)庫構(gòu)建和優(yōu)化專用存儲(chǔ)服務(wù),不如利用現(xiàn)有云存儲(chǔ)服務(wù)構(gòu)建云本機(jī)數(shù)據(jù)庫,這是一種非常可行的選擇。此外,隨著云存儲(chǔ)服務(wù)幾乎實(shí)現(xiàn)了標(biāo)準(zhǔn)化,相應(yīng)的開發(fā)、遷移變得更加快速。
圖1展示了本地?cái)?shù)據(jù)庫(不含備份)與shared-storage云原生數(shù)據(jù)庫的系統(tǒng)結(jié)構(gòu),AWS Aurora首先引導(dǎo)了這種從本地?cái)?shù)據(jù)庫向shared-storage云原生數(shù)據(jù)庫的遷移。它將數(shù)據(jù)庫分為存儲(chǔ)層和計(jì)算層,并可以獨(dú)立擴(kuò)展每一層。為了消除了傳輸數(shù)據(jù)頁中產(chǎn)生的沉重的網(wǎng)絡(luò)開銷,它進(jìn)一步定制了存儲(chǔ)層,在數(shù)據(jù)頁上應(yīng)用重做日志,從而不再需要在兩層之間傳輸數(shù)據(jù)頁。無疑這種設(shè)計(jì)在云中提供了一種非標(biāo)準(zhǔn)存儲(chǔ)服務(wù),只能由Aurora的計(jì)算層使用。 另一種方案是依賴標(biāo)準(zhǔn)化接口的云存儲(chǔ)服務(wù)遷移或構(gòu)建獲得云數(shù)據(jù)庫,這也是本文的研究目標(biāo)。前面已經(jīng)提到過,這樣做的優(yōu)勢(shì)主要在于的可以實(shí)現(xiàn)系統(tǒng)的快速開發(fā)、平滑遷移、收納標(biāo)準(zhǔn)化規(guī)模化存儲(chǔ)服務(wù)的原有優(yōu)勢(shì)等。此外,特別是在我們項(xiàng)目(PolarDB)的硬件環(huán)境、已有背景下,兼顧服務(wù)可靠性和開發(fā)迭代需求,針對(duì)進(jìn)行云存儲(chǔ)服務(wù)特性進(jìn)行性能優(yōu)化是最迫切的第一步。
挑戰(zhàn)與分析 云存儲(chǔ)和本地SSD存儲(chǔ)在帶寬、延遲、彈性、容量等方面存在巨大差異,例如圖2展示了在穩(wěn)態(tài)條件下本地SSD與云存儲(chǔ)I/O延時(shí)、帶寬與工作線程關(guān)系,它們對(duì)數(shù)據(jù)庫等設(shè)計(jì)有著巨大影響。此外,共享存儲(chǔ)的架構(gòu)特性也會(huì)對(duì)云存儲(chǔ)帶來影響,如多個(gè)節(jié)點(diǎn)之間的數(shù)據(jù)一致性增加了維護(hù)cache一致性開銷。
通過系統(tǒng)實(shí)驗(yàn)、總結(jié)分析等,我們發(fā)現(xiàn)CloudJump面臨以下技術(shù)挑戰(zhàn):
遠(yuǎn)程分布式存儲(chǔ)集群的訪問導(dǎo)致云存儲(chǔ)服務(wù)的I/O延遲高;
通常聚合I/O帶寬未被充分利用;
在具有本地存儲(chǔ)的單機(jī)上運(yùn)行良好但需要適應(yīng)云存儲(chǔ)而導(dǎo)致特性改變的傳統(tǒng)設(shè)計(jì),例如文件cache緩存;
長鏈路導(dǎo)致各種數(shù)據(jù)庫I/O操作之間的隔離度較低(例如,日志刷寫與大量數(shù)據(jù)I/O的競(jìng)爭(zhēng));
云用戶允許且可能使用非常大的單表文件(例如數(shù)十TB)而不進(jìn)行數(shù)據(jù)切分,這加劇了I/O問題的影響。
針對(duì)不同的數(shù)據(jù)存儲(chǔ)引擎,如基于B-tree和LSM-tree的存儲(chǔ)引擎,這些特性差異會(huì)帶來不同的性能差異,表1歸納總結(jié)了這些挑戰(zhàn)及其對(duì)數(shù)據(jù)庫設(shè)計(jì)的影響。其中有共性問題,如WAL路徑寫入變慢、共享存儲(chǔ)(分布式文件系統(tǒng))cache一致性代價(jià)等;也有個(gè)性問題,如B-tree結(jié)構(gòu)在獨(dú)占資源情況下做遠(yuǎn)程I/O、遠(yuǎn)程加劇I/OLSM-tree讀放大影響等。
優(yōu)化原則 CloudJump針對(duì)上述挑戰(zhàn),提出7條優(yōu)化準(zhǔn)則:
Thread-level Parallelism:例如依據(jù)I/O特性實(shí)驗(yàn),采用(更)多線程的日志、數(shù)據(jù)I/O線程及異步I/O模型,將數(shù)據(jù)充分打散到多個(gè)存儲(chǔ)節(jié)點(diǎn)上。
Task-level Parallelism:例如對(duì)集中Log buffer按Page Partition分片,實(shí)現(xiàn)并行寫入并基于分片進(jìn)行并行Recovery。
Reduce remote read and Prefetching:例如通過收集并聚合原分散meta至統(tǒng)一的superblock,將多個(gè)I/O合一實(shí)現(xiàn)fast validating;通過預(yù)讀利用聚合讀帶寬、減少讀任務(wù)延時(shí);通過壓縮、filter過濾減少讀取數(shù)據(jù)量。與本地SSD上相比,這些技術(shù)在云存儲(chǔ)上更能獲得收益。
Fine-grained Locking and Lock-free Data Structures:云存儲(chǔ)中較長的I/O延遲放大了同步開銷,主要針對(duì)Update-in-place系統(tǒng),實(shí)現(xiàn)無鎖刷臟、無鎖SMO等。
Scattering among Distributed Nodes:在云存儲(chǔ)中,多個(gè)節(jié)點(diǎn)之間的分散訪問可以利用更多的硬件資源,例如將單個(gè)大I/O并發(fā)分散至不同存儲(chǔ)節(jié)點(diǎn) ,充分利用聚合帶寬。
Bypassing Caches:通過Bypassing Caches來避免分布式文件系統(tǒng)的cache coherence,并在DB層面優(yōu)化I/O格式匹配存儲(chǔ)最佳request格式。
Scheduling Prioritized I/O Tasks:由于訪問鏈路更長(如路徑中存在更多的排隊(duì)情況),不填I(lǐng)/O請(qǐng)求間的隔離性相對(duì)本地存儲(chǔ)更低,因此需要在DB層面對(duì)不同I/O進(jìn)行打標(biāo)、調(diào)度優(yōu)先級(jí),例:優(yōu)先WAL、預(yù)讀分級(jí)。
實(shí)踐案例
實(shí)踐案例:PolarDB
PolarDB構(gòu)建基于具有兼容Posix接口的分布式文件系統(tǒng)PolarFS,與Aurora一樣采用計(jì)算存儲(chǔ)分離架構(gòu),借助高速RDMA網(wǎng)絡(luò)以及最新的塊存儲(chǔ)技術(shù)實(shí)現(xiàn)超低延遲和高可用能力能力。在PolarDB上,我們做了許多適配于分布式存儲(chǔ)特性、符合CloudJump準(zhǔn)則的性能優(yōu)化,大幅提升了云原生數(shù)據(jù)庫PolarDB的性能。
1. WAL寫入優(yōu)化 WAL(Write ahead log)寫入是用于一致性和持久性的關(guān)鍵路徑,事務(wù)的寫入性能對(duì)log I/O的延遲非常敏感。原生InnoDB以MTR(Mini-Transaction)的粒度組織日志,并保有一個(gè)全局redo日志緩沖區(qū)。當(dāng)一個(gè)MTR被提交時(shí),它緩存的所有日志記錄被追加到全局日志緩沖區(qū),然后集中的順序刷盤以保證持久化特性。這一傳統(tǒng)集中日志模式在本地盤上工作良好,但使用云存儲(chǔ)時(shí),集中式日志的寫入性能隨著遠(yuǎn)程I/O時(shí)延變高而下降,進(jìn)而影響事務(wù)寫入性能。基于云存儲(chǔ)的特性,我們提出了兩個(gè)優(yōu)化來提升WAL的寫入性能:日志分片和(大)I/O任務(wù)并行打散。
Redo日志分片:InnoDB的redo采用的是Physiological Logging的方式,大部分MTR針對(duì)單個(gè)的數(shù)據(jù)頁(除部分特殊),頁之間基本相互獨(dú)立。如圖5(左),我們將redo日志、redo緩沖區(qū)等按其修改的page進(jìn)行分片(partition),分別寫入不同的文件中,來支持并發(fā)寫log(以及并發(fā)Recovery,并發(fā)物理復(fù)制等),從而在并發(fā)寫友好的分布式文件系統(tǒng)上的獲得寫入性能優(yōu)勢(shì)。 I/O任務(wù)并行打散:在云存儲(chǔ)中,一個(gè)文件由多個(gè)chunk組成,根據(jù)chunk的分配策略,不同chunk很可能位于不同的存儲(chǔ)節(jié)點(diǎn)中。我們將每個(gè)redo分片(partition)的文件進(jìn)一步拆分為多個(gè)物理分片(split),如圖5(右)所示,對(duì)于單個(gè)大log I/O任務(wù)(如group commit、BLOB record等),log writer會(huì)將I/O按lsn切片并且并發(fā)的分發(fā)I/O請(qǐng)求至不同split。通過這種方式,可以將大延時(shí)的log I/O任務(wù)拆分,并利用分布式存儲(chǔ)高分布寫特性來減少整體I/O時(shí)間。 2. 快速恢復(fù) 為了實(shí)現(xiàn)快速恢復(fù),我們提出了兩個(gè)優(yōu)化:快速(啟動(dòng))驗(yàn)證和全并行恢復(fù)。
在InnoDB的原有恢復(fù)過程中,InnoDB首先在啟動(dòng)期間會(huì)打開所有文件讀取元信息(如文件名、表ID等)并驗(yàn)證正確性,然后通過ARIES風(fēng)格的恢復(fù)算法重做未checkpoint的數(shù)據(jù)。為了加速啟動(dòng),快速驗(yàn)證方法不會(huì)掃描所有文件,而是在數(shù)據(jù)庫的生命周期中記錄和集中必要的元信息,并在創(chuàng)建、修改文件時(shí)將必要的元信息集中記錄在一個(gè)superblock中,在啟動(dòng)時(shí)僅掃描元數(shù)據(jù)塊文件。因此,減少了啟動(dòng)掃描過程中的遠(yuǎn)程I/O訪問開銷。其次,依賴于Redo日志分片,我們將log file按page拆分成多個(gè)文件,在恢復(fù)階段(可以進(jìn)一步劃分為parse、redo、undo三個(gè)階段),可以天然的支持并發(fā)parse和redo(undo階段在后臺(tái)進(jìn)行),通過并發(fā)任務(wù)充分調(diào)動(dòng)CPU和I/O資源加速恢復(fù)。
3. 預(yù)讀取
在云存儲(chǔ)環(huán)境下,讀I/O延時(shí)大大增加,當(dāng)用戶任務(wù)訪問數(shù)據(jù)發(fā)生cache miss的情況下,而有效的預(yù)讀取能夠充分利用聚合讀帶寬來減少讀任務(wù)延時(shí)。InnoDB中有線性預(yù)讀和非線性預(yù)讀兩種原生的物理預(yù)讀方法,我們進(jìn)一步引入了邏輯預(yù)讀策略(由于無序的插入和更新,索引在物理上不一定是順序的)。例如對(duì)于主索引掃描,當(dāng)任務(wù)線程從起始鍵順序掃描索引超過一定閾值時(shí),邏輯預(yù)讀會(huì)在主索引上按邏輯順序觸發(fā)異步預(yù)讀,提前讀取一定量的順序頁。又如對(duì)于具有二級(jí)索引和非索引列回表操作的掃描,在對(duì)二級(jí)索引進(jìn)行掃描同時(shí)批量收集相關(guān)命中的主鍵,積累一定批數(shù)據(jù)后觸發(fā)異步任務(wù)預(yù)讀對(duì)應(yīng)主索引數(shù)據(jù)(此時(shí)剩余的二級(jí)索引掃描可能仍在進(jìn)行中)。
4. 同步(鎖)優(yōu)化
相關(guān)背景可以先查閱《InnoDB btree latch 優(yōu)化歷程》[1]這篇文章。
無鎖刷臟:原生InnoDB在刷臟時(shí)需要持有當(dāng)前page的sx鎖,導(dǎo)致I/O期間當(dāng)前page的寫入被完全阻塞。而在云存儲(chǔ)上I/O延遲更高,阻塞時(shí)間更久。我們采用shadow page的方式,首先對(duì)當(dāng)前page構(gòu)建內(nèi)存副本,構(gòu)建好內(nèi)存副本后原有page的sx鎖被釋放,然后用這個(gè)shadow page內(nèi)容去做刷臟及相關(guān)刷寫信息更新。
SMO加鎖優(yōu)化:在InnoDB 里面, 依然有一個(gè)全局的index latch, 由于全局的index latch 存在會(huì)導(dǎo)致同一時(shí)刻在Btree 中只有一個(gè)SMO 能夠發(fā)生, index latch 依然會(huì)成為全局的瓶頸點(diǎn)。上述index latch不僅是計(jì)算瓶頸,而從另一方面考慮,鎖同步期間index上其他可能I/O操作無法并行,存儲(chǔ)帶寬利用率較低。相關(guān)實(shí)現(xiàn)可以參考文章《路在腳下, 從BTree 到Polar Index》[2]。
5. 多I/O任務(wù)隊(duì)列適配
針對(duì)云存儲(chǔ)具有I/O隔離性低的挑戰(zhàn),同時(shí)為了避免云存儲(chǔ)無法識(shí)別DB層存儲(chǔ)內(nèi)核的I/O語義,而造成優(yōu)先級(jí)低的I/O請(qǐng)求(如page刷臟、低優(yōu)先級(jí)預(yù)讀)影響關(guān)鍵I/O路徑的性能,在數(shù)據(jù)庫內(nèi)核中提供合理的I/O調(diào)度模型是很重要的。在 PolarDB 中,我們?cè)跀?shù)據(jù)庫內(nèi)核層為不同類型的I/O請(qǐng)求進(jìn)行調(diào)度,實(shí)現(xiàn)根據(jù)當(dāng)前I/O壓力實(shí)現(xiàn)數(shù)據(jù)庫最優(yōu)的性能,每個(gè)I/O請(qǐng)求都具有 DB 層的語義標(biāo)簽,如 WAL 讀/寫,Page 讀/寫。
我們?yōu)閿?shù)據(jù)庫的異步I/O請(qǐng)求建立了多個(gè)支持并發(fā)寫入的生產(chǎn)者 / 消費(fèi)者隊(duì)列,并且其存在三種不同特性的隊(duì)列,分別為 Private 隊(duì)列,Priority 隊(duì)列,以及 General 隊(duì)列,不同隊(duì)列的數(shù)量是根據(jù)當(dāng)前云存儲(chǔ)的I/O能力決定的。
正常情況下,WAL 的寫入只通過其 Private 隊(duì)列,當(dāng)寫入量增大時(shí),其I/O請(qǐng)求也會(huì)轉(zhuǎn)發(fā)至 Priority 隊(duì)列,此時(shí) Priority 隊(duì)列會(huì)優(yōu)先執(zhí)行 WAL 的寫入,并且后續(xù)Page寫入的I/O不會(huì)進(jìn)入 Priority 隊(duì)列。基于這種I/O模型,我們保證了一定部分的I/O資源時(shí)預(yù)留給WAL寫入,保證事務(wù)提交的寫入性能,充分利用云存儲(chǔ)的高聚合帶寬。此外,I/O任務(wù)隊(duì)列的長度和數(shù)目也進(jìn)行了拓展以一步匹配云存儲(chǔ)高吞吐、大帶寬但時(shí)延較高且波動(dòng)大的特性。
6. 格式化I/O請(qǐng)求
云存儲(chǔ)和本地存儲(chǔ)在I/O格式上具有顯著的不同,例如 Block 大小,I/O請(qǐng)求的發(fā)起方式。在大多數(shù)分布式的云存儲(chǔ)中,在實(shí)現(xiàn)多個(gè)計(jì)算節(jié)點(diǎn)的共享時(shí),為了避免維護(hù)計(jì)算節(jié)點(diǎn) cache 一致性的問題,不存在 page cache,此時(shí)采用原先本地存儲(chǔ)的I/O格式在云上會(huì)造成例如 read-on-write 和邏輯與物理位置映射的問題,造成性能下降。在 PolarDB中,我們?yōu)閃AL I/O和 Page I/O匹配了適應(yīng)云存儲(chǔ)的請(qǐng)求I/O格式以盡可能降低單個(gè)I/O的延時(shí)。
WAL I/O對(duì)齊:文件是通過固定大小的 block 進(jìn)行讀寫的。云存儲(chǔ)具有更大的 block size (4-128 KB),傳統(tǒng)的 log 對(duì)齊策略不適合云存儲(chǔ)上的 stripe boundary。我們?cè)?log 數(shù)據(jù)進(jìn)行提交的時(shí)候,將I/O請(qǐng)求的長度和偏移與云存儲(chǔ)的 block size進(jìn)行對(duì)齊。
Data I/O對(duì)齊:例如當(dāng)前存在兩種類型的數(shù)據(jù)頁:常規(guī)頁和壓縮頁,常規(guī)頁為16 KB,可以很容易與云存儲(chǔ)的 Block size 進(jìn)行對(duì)齊,但是壓縮頁會(huì)造成后續(xù)大量的不對(duì)齊I/O。以PolarDB 中對(duì)于壓縮頁的對(duì)齊為例。首先,我們讀取時(shí)保證以最小單位(如PolarFS的4 KB)讀取。而在寫入時(shí),對(duì)于所有小于最小訪問單元的壓縮頁數(shù)據(jù),我們會(huì)拓展到最小單位再進(jìn)行寫入,以保證存儲(chǔ)上的頁數(shù)據(jù)都是最小單位對(duì)齊的。
去除 Data I/O合并:在本地?cái)?shù)據(jù)庫中,數(shù)據(jù)頁的I/O會(huì)被合并來形成大的I/O實(shí)現(xiàn)連續(xù)地順序?qū)懭搿T谠拼鎯?chǔ)中,并發(fā)地向不同存儲(chǔ)節(jié)點(diǎn)寫入具有更高的性能,因此在云存儲(chǔ)的數(shù)據(jù)庫上,可以無需數(shù)據(jù)頁的I/O合并操作。
受篇幅所限,我們?cè)诒疚闹兄缓?jiǎn)單介紹所提優(yōu)化方法的大致實(shí)現(xiàn)邏輯,具體實(shí)現(xiàn)細(xì)節(jié)請(qǐng)讀者查閱論文及相關(guān)文章。
為了驗(yàn)證我們的優(yōu)化效果, 我們對(duì)比了為針對(duì)云存儲(chǔ)優(yōu)化的MySQL 分別運(yùn)行在PolarStore 和 Local Disk, 以及我們優(yōu)化以后的PolarDB, 從下圖可以看到PolarDB 在CPU-bound, IO-bound sysbench, TPCC 等各個(gè)場(chǎng)景下都表現(xiàn)除了明顯的性能優(yōu)勢(shì)。
同時(shí), 為了證明我們的優(yōu)化效果不僅僅對(duì)于我們自己的云存儲(chǔ)PolarStore 有收益, 對(duì)于所有的云存儲(chǔ)應(yīng)該都有收益, 因此我們將針對(duì)云存儲(chǔ)優(yōu)化的PolarDB 運(yùn)行在 StorageX, ESSD 等其他云存儲(chǔ)上, 我們發(fā)現(xiàn)均能獲得非常好的性能提升, 從而說明我們的優(yōu)化對(duì)于大部分云存儲(chǔ)都是有非常大的收益
實(shí)踐案例:RocksDB
我們還將CloudJump的分析框架和部分優(yōu)化方法拓展到基于云存儲(chǔ)的RocksDB上,同樣獲得了預(yù)計(jì)的性能收益。
1. Log I/O任務(wù)并行打散
RocksDB同樣使用集中WAL來保證進(jìn)程崩潰的一致性,集中日志收集多個(gè)column family的日志記錄并持久化至單個(gè)日志文件。考慮到LSM-Tree只需要恢復(fù)尾部append-only的數(shù)據(jù)塊,我們采用在上一個(gè)案例中提到的log I/O并行打散的方法在log writer中切分批日志并且并行分發(fā)到不同文件分片中。
2. 數(shù)據(jù)訪問加速
在RocksDB中有許多加速數(shù)據(jù)訪問的技術(shù),主要有prefetching, filtering 和compression機(jī)制。考慮到云存儲(chǔ)的特性,這些技術(shù)(經(jīng)過適當(dāng)改造)在云存儲(chǔ)環(huán)境中更有價(jià)值。經(jīng)過分析和實(shí)驗(yàn),我們提出了以下建議:1)預(yù)讀機(jī)制能加速部分查詢和compaction操作,建議compaction操作開啟預(yù)讀并設(shè)定合理的預(yù)讀I/O任務(wù)優(yōu)先級(jí),并將單個(gè)預(yù)讀操作的大小對(duì)齊存儲(chǔ)粒度,對(duì)于查詢操作預(yù)讀應(yīng)由用戶場(chǎng)景確定;2)在云存儲(chǔ)上建議開啟bloom filters,并且將filter的meta和常規(guī)數(shù)據(jù)分離,將filter信息并集中管理;3)采用塊壓縮來減小數(shù)據(jù)訪問的整體用時(shí),如下表展示了數(shù)據(jù)量和PolarFS訪問延時(shí),表中存儲(chǔ)基于RDMA,在延遲更高的存儲(chǔ)環(huán)境中,壓縮收益更高,引入壓縮后數(shù)據(jù)訪問的整體延時(shí)(特別是讀延時(shí))下降。
3. 多I/O任務(wù)隊(duì)列及適配
在多核硬件環(huán)境中,我們引入了一個(gè)多隊(duì)列I/O模型并在RocksDB中拆分I/O任務(wù)和工作任務(wù)(例如壓縮作業(yè)和刷新作業(yè))。這是因?yàn)槲覀兺ㄟ^調(diào)整I/O線程的數(shù)量來控制較好吞吐和延遲關(guān)系。由于將I/O任務(wù)與后臺(tái)刷寫作業(yè)分離,因此無需進(jìn)一步增加刷寫線程的數(shù)量,刷寫線程只會(huì)對(duì)齊I/O請(qǐng)求并進(jìn)行調(diào)度分發(fā)。RocksDB本身提供了基于線程角色的優(yōu)先級(jí)調(diào)度方案,而我們的調(diào)度方法這里是基于I/O標(biāo)簽。
我們根據(jù)云存儲(chǔ)調(diào)整I/O請(qǐng)求和數(shù)據(jù)組織(例如block和SST)的大小,并進(jìn)行更精確的控制,以使SST文件過濾器的塊大小也正確對(duì)齊。以PolarFS為例,存儲(chǔ)的最小請(qǐng)求大小為4 KB(表示最小的處理單元),理想的請(qǐng)求大小為16 KB的倍數(shù)(不造成read-on-write),元數(shù)據(jù)存儲(chǔ)粒度為4 MB。SST大小和塊大小分別嚴(yán)格對(duì)齊存儲(chǔ)粒度和理想請(qǐng)求大小的倍數(shù)。原生RocksDB也有對(duì)齊策略,我們?cè)诖诵枰M(jìn)行存儲(chǔ)參數(shù)適配并且對(duì)壓縮數(shù)據(jù)塊也進(jìn)行對(duì)齊。
我們不會(huì)向多隊(duì)列I/O模型傳遞小于最小請(qǐng)求大小的I/O請(qǐng)求,而是對(duì)齊最小I/O大小,并將未對(duì)齊的后綴緩存在內(nèi)存中以供后續(xù)對(duì)齊使用。其次,我們不會(huì)下發(fā)單個(gè)大于存儲(chǔ)粒度的I/O請(qǐng)求,而是通過多隊(duì)列I/O模型執(zhí)行并行任務(wù)(例如一個(gè)6 MB的I/O會(huì)分散成4 MB加1 MB的兩個(gè)任務(wù))。這不僅可以將數(shù)據(jù)盡可能分散在不同的存儲(chǔ)節(jié)點(diǎn)上,還可以最大限度地提高并行性以充分利用帶寬。
4. I/O對(duì)齊
在所有日志和數(shù)據(jù)I/O請(qǐng)求排入隊(duì)列前,對(duì)其的大小和起始o(jì)ffset進(jìn)行對(duì)齊。對(duì)于WAL寫入路徑,類似于PolarDB的log I/O對(duì)齊。對(duì)于數(shù)據(jù)寫入路徑,在采用數(shù)據(jù)壓縮時(shí),LSM樹結(jié)構(gòu)可能會(huì)有大量未對(duì)齊的數(shù)據(jù)塊。例如要刷寫從1 KB開始的2 KB日志數(shù)據(jù)時(shí),它將從內(nèi)存緩存的數(shù)據(jù)中填充前1 KB(對(duì)于append-only結(jié)構(gòu)通過保存尾部數(shù)據(jù)緩存實(shí)現(xiàn),這是與update-in-place結(jié)構(gòu)直接拓展原生頁至最小單位的不同之處),并在3-4 KB中附加零,然后從0 KB起始發(fā)送一個(gè)4 KB的I/O。
總結(jié)
在這項(xiàng)論文工作中,我們分析了云存儲(chǔ)的性能特征,將它們與本地SSD存儲(chǔ)進(jìn)行了比較,總結(jié)了它們對(duì)B-tree和LSM-tree類數(shù)據(jù)庫存儲(chǔ)引擎設(shè)計(jì)的影響,并推導(dǎo)出了一個(gè)框架CloudJump來指導(dǎo)本地存儲(chǔ)引擎遷移到云存儲(chǔ)的適配和優(yōu)化。并通過PolarDB, RocksDB 兩個(gè)具體Case 展示優(yōu)化帶來的收益。
審核編輯 :李倩
-
數(shù)據(jù)庫
+關(guān)注
關(guān)注
7文章
3763瀏覽量
64274 -
云存儲(chǔ)
+關(guān)注
關(guān)注
7文章
732瀏覽量
45991
原文標(biāo)題:過去5年,PolarDB云原生數(shù)據(jù)庫是如何進(jìn)行性能優(yōu)化的?
文章出處:【微信號(hào):inf_storage,微信公眾號(hào):數(shù)據(jù)庫和存儲(chǔ)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論