国产数据库存储引擎X-Engine的科研之路
X-Engine是阿里云RDS MySQL 的存儲引擎之一,基于Log-structured Merge Tree (LSM-tree),較基于 B-tree 一族的其它存儲引擎而言年輕很多,所以在實踐中遇到問題也更多,對研究的需求也更大。
LSM-tree是1996 年美國計算機科學(xué)家 Patrick O'Neil 等人提出的一種數(shù)據(jù)結(jié)構(gòu),和 B-tree 相比,它擁有更快的寫入性能和層次化的存儲結(jié)構(gòu),能夠同時利用好 DRAM 內(nèi)存的高性能和持久化存儲的高容量。尤其是 LSM-tree 的分層存儲結(jié)構(gòu),可以天然地利用數(shù)據(jù)局部性將熱數(shù)據(jù)和冷數(shù)據(jù)區(qū)別開,方便壓縮算法有的放矢,有機會在降低整體成本的情況下,實現(xiàn)同樣優(yōu)秀的性能。但是,與幾乎所有的計算機數(shù)據(jù)結(jié)構(gòu)和系統(tǒng)設(shè)計一樣,有得必有失。LSM-tree 難以避免的在讀性能、I/O 寫放大和空間效率上面對挑戰(zhàn)。
01、寫路徑上的羅生門
首先,LSM-tree 使用了能夠支持快速寫入的 copy-on-write (CoW)方式來存儲新增數(shù)據(jù)。顧名思義,假如要使用 CoW 來更新一條記錄,不需要定位存儲引擎中該條記錄的地址并將它讀取出來,只需要直接將我要更新的內(nèi)容(例如,key = 100, value = value +100)寫入內(nèi)存和日志(直接寫磁盤)即可。
這樣整個寫入操作就像記日記一樣,我只需要在日記本的最后一個空白頁上新增內(nèi)容即可,至于這個日記本已經(jīng)寫了多少頁,或者以前的某頁里面寫了什么,我都不需要管。
所以,LSM-tree 的寫入操作代價很低,而且與數(shù)據(jù)庫中的已存數(shù)據(jù)關(guān)系不大,無論這個數(shù)據(jù)庫已經(jīng)存了多少數(shù)據(jù),運行了多少天,寫一條記錄在理想狀態(tài)下都可以被執(zhí)行得非常快。同理,如果我需要刪除一條記錄,我只需要新插入一條反記錄即可。
那么問題來了,讀記錄的時候我難免要去檢查一下這條記錄的原始數(shù)據(jù)在哪里,是什么,它有沒有更新.....然后把所有這樣的碎片合并在一起,我才知道這條記錄到底是什么(例如,key == 100, value = 0 + 100 + 200 - 300 = 0)。這個過程顯然是比較費時的,不如我直接根據(jù)索引讀一條記錄來得快。
而且,絕大部分的數(shù)據(jù)庫是需要服務(wù)大量查詢的,幫用戶查數(shù)據(jù)才是數(shù)據(jù)庫的主要工作,用戶存數(shù)據(jù)就是為了有朝一日要讀取它,而 LSM-tree 卻在寫性能上大做文章,涉嫌揀了芝麻,丟了西瓜,老老實實優(yōu)化讀操作不香嗎?為什么非要玩高難度呢?
我們也想輕松啊……可是,各位敬愛的淘寶剁手黨、天貓爸爸會員、釘釘校友們,你們知道你們給數(shù)據(jù)庫帶來了多大的寫入流量嗎?那可是摧枯拉朽,天崩地裂,滄海桑田!比如雙 11 零點那一秒,阿里云數(shù)據(jù)庫要面對 100 多倍的寫入流量海嘯(詳見我們的 SIGMOD'19 論文),臣妾要是不加班加點,那根本是做不到的……
問題還不止于此。數(shù)據(jù)庫所有數(shù)據(jù)最終都要落盤實現(xiàn)持久化。內(nèi)存新寫入的記錄就需要時不時地刷入到磁盤。刷盤時,反正都要做 I/O 寫,我們可以把新數(shù)據(jù)與舊數(shù)據(jù)直接合并到位,這樣就減少了碎片的數(shù)量,同時保持了磁盤上數(shù)據(jù)的有序,方便讀取。
可是,當(dāng)盤上數(shù)據(jù)越來越多時,這樣的合并會越來越昂貴,在不能按字節(jié)尋址的存儲器件上(注意這個限定詞,NVM 正在熱身,等待上場),我們必須讀入所有需要參與合并的頁,完成合并,并將這些頁寫回。
這些頁里面的很多數(shù)據(jù)其實是躺槍的,純粹是被鄰居帶下水。隨著數(shù)據(jù)增多,我們要讀的頁也會越來越多,整體代價也就越來越大。我們稱這個問題為『寫放大』。除了對性能的影響外,寫放大也會給 SSD 盤本身的 endurance 帶來壓力,如果寫放大過高,會提高云廠商的服務(wù)成本。而云計算的最最最精華的精髓,就是『低成本、干大事』。
為了解決寫放大問題,LSM-tree 在磁盤上已經(jīng)進化出了一種分層存儲結(jié)構(gòu)。新數(shù)據(jù)先寫在『零層』,零層我們給他一個非常小的容量,只存剛剛刷下來的數(shù)據(jù)。因為數(shù)據(jù)局部性的緣故,零層的數(shù)據(jù)有很大概率會被訪問到,還是熱乎的,那么通過限制容量,無論怎么訪問,點讀也好,掃描也罷,它總共就這么大點地方,不會慢到哪里去。
當(dāng)零層容量飽和時,我們將它的內(nèi)容與『壹層』中的數(shù)據(jù)合并。壹層比零層更大,比如大10倍。那么理論上,這次合并中最多需要讀取和寫回壹層大概十分之一左右的數(shù)據(jù),不會更大了。寫放大,也就被限制住了。當(dāng)『壹層』也滿了的時候,我們使用同樣的方法繼續(xù)往下刷,刷出『貳層』、『叁層』等等等等,以此類推。
每一層的容量,比上一層大 10 倍,整個存儲中每層的大小呈指數(shù)級增長。有了層次化的存儲,配合這樣的合并操作,寫放大就被控制住了。對于數(shù)據(jù)庫系統(tǒng)中的很多問題,我們往往不太可能把它徹底解決掉,而是將其控制在一定的可接受的界限內(nèi)即可。成年人的世界就是這么殘酷,沒有歲月靜好,沒有美麗童話,只有負(fù)重前行。
分層控制住了寫放大,但是新的問題又來了,合并算法本身是一種數(shù)據(jù)密集型算法,它需要讀取多路數(shù)據(jù),然后進行相對簡單的合并計算,再將合并結(jié)果寫回去,整個過程本質(zhì)上讀寫很多,對存儲帶寬的消耗非常大,也會給 CPU 流水線帶來很多的 I/O 等待、內(nèi)存等待等氣泡,降低 CPU 流水線的執(zhí)行效率,拖慢整個系統(tǒng)。
單次跑一下還好,如果頻繁跑,會對系統(tǒng)性能有很大影響。而且它即不處理查詢,也不處理新增數(shù)據(jù),完全是個看起來不必要的背景操作。這種合并操作,我們叫他『Compaction』。在 LSM-tree 引擎中,compaction 不僅肩負(fù)著層與層之間合并數(shù)據(jù)的任務(wù),還肩負(fù)著為了刪除操作將反記錄與真實記錄合并從而實現(xiàn)刪除的任務(wù)等等,是一種多功能的重要操作,是 LSM-tree 中的『消防隊員』兼『警察叔叔』兼『快遞小哥』兼『醫(yī)生』兼……
到此為止,LSM-tree 在寫路徑上的各個部分都已經(jīng)悉數(shù)登場了,而這片江湖上的恩恩怨怨才剛剛開始。為了服務(wù)好寫流量越來越多的 workload,LSM-tree 為了加速寫可謂是不遺余力,基本上所有的設(shè)計都向?qū)懧窂降男阅茏隽藘A斜,讓寫入看上去十分美好,實際上也開了一扇羅生門,門后慘象環(huán)生。具體怎么慘,下文詳述。
02、讀路徑上帶著鐐銬的舞蹈
LSM-tree讀路徑,從出生就帶著鐐銬。因為 CoW 的使用,讀一條記錄實際上需要把這條記錄所有的增量碎片都找到。橫跨內(nèi)存和磁盤兩種介質(zhì)和有層次化的存儲,讓碎片可能藏在各種犄角旮旯里面。更慘的是,如果是讀一個范圍內(nèi)的記錄,俗稱 range scan,因為 LSM-tree 的每一層的 key range 是交疊的,那么一個 range 內(nèi)的數(shù)據(jù)就很有可能會落在所有的層次上,為了把他們都找到,我們就需要每層都去讀,這個工作量也不小。
為了解決這個問題,目前的 LSM-tree 引擎把各種經(jīng)典技術(shù)都用上了:各種索引、各種 cache。但是為了提高索引和 cache 的效率,讓他們一直發(fā)揮比較好的作用,難度不小。以 cache 為例,X-Engine 中使用了兩種經(jīng)典的 cache,一種是 row cache,緩存記錄級別的熱數(shù)據(jù),一種是 block cache,緩存數(shù)據(jù)塊級別的熱數(shù)據(jù)。
Row cache 可以加速點查詢,block cache 可以加速 range scan,一切看上去都是很完美的芭蕾舞。然而,當(dāng) compaction 被大王叫來巡山的時候,危險就發(fā)生了。因為 compaction 會重新組織數(shù)據(jù)塊里面的內(nèi)容,干掉一些老的 block,生成一些新的 block,傳統(tǒng)的 cache 替換策略對老的 block 做的訪問統(tǒng)計會失效,而新的 block 它不認(rèn)識,沒統(tǒng)計信息。此外,compaction 還會移動數(shù)據(jù)。這兩點加起來,只要 compaction 巡了一次山,cache 里面緩存的記錄就有很大可能出現(xiàn)大面積失效,導(dǎo)致原本可以命中 cache 的查詢,不得不去訪問磁盤,造成嚴(yán)重的延遲尖刺。
熱數(shù)據(jù)的麻煩還不僅僅來源于 cache,因為熱數(shù)據(jù)經(jīng)常會被大量更新,而 X-Engine 為了實現(xiàn)一個 OLTP 數(shù)據(jù)庫的 ACID 特性,使用了 MVCC 的并發(fā)控制方法,會為一條熱數(shù)據(jù)上存上非常多的版本,這樣的設(shè)計實際上造成了一條邏輯記錄可能會有特別多的物理分身。這個現(xiàn)實無論是對承接新寫入數(shù)據(jù)的 memtable(經(jīng)常被實現(xiàn)為跳躍鏈表),還是索引,還是 compaction,都是一個很煩人的刺頭,硬生生地通過放大數(shù)據(jù)的體量來造成各種各樣的問題。
除了上述由于 LSM-tree 或者數(shù)據(jù)庫的機制帶來的問題以外,這些涉及到的數(shù)據(jù)結(jié)構(gòu)本身的設(shè)計和實現(xiàn)也有很大的挑戰(zhàn),比如 cache 的分桶策略、鎖的管理、跳躍鏈表和索引的查詢效率、數(shù)據(jù)結(jié)構(gòu)針對多核處理器的并行優(yōu)化等等等等,都是風(fēng)景秀麗的坑、大坑、天坑。坑夠大,填坑才有樂趣。除了讀路徑的問題,LSM-tree 上還有刪除效率的問題、空間效率的問題等等,此處不再詳述,詳見相關(guān)論文。
03、學(xué)術(shù)成果與產(chǎn)學(xué)研互動
X-Engine 團隊聯(lián)合其他合作伙伴,為了解決上述問題做出了很多優(yōu)化,申請了大量專利,其中的很多技術(shù)也作為學(xué)術(shù)成果在數(shù)據(jù)庫和存儲領(lǐng)域的頂會內(nèi)完成了發(fā)表。
?
X-Engine團隊合作伙伴們
2019年,我們在 ACM SIGMOD 的 industrial track 中發(fā)表了一篇介紹 X-Engine 來龍去脈的論文X-Engine: An Optimized Storage Engine for Large-scale E-commerce Transaction Processing。在這篇文章中,我們介紹了 X-Engine 這種面向?qū)懭雰?yōu)化的存儲引擎為什么在工業(yè)界人氣飆升,為什么阿里巴巴的電商場景需要這樣的引擎,主要原因就是每次電商促銷所帶來的富含新增數(shù)據(jù)的高流量海嘯。
面對這樣的挑戰(zhàn),我們首先將問題拆解為了具體的數(shù)據(jù)庫技術(shù)問題,如處理高流量所需的并行寫入流水線、數(shù)據(jù)量海嘯快速填滿內(nèi)存對刷盤帶來的壓力、促銷導(dǎo)致的數(shù)據(jù)熱點范圍頻繁變化帶來的讀性能的挑戰(zhàn)等等。為了解決這些實際的技術(shù)問題,我們介紹了 X-Engine 做了怎么樣的技術(shù)選型,采取了哪些優(yōu)化,以及每項優(yōu)化所帶來的實際效果。這篇論文是中國大陸公司首次在 SIGMOD 上發(fā)表數(shù)據(jù)庫內(nèi)核上的工作。詳情請見論文(在 ACM DL 中可免費下載)。
2020年,與 AIS 軟硬件結(jié)合開發(fā)團隊合作,我們在存儲領(lǐng)域的頂會 USENIX FAST 2020 上發(fā)表了利用 FPGA 異構(gòu)計算技術(shù)來加速 X-Engine 中很多問題的罪魁禍?zhǔn)住?compaction 的工作FPGA-Accelerated Compactions for LSM-based Key-Value Store。
在這項工作中,我們首先系統(tǒng)研究了 compaction 對 LSM-tree 存儲引擎在 CPU、內(nèi)存、磁盤等資源的消耗上有什么特征,分析了 compaction 的算法,發(fā)現(xiàn) compaction 算法在合并較短的記錄的時候竟然是受限于 CPU 的。
其原因一方面是因為 compaction 對計算的需求,另一方面也是因為這些年來磁盤帶寬有了顯著的增長。所以,我們提出將 compaction 算法 offload 到 FPGA 加速卡上,并在 FPGA 上設(shè)計和實現(xiàn)了一套高效的流水線,和 CPU host 實現(xiàn)了快速的交互,也實現(xiàn)了 compaction 算法的加速。這項工作所做的探索讓我們看到了計算型存儲技術(shù)的紅利。
近年來,隨著 SSD 的不斷發(fā)展和處理器的微小型化,市場上出現(xiàn)了類似 SmartSSD 這樣的計算型存儲設(shè)備,其核心優(yōu)勢是把較小的 ARM CPU 處理器或者 FPGA 芯片直接嵌入 SSD 內(nèi)部,讓部分計算任務(wù)不需要離開 SSD 就能完成,省去了 I/O 和 CPU 的開銷。因為 SSD 內(nèi)部的訪存帶寬比外部的 I/O 快幾十倍,計算型存儲特別適合處理類似 compaction、scan 等相對而言更加訪存密集的操作。
今年阿里云數(shù)據(jù)庫團隊在 FAST 上收獲了大豐收,投稿的 3 篇論文全部被錄用,而 FAST 是個比較小而專的會議,今年一共也僅有 23 篇論文。
?
FAST'20現(xiàn)場,X-Engine分享
除了上述已經(jīng)發(fā)表的成果,我們還探索了使用機器學(xué)習(xí)技術(shù)來預(yù)測 compaction 前后的數(shù)據(jù)訪問趨勢,以解決傳統(tǒng) cache 替換策略被干擾的問題;我們也探索了在 X-Engine 內(nèi)部應(yīng)用細(xì)粒度、自適應(yīng)的調(diào)度算法,來改善 compaction 的執(zhí)行時機,從而提高系統(tǒng)性能的穩(wěn)定性;我們也優(yōu)化了內(nèi)存分配策略、cache 結(jié)構(gòu)和訪問方式等等底層細(xì)節(jié),旨在從根本上顯著提高 X-Engine 的性能與穩(wěn)定性。目前,這些工作還在進一步的研發(fā)中。
X-Engine 自 2019 年進入數(shù)據(jù)庫界國際頂級學(xué)術(shù)圈以來,通過向?qū)W術(shù)界介紹阿里巴巴的應(yīng)用場景以及技術(shù)挑戰(zhàn),尤其是 X-Engine 引擎本身所面對的技術(shù)挑戰(zhàn),已經(jīng)吸引了很多專家學(xué)者的目光。我們所拋出的 LSM-tree 刪除性能差的問題,已經(jīng)吸引了來自波士頓大學(xué)和哈佛大學(xué)的研究者提出了新的優(yōu)化技術(shù),相應(yīng)學(xué)術(shù)成果將發(fā)表在最近的學(xué)術(shù)會議中。
在國內(nèi),X-Engine 團隊與阿里自家的達摩院數(shù)據(jù)庫存儲與實驗室、浙江大學(xué) AZFT 實驗室孫建伶教授、中科院計算所陳世敏教授等學(xué)者和研究人員長期合作,共同研究 LSM-tree 相關(guān)的技術(shù)問題,并且不斷產(chǎn)出優(yōu)質(zhì)的學(xué)術(shù)成果。通過學(xué)術(shù)合作,目前已經(jīng)發(fā)表了 FAST 一篇(FPGA 加速),VLDB 一篇(NVM 索引)。除此以外,我們追求將學(xué)術(shù)研究探索出來的新技術(shù)真正落地在 X-Engine 系統(tǒng)內(nèi)核中,為提高 X-Engine 產(chǎn)品力貢獻力量。
04、未來研究方向
未來,X-Engine 團隊會針對生產(chǎn)實踐中遇到的各項技術(shù)難題展開公關(guān),也會緊跟新的技術(shù)趨勢,探索新型硬件(如 NVM,FPGA 等)在 X-Engine 上的應(yīng)用。
首先,分布式是數(shù)據(jù)庫產(chǎn)品的潮流。在未來,用戶不需要再操心數(shù)據(jù)庫擴展性上的麻煩,而是買一份分布式數(shù)據(jù)庫 PolarDB-X,把所有任務(wù)都交給它后就可以高枕無憂了。我們當(dāng)前正致力于 PolarDB-X 的研發(fā),旨在為用戶提供一款高性能、低成本、伸縮性好的分布式數(shù)據(jù)庫產(chǎn)品,將阿里多年來積累的數(shù)據(jù)庫技術(shù)紅利分享給阿里云上的客戶們。在這個方向上,我們會著力于分布式SQL引擎、私有協(xié)議、分布式事務(wù)處理、分布式負(fù)載均衡、故障恢復(fù)等重要技術(shù)問題。
其次,我們認(rèn)為,X-Engine 的內(nèi)存部分可以看成一個內(nèi)存數(shù)據(jù)庫,應(yīng)該與處理器、DRAM 內(nèi)存等硬件深度融合,突破性能瓶頸。具體的研究方向包括 cache-conscious 的高性能內(nèi)存索引、利用 SIMD 技術(shù)(Single Instruction Multiple Data)來加速內(nèi)存數(shù)據(jù)結(jié)構(gòu)訪問、降低內(nèi)存鎖開銷等。
最后,對于時下的熱點人工智能,我們也不會放過。目前,我們已經(jīng)探索了機器學(xué)習(xí)技術(shù)在 cache 替換上的應(yīng)用,未來我們會探索智能調(diào)參、智能 compaction 調(diào)度、智能索引等 AI for DB 技術(shù)。我們希望利用人工智能技術(shù),將復(fù)雜的數(shù)據(jù)庫運維轉(zhuǎn)換為十分傻瓜的簡單操作,降低用戶使用和維護數(shù)據(jù)庫的難度,同時改善數(shù)據(jù)庫的性能。
作為一款重量級的數(shù)據(jù)庫基礎(chǔ)軟件,X-Engine 雖然看上去只是負(fù)責(zé)數(shù)據(jù)增、刪、改、查這樣平淡無奇的操作,但正是因為這些操作足夠基礎(chǔ),X-Engine 才會被集成于 MySQL 內(nèi)核和分布式數(shù)據(jù)庫 PolarDB-X 中,我們的每一項優(yōu)化也獲得了更大的影響力,直接決定著所有上層應(yīng)用的安全、穩(wěn)定和性能。歡迎有志于從事國產(chǎn)自研數(shù)據(jù)庫研發(fā)的同學(xué)加入我們。
阿里云分布式數(shù)據(jù)庫PolarDB-X團隊招人啦!
面向人群:2021 屆海內(nèi)外院校應(yīng)屆畢業(yè)生(畢業(yè)時間為 2020 年 11 月 - 2021 年 10 月)
應(yīng)聘方式:請將簡歷投遞至dehao.wdh@alibaba-inc.com
原文鏈接
本文為云棲社區(qū)原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。
總結(jié)
以上是生活随笔為你收集整理的国产数据库存储引擎X-Engine的科研之路的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 云原生存储详解:容器存储与K8s存储卷
- 下一篇: 十年磨一剑,阿里云RDS MySQL和A