王聰聰, 胡卉芪
(華東師范大學(xué) 數(shù)據(jù)科學(xué)與工程學(xué)院, 上海 200062)
在過去的十年中, 云計(jì)算技術(shù)經(jīng)歷了飛速的發(fā)展. 在這一趨勢(shì)的影響下, 數(shù)據(jù)庫市場(chǎng)的重心已經(jīng)逐漸從企業(yè)內(nèi)部向云端遷移. 眾多商業(yè)云數(shù)據(jù)庫, 如亞馬遜的Aurora[1]、阿里巴巴的PolarDB[2]等, 已被廣泛應(yīng)用. 云數(shù)據(jù)庫是一種基于云計(jì)算平臺(tái)的數(shù)據(jù)庫系統(tǒng), 以服務(wù)形式提供給用戶. 該系統(tǒng)利用云計(jì)算中的資源池技術(shù), 將數(shù)據(jù)庫的存儲(chǔ)、計(jì)算和網(wǎng)絡(luò)資源進(jìn)行統(tǒng)一管理和調(diào)度, 以提供靈活、可靠、易用且可擴(kuò)展的數(shù)據(jù)庫服務(wù).
云原生數(shù)據(jù)庫的崛起改變了人們對(duì)于數(shù)據(jù)庫設(shè)計(jì)前景和權(quán)衡的理解. 在分布式系統(tǒng)設(shè)計(jì)中, 對(duì)于無共享架構(gòu)和共享存儲(chǔ)架構(gòu)的選擇, 存在著深入的爭論. 許多早期的在線事務(wù)處理 (on-line transaction processing, OLTP) 系統(tǒng), 例如Spanner[3]和CosmosDB[4], 都積極推動(dòng)使用無共享架構(gòu)以擴(kuò)展OLTP 系統(tǒng), 從而超越單一系統(tǒng)的處理能力. 然而, 在云數(shù)據(jù)庫的發(fā)展背景下, 這種立場(chǎng)可能已經(jīng)不再那么明確. 云服務(wù)為數(shù)據(jù)庫帶來了全新的需求, 例如計(jì)算層和存儲(chǔ)層的彈性擴(kuò)展, 以及靈活適應(yīng)各種負(fù)載場(chǎng)景等. 在這些新需求的推動(dòng)下, 共享存儲(chǔ)架構(gòu)再次受到了重視.
許多云原生數(shù)據(jù)庫如Aurora[1]和Socrates[5], 都已經(jīng)采用了共享存儲(chǔ)架構(gòu). 在這一架構(gòu)中, 首先所有的寫入事務(wù)都在一個(gè)主節(jié)點(diǎn)上完成, 其次該主節(jié)點(diǎn)將其寫前日志 (write-ahead log) 發(fā)送到共享存儲(chǔ), 以供次級(jí)節(jié)點(diǎn)訪問. 存儲(chǔ)節(jié)點(diǎn)利用這些寫前日志在后臺(tái)重建數(shù)據(jù)頁, 而這些重建的數(shù)據(jù)頁可以被次級(jí)節(jié)點(diǎn)按需讀取, 從而以較低的開銷可在任何時(shí)候生成. 雖然這種設(shè)計(jì)提供了如熱故障切換和彈性負(fù)載均衡等重要功能, 但其仍然受到主節(jié)點(diǎn)處理能力的限制. 這種限制在OLTP 常見的寫入密集型負(fù)載場(chǎng)景下尤為明顯.
在共享存儲(chǔ)架構(gòu)中簡單地添加多個(gè)主節(jié)點(diǎn)并不能解決這一問題, 因?yàn)槿绻试S多個(gè)讀寫節(jié)點(diǎn)同時(shí)修改共享存儲(chǔ)層, 那么為了保證數(shù)據(jù)的一致性, 讀寫節(jié)點(diǎn)之間的競爭將使共享存儲(chǔ)層成為新的瓶頸.一個(gè)可能的解決方案是采用共享緩存架構(gòu), 即在共享存儲(chǔ)架構(gòu)中增加一層共享緩存, 從而讓多個(gè)讀寫節(jié)點(diǎn)可以在共享緩存中修改數(shù)據(jù)項(xiàng), ScaleStore[6]、Oracle RAC[7]和NAM-DB[8]都采用了這種設(shè)計(jì). 然而, 這種設(shè)計(jì)需要解決緩存一致性的問題, 主要有兩種方式: 一種是節(jié)點(diǎn)始終在共享存儲(chǔ)中進(jìn)行讀寫;另一種是節(jié)點(diǎn)間通過緩存一致性協(xié)議來保證數(shù)據(jù)的一致性. 雖然共享緩存架構(gòu)可以有效滿足云計(jì)算場(chǎng)景對(duì)內(nèi)存擴(kuò)展的需求, 但在提高數(shù)據(jù)庫事務(wù)的可擴(kuò)展性方面, 仍有許多待解決的問題, 例如時(shí)間戳的擴(kuò)展瓶頸及事務(wù)持久化速度的緩慢等.
時(shí)間戳用于在事務(wù)中提供快照, 然而在共享緩存數(shù)據(jù)庫中經(jīng)常使用的全局時(shí)間戳存在線程級(jí)別的擴(kuò)展性限制, NAM-DB[8]中采用的向量時(shí)間戳利用每個(gè)機(jī)器的時(shí)鐘解決了線程級(jí)別的擴(kuò)展性瓶頸,但仍然無法擴(kuò)展到多臺(tái)節(jié)點(diǎn)上. 此外在共享緩存數(shù)據(jù)庫中, 新的頁面會(huì)被快速地添加到節(jié)點(diǎn)的緩存中,因此共享緩存數(shù)據(jù)庫需要快速地驅(qū)逐冷頁到存儲(chǔ)層, 然而由于頁面需要在共享存儲(chǔ)層完成持久化, 整個(gè)傳輸過程依然較慢, 如何實(shí)現(xiàn)快速持久化是一個(gè)重要挑戰(zhàn).
針對(duì)上述問題, 本文在共享緩存架構(gòu)的基礎(chǔ)上, 結(jié)合新型硬件—持久化內(nèi)存, 實(shí)現(xiàn)了一個(gè)具有三層共享架構(gòu) (包括內(nèi)存層、持久化內(nèi)存層、存儲(chǔ)層) 的數(shù)據(jù)庫. 在此架構(gòu)的基礎(chǔ)上, 重新設(shè)計(jì)了事務(wù)的執(zhí)行流程, 并針對(duì)若干關(guān)鍵技術(shù)進(jìn)行優(yōu)化, 以進(jìn)一步提升數(shù)據(jù)庫事務(wù)執(zhí)行的性能. 本文的主要貢獻(xiàn)有以下兩點(diǎn).
(1) 提出了一種解耦事務(wù)執(zhí)行流程的共享架構(gòu). 通過利用持久化內(nèi)存技術(shù), 對(duì)共享緩存架構(gòu)進(jìn)行了重新設(shè)計(jì), 引入了共享持久化內(nèi)存層, 并對(duì)數(shù)據(jù)庫事務(wù)的執(zhí)行流程進(jìn)行了優(yōu)化. 本文利用持久化內(nèi)存層的重做日志回放功能來重新生成頁面, 從而消除了從共享緩存層驅(qū)逐臟頁到存儲(chǔ)層的過程. 這一設(shè)計(jì)有助于消除共享緩存的頁面驅(qū)逐過程, 并實(shí)現(xiàn)快速的持久化.
(2) 提出了分布式向量時(shí)間戳技術(shù). 為了解決在共享緩存架構(gòu)下, 事務(wù)時(shí)間戳可擴(kuò)展性的瓶頸問題, 本文利用RDMA (remote direct memory access)的原子更新能力, 設(shè)計(jì)了分布式向量時(shí)間戳技術(shù).這項(xiàng)技術(shù)將時(shí)間戳分布式地維護(hù)在各個(gè)節(jié)點(diǎn)上, 并提供了一個(gè)一致的時(shí)間戳快照, 從而在多節(jié)點(diǎn)環(huán)境下顯著提升了時(shí)間戳的可擴(kuò)展性.
本章首先回顧了分布式數(shù)據(jù)庫中的共享存儲(chǔ)架構(gòu)和無共享架構(gòu); 其次介紹了云數(shù)據(jù)庫中的共享緩存架構(gòu); 最后針對(duì)當(dāng)前共享緩存架構(gòu)的一些問題提出了本文的架構(gòu)設(shè)計(jì)—共享持久化內(nèi)存架構(gòu).
分布式數(shù)據(jù)庫的架構(gòu)可分為共享存儲(chǔ)架構(gòu)(圖1 (a)) 和無共享架構(gòu)(圖1 (b)) 兩種. 在共享存儲(chǔ)架構(gòu)中, 所有節(jié)點(diǎn)都可以訪問數(shù)據(jù)庫的存儲(chǔ)層; 然而, 在無共享架構(gòu)中, 每個(gè)節(jié)點(diǎn)都有其私有存儲(chǔ), 其他節(jié)點(diǎn)無法訪問.
圖1 分布式數(shù)據(jù)庫的4 種經(jīng)典架構(gòu)Fig. 1 Four classical architectures for distributed databases
許多分布式數(shù)據(jù)庫, 如IBM DB2[9]、AlloyDB[10], 采用了共享存儲(chǔ)架構(gòu). 這些數(shù)據(jù)庫允許多個(gè)節(jié)點(diǎn)訪問共享存儲(chǔ)的讀副本, 但通常只有一個(gè)讀寫節(jié)點(diǎn)執(zhí)行更新. 在讀密集型負(fù)載下, 這種單一更新節(jié)點(diǎn)的架構(gòu)能實(shí)現(xiàn)良好的擴(kuò)展性. 計(jì)算與存儲(chǔ)的分離架構(gòu)能滿足云計(jì)算場(chǎng)景下的快速故障切換和彈性需求, 同時(shí)系統(tǒng)的復(fù)雜度相對(duì)較低. 然而, 這種架構(gòu)在處理寫密集型負(fù)載時(shí)的擴(kuò)展性受到單一節(jié)點(diǎn)能力的限制.
在無共享架構(gòu)中, 數(shù)據(jù)庫被分為多個(gè)分區(qū), 每個(gè)分區(qū)僅由相應(yīng)的讀寫節(jié)點(diǎn)更新. 該架構(gòu)通過數(shù)據(jù)分區(qū)將數(shù)據(jù)分散在各個(gè)節(jié)點(diǎn)上, 各節(jié)點(diǎn)負(fù)責(zé)對(duì)其本地分區(qū)進(jìn)行讀寫操作. 現(xiàn)有的數(shù)據(jù)庫系統(tǒng)如MongoDB[11]及Cassandra[12]等, 主要依靠兩階段提交來確保分布式事務(wù)的原子性. 與共享存儲(chǔ)架構(gòu)的單一讀寫節(jié)點(diǎn)相比, 該架構(gòu)的可擴(kuò)展性更好, 其可以通過分區(qū)將工作分配到對(duì)應(yīng)的節(jié)點(diǎn)上. 與之相反,在處理帶有熱點(diǎn)的傾斜訪問時(shí), 由于對(duì)熱鍵的請(qǐng)求都集中在這些節(jié)點(diǎn)上, 被頻繁訪問的少數(shù)節(jié)點(diǎn)可能成為新的瓶頸. 從彈性擴(kuò)展的角度看, 由于增加新的節(jié)點(diǎn)可能需要對(duì)數(shù)據(jù)庫進(jìn)行重新分區(qū), 該架構(gòu)的彈性相對(duì)較有限.
在共享存儲(chǔ)架構(gòu)中, 允許多個(gè)讀寫節(jié)點(diǎn)同時(shí)對(duì)存儲(chǔ)層進(jìn)行更新的情況下, 主要問題在于存儲(chǔ)層可能會(huì)受到來自不同讀寫節(jié)點(diǎn)的大量請(qǐng)求, 這將成為一個(gè)瓶頸, 從而限制存儲(chǔ)層和計(jì)算層的可擴(kuò)展性.此外, 每次數(shù)據(jù)訪問都需要進(jìn)行網(wǎng)絡(luò)通信以訪問存儲(chǔ)層, 這會(huì)顯著增加訪問延遲. 針對(duì)這些問題, 圖1 (c)中的共享緩存架構(gòu)得以被提出. 在共享緩存架構(gòu)中, 頻繁訪問的數(shù)據(jù)項(xiàng)被存儲(chǔ)在共享緩存層, 從而顯著降低了訪問延遲. 同時(shí), 共享緩存層允許多個(gè)讀寫節(jié)點(diǎn)更新數(shù)據(jù), 并通過緩存一致性協(xié)議來保證數(shù)據(jù)的一致性. 雖然共享緩存架構(gòu)在處理傾斜訪問時(shí)的可擴(kuò)展性仍然有限, 但在云服務(wù)場(chǎng)景中, 它帶來了許多優(yōu)點(diǎn), 如良好的彈性 (新添加的計(jì)算節(jié)點(diǎn)的緩存可以在訪問過程中逐漸填充), 以及靈活性 (不依賴用戶分區(qū), 可以根據(jù)不同負(fù)載場(chǎng)景自適應(yīng)數(shù)據(jù)的分布).
然而, 在共享緩存架構(gòu)中, 仍然存在許多需要解決的問題, 尤其是在OLTP 云數(shù)據(jù)庫的事務(wù)處理場(chǎng)景中. 本文主要列舉了以下幾點(diǎn).
(1) 數(shù)據(jù)持久化速度慢. 首先, 因?yàn)楣蚕砭彺鎸又械捻撁媸且资缘? 因此數(shù)據(jù)庫可能需要將臟頁面或日志寫入到存儲(chǔ)層. 其次, 數(shù)據(jù)從共享緩存層到共享存儲(chǔ)層的傳輸速度較慢, 這降低了寫入速度.這引發(fā)了兩個(gè)問題: 一是在云場(chǎng)景中, 節(jié)點(diǎn)的本地緩存可能會(huì)很快被填滿, 如果不能快速驅(qū)逐冷頁面,將導(dǎo)致共享緩存的性能受限; 二是數(shù)據(jù)庫的事務(wù)處理流程通常需要先將持久化日志寫入到存儲(chǔ)層, 如果寫入速度慢, 那么可能重新出現(xiàn)事務(wù)的可擴(kuò)展性瓶頸.
(2) 事務(wù)時(shí)間戳的可擴(kuò)展性瓶頸. 共享緩存架構(gòu)沒有解決事務(wù)時(shí)間戳的可擴(kuò)展性瓶頸. 主要原因有兩點(diǎn): 一是共享緩存層的時(shí)間戳管理線程不能隨事務(wù)數(shù)量的增加而增加; 二是在訪問時(shí)間戳?xí)r, 每個(gè)計(jì)算節(jié)點(diǎn)都會(huì)對(duì)同一個(gè)內(nèi)存區(qū)域進(jìn)行RDMA Fetch & Add 操作, 對(duì)同一內(nèi)存位置的RDMA 原子操作會(huì)隨并發(fā)操作數(shù)的增加而增加, 而RDMA 原子操作的同步成本很高.
(3) 維護(hù)緩存一致性協(xié)議目錄的延遲高. 共享緩存通常需要基于目錄的緩存失效協(xié)議來保證頁面的一致性.頁面的目錄通常存儲(chǔ)在不同的存儲(chǔ)節(jié)點(diǎn)上, 這些目錄主要負(fù)責(zé)管理基于失效的緩存一致性協(xié)議的元數(shù)據(jù). 盡管以頁面粒度組織數(shù)據(jù)可以減少修改目錄的次數(shù), 但由于從共享緩存層訪問存儲(chǔ)層的延遲較大, 所以記錄目錄的成本依然較高.
新型存儲(chǔ)介質(zhì)持久化內(nèi)存 (persistent memory, PM) 成功地在共享緩存層和存儲(chǔ)層之間架設(shè)了橋梁. 2019 年, 英特爾推出了首款商品化的PM 產(chǎn)品—Optane PM. 一些基于CXL (compute express link) 的解決方案也試圖通過整合DRAM、閃存SSD 以及兼容內(nèi)存的互連技術(shù)來靠近PM. PM 的優(yōu)勢(shì)在于其字節(jié)尋址能力、數(shù)據(jù)持久性以及快速訪問速度. 此外, 結(jié)合了RDMA (remote direct memory access) 技術(shù)后, PM 可以實(shí)現(xiàn)低延遲的數(shù)據(jù)訪問. 鑒于以上特性, PM 成為了解決共享緩存架構(gòu)中現(xiàn)存問題的一種理想選擇.
為了解決共享緩存架構(gòu)存在的問題, 本文提出了TampoDB: 一個(gè)在線事務(wù)處理 (OLTP) 共享數(shù)據(jù)庫. 該數(shù)據(jù)庫整合了RDMA、DRAM、PM 和SSD 等多種技術(shù). 如圖1 (d) 所示, TampoDB 的設(shè)計(jì)基于三層共享架構(gòu), 包括共享緩存層、共享持久化內(nèi)存層及共享存儲(chǔ)層.
(1) 共享緩存層. 共享緩存層位于存儲(chǔ)架構(gòu)的頂層, 有最低的訪問延遲, 但又是易失性的. 該層主要用于存儲(chǔ)頻繁訪問的頁面.
(2) 共享持久化內(nèi)存層. 該層是非易失性的, 提供與DRAM 相近的低延遲訪問性能, 并通過RDMA 實(shí)現(xiàn)快速的網(wǎng)絡(luò)訪問. 在TampoDB 中, 該層用于存儲(chǔ)持久化日志、日志回放生成的頁面以及緩存目錄.
(3) 共享存儲(chǔ)層. 位于存儲(chǔ)架構(gòu)的最底層, 其訪問速度相較于共享緩存層和共享持久化內(nèi)存層較慢. 該層用于儲(chǔ)存所有的數(shù)據(jù)頁.
本章首先全面概述了TampoDB 三層架構(gòu)的構(gòu)成與功能, 并解析了三層之間如何協(xié)同工作以執(zhí)行事務(wù); 其次, 詳細(xì)闡述了TampoDB 是如何執(zhí)行事務(wù)的, 以及如何將事務(wù)在共享緩存層和共享持久化內(nèi)存層之間解耦, 從而加快事務(wù)的持久化過程; 最后, 介紹了如何將向量時(shí)間戳擴(kuò)展到多個(gè)節(jié)點(diǎn), 并提出分布式向量時(shí)間戳技術(shù).
TampoDB 的整體架構(gòu)如圖2 所示. 事務(wù)的執(zhí)行主要在共享緩存層進(jìn)行, 持久化日志和頁面的回放則在共享持久化內(nèi)存層完成, 而共享存儲(chǔ)層主要用于存放冷頁面. TampoDB 在共享緩存層和共享持久化內(nèi)存層中, 都會(huì)維護(hù)同一個(gè)邏輯頁面的兩個(gè)物理頁面. 圖中的箭頭展示了事務(wù)執(zhí)行的過程. 對(duì)于事務(wù)執(zhí)行過程中需要訪問的頁面, 首先需要判斷該邏輯頁面是否存在于共享緩存層. 如果邏輯頁面不在共享緩存層, 那么事務(wù)則需要訪問共享存儲(chǔ)層以獲取所需頁面, 同時(shí), 該頁面的副本也會(huì)被添加到共享緩存層和共享持久化內(nèi)存層. 如果邏輯頁面在共享緩存層, 但對(duì)應(yīng)的物理頁面并未在共享緩存層, 那么就會(huì)觸發(fā)一次緩存未命中. 這時(shí), 后臺(tái)線程會(huì)將該邏輯頁面存在于共享持久化內(nèi)存層中的物理頁面換入共享緩存層, 以便事務(wù)能重新讀取. 在事務(wù)執(zhí)行過程中產(chǎn)生的重做日志將會(huì)被持久化到PM 層中的日志區(qū)域, 并由后臺(tái)線程回放, 生成共享持久化內(nèi)存層中的頁面. 當(dāng)共享持久化內(nèi)存的空間受到壓力時(shí), 已完成回放的冷頁面將被驅(qū)逐到共享存儲(chǔ)層中.
圖2 TampoDB 的架構(gòu)概覽Fig. 2 Overview of TampoDB architecture
TampoDB 的事務(wù)執(zhí)行可以分為3 個(gè)階段: 執(zhí)行、持久化和回放.
(1) 執(zhí)行. 在事務(wù)開始時(shí), 會(huì)為其分配一個(gè)時(shí)間戳. 對(duì)于事務(wù)請(qǐng)求的每個(gè)頁面,頁面讀取器將其讀取到本節(jié)點(diǎn)的緩存中. 事務(wù)完全在本地執(zhí)行, 由事務(wù)管理器將事務(wù)執(zhí)行中產(chǎn)生的私有數(shù)據(jù)保存在本地.每個(gè)已提交的事務(wù)都會(huì)產(chǎn)生一個(gè)重做日志, 它將被臨時(shí)存儲(chǔ)在一個(gè)線程本地的日志緩沖區(qū)中, 以避免線程之間的爭用.
(2) 持久化. 已提交的事務(wù)將其在日志緩沖區(qū)中的重做日志寫入到本節(jié)點(diǎn)的持久化內(nèi)存中, 此步驟由后臺(tái)線程完成. 每個(gè)節(jié)點(diǎn)都將其私有日志文件寫入, 從而確保事務(wù)的原子性和持久性.
(3) 回放. 系統(tǒng)對(duì)持久化日志進(jìn)行回放, 并將其應(yīng)用到共享持久化內(nèi)存的頁面中. 由于計(jì)算節(jié)點(diǎn)可能訪問任何頁面, 因此單個(gè)頁面的更改會(huì)分散在多個(gè)本地日志中. 因此, 在回放過程中, 各節(jié)點(diǎn)的本地日志首先會(huì)發(fā)送到一個(gè)節(jié)點(diǎn)進(jìn)行合并后再發(fā)送回各節(jié)點(diǎn). 每個(gè)節(jié)點(diǎn)根據(jù)重做日志, 修改持久化內(nèi)存中的頁面數(shù)據(jù). 回放也在后臺(tái)進(jìn)行.
TampoDB 能夠利用持久化的重做日志在后臺(tái)執(zhí)行回放, 將更新同步到共享持久化內(nèi)存中的頁面.因此, 在事務(wù)執(zhí)行過程中, 一旦完成持久化步驟, 就可以認(rèn)為事務(wù)已經(jīng)持久化. PM 層和DRAM 層被映射到同一地址空間, 事務(wù)執(zhí)行過程中, 所有對(duì)日志數(shù)據(jù)的訪問都會(huì)被重定向到共享緩存中的地址.事務(wù)在共享緩存層和共享持久化層之間是完全解耦的, 滿足事務(wù)執(zhí)行中對(duì)頁面訪問的較低延遲需求的同時(shí), 又提升了共享緩存層臟頁驅(qū)逐的效率, 因?yàn)槭聞?wù)持久化過程中不需要對(duì)共享緩存層進(jìn)行臟頁驅(qū)逐.
數(shù)據(jù)庫通常使用一個(gè)全局計(jì)數(shù)器為事務(wù)提供全局時(shí)間戳 (global timestamp, GTS), 該時(shí)間戳代表了事務(wù)的執(zhí)行順序. 然而, GTS 機(jī)制不僅增加了事務(wù)之間的通信量, 還導(dǎo)致事務(wù)并發(fā)控制的擴(kuò)展性存在較大瓶頸.
向量時(shí)間戳 (vector timestamp, VTS) 為每個(gè)計(jì)算服務(wù)器或線程維護(hù)提供一個(gè)邏輯時(shí)鐘. 事務(wù)開始時(shí)需要獲取最新版本的VTS 作為讀取時(shí)間戳, 獲取提交時(shí)間戳則相對(duì)簡單, 只需將對(duì)應(yīng)計(jì)算服務(wù)器的邏輯時(shí)鐘遞增1 (內(nèi)存服務(wù)器也需要同步). 由于事務(wù)間的時(shí)間戳是獨(dú)立的, 長時(shí)間運(yùn)行的事務(wù)不會(huì)阻止讀取時(shí)間戳的前進(jìn), 從而消除了線程級(jí)別的時(shí)間戳擴(kuò)展性瓶頸. 然而, 目前的VTS 機(jī)制無法擴(kuò)展到多臺(tái)服務(wù)器, 因?yàn)檫@會(huì)導(dǎo)致不同工作線程之間無法獲取一致的快照. VTS 機(jī)制受限于單個(gè)服務(wù)器帶來的顯著問題是VTS 的網(wǎng)絡(luò)通信壓力集中在單個(gè)節(jié)點(diǎn)上, 盡管使用RDMA 原子更新操作延遲較小, 但是性能下降和可擴(kuò)展性瓶頸依然存在.
將VTS 擴(kuò)展到多臺(tái)服務(wù)器引入了一個(gè)新問題. 在單臺(tái)時(shí)間戳節(jié)點(diǎn)上, 計(jì)算節(jié)點(diǎn)讀取到的VTS 滿足單調(diào)遞增的關(guān)系. 但在多臺(tái)服務(wù)器中讀取VTS 會(huì)使其不再滿足此特性, 因此需要添加一些約束, 以使不同計(jì)算節(jié)點(diǎn)讀取到的時(shí)間戳重新滿足遞增的關(guān)系. 一個(gè)自然的想法是讓所有計(jì)算節(jié)點(diǎn)按照相同的順序訪問每臺(tái)時(shí)間戳服務(wù)器. 如果訪問每臺(tái)時(shí)間戳服務(wù)器的訪問延遲是相同的, 這就可以保證多臺(tái)服務(wù)器之間讀取到的VTS 按照最初的訪問順序是滿足單調(diào)遞增的. 但由于每臺(tái)時(shí)間戳服務(wù)器的訪問延遲是不可控的, 必須添加額外的約束, 使多臺(tái)服務(wù)器之間讀取到的VTS 按照最初的訪問順序保持單調(diào)遞增. 因此, 針對(duì)VTS 存在的問題本文提出了分布式向量時(shí)間戳 (discribute vector timestamp,DVTS), DVTS 在VTS 的基礎(chǔ)上添加了兩個(gè)約束規(guī)則以支持多節(jié)點(diǎn)間的擴(kuò)展.
規(guī)則一: 所有計(jì)算節(jié)點(diǎn)在獲取時(shí)間戳?xí)r, 必須按照固定的順序訪問時(shí)間戳服務(wù)器, 例如 (時(shí)間戳服務(wù)器1、時(shí)間戳服務(wù)器2、時(shí)間戳服務(wù)器3······) .
規(guī)則二: 每個(gè)計(jì)算節(jié)點(diǎn)在當(dāng)前時(shí)間戳服務(wù)器讀取的VTS 產(chǎn)生的偏序關(guān)系要和前一個(gè)訪問的時(shí)間戳服務(wù)器讀取的VTS 產(chǎn)生的偏序關(guān)系一致, 即若對(duì)于時(shí)間服務(wù)器n有an≤bn, 則有ai≤bi,?i≤n.
相對(duì)于VTS 單個(gè)服務(wù)器的網(wǎng)絡(luò)通信瓶頸, DVTS 利用RDMA 讀取和原子更新操作將時(shí)間戳的更新和讀取過程中的網(wǎng)絡(luò)開銷分布在多臺(tái)服務(wù)器中, 避免單一服務(wù)器的通信瓶頸. 此外, 由于時(shí)間戳分布在不同節(jié)點(diǎn)的不同內(nèi)存區(qū)域, RDMA 遠(yuǎn)程更新時(shí)避免了對(duì)統(tǒng)一內(nèi)存區(qū)域的爭議. 此外DVTS 可以實(shí)現(xiàn)在多臺(tái)服務(wù)器之間的擴(kuò)展, 具有更好的可擴(kuò)展性.
在具體實(shí)現(xiàn)中, TampoDB 為時(shí)間戳服務(wù)器的每個(gè)時(shí)間戳維護(hù)一個(gè) (tmin,tmax) 可見性區(qū)間,tmin和tmax分別代表前一個(gè)時(shí)間戳服務(wù)器訪問當(dāng)前時(shí)間戳服務(wù)器時(shí)間戳的最小和最大版本. 這個(gè)區(qū)間記錄了訪問前一個(gè)時(shí)間戳服務(wù)器所生成的時(shí)間戳的可見性范圍, 時(shí)間戳的可見性區(qū)間之間滿足單調(diào)遞增的關(guān)系. 每個(gè)服務(wù)器會(huì)從當(dāng)前最新的時(shí)間戳開始向前遍歷, 直到找到符合可見性區(qū)間范圍的時(shí)間戳為止.
本章首先描述了TampoDB 架構(gòu)由哪些主要組成部分構(gòu)成(圖3); 其次詳細(xì)描述了主要組成部分的功能及實(shí)現(xiàn).
圖3 TampoDB 的組成部分Fig. 3 Components of TampoDB
DRAM 層主要用于處理事務(wù), 由事務(wù)管理器負(fù)責(zé)執(zhí)行.頁面讀取器負(fù)責(zé)在事務(wù)執(zhí)行過程中獲取所需的頁面, 可能需要從本節(jié)點(diǎn)或遠(yuǎn)程節(jié)點(diǎn)進(jìn)行獲取. 在后臺(tái), 分布式向量時(shí)間戳?xí)掷m(xù)生成滿足遞增關(guān)系的向量時(shí)間戳, 并在事務(wù)管理器首次訪問時(shí)進(jìn)行分配. 日志寫入器負(fù)責(zé)將事務(wù)執(zhí)行過程中產(chǎn)生的重做日志首先寫入日志緩沖區(qū), 以便事務(wù)執(zhí)行過程中的訪問; 其次, 由專門的后臺(tái)線程將數(shù)據(jù)日志和元數(shù)據(jù)日志寫入PM 的日志區(qū)域.頁面的回放也在后臺(tái)進(jìn)行, PM 中的持久化日志的更改會(huì)被同步到共享持久化內(nèi)存中的頁面上.
TampoDB 采用了一種基于目錄的緩存一致性協(xié)議, 這種協(xié)議能在頁面粒度上提供一致性. 根據(jù)緩存一致性協(xié)議,頁面根據(jù)其所有權(quán)被分為3 種狀態(tài): 獨(dú)占、共享、失效. 協(xié)議通過失效動(dòng)作來確保頁面的一致性, 例如每當(dāng)某個(gè)節(jié)點(diǎn)打算修改一個(gè)頁面時(shí), 這個(gè)節(jié)點(diǎn)就會(huì)向跟蹤當(dāng)前緩存此頁面的節(jié)點(diǎn)的目錄并發(fā)送失效請(qǐng)求, 從而使頁面由獨(dú)占或共享狀態(tài)轉(zhuǎn)換為失效狀態(tài). 每個(gè)節(jié)點(diǎn)都充當(dāng)一些頁面目錄的存放節(jié)點(diǎn), 并負(fù)責(zé)管理存儲(chǔ)在其本地PM 中的目錄. TampoDB 使用頁面ID 定位到目錄,頁面ID 共有64 位, 前8 位記錄節(jié)點(diǎn)ID, 后56 位記錄該頁對(duì)應(yīng)目錄的偏移量. 目錄主要包含緩存一致性協(xié)議中的元數(shù)據(jù). 如上圖所示,頁面P2 被本節(jié)點(diǎn)以獨(dú)占模式持有, 而頁面P1 則被節(jié)點(diǎn)0 和1 以共享模式緩存.
頁面讀取器對(duì)頁面的訪問包括本地節(jié)點(diǎn)訪問和遠(yuǎn)程節(jié)點(diǎn)訪問兩種方式. 在本地節(jié)點(diǎn)訪問時(shí),頁面讀取器首先會(huì)查找位于DRAM 中的頁表, 以判斷頁面是否存在于本地緩存中.頁表中還額外記錄了頁面的所有權(quán)信息、頁鎖狀態(tài)以及驅(qū)逐信息.頁面的所有權(quán)分為節(jié)點(diǎn)獨(dú)占和節(jié)點(diǎn)共享兩種. 每個(gè)工作線程在訪問頁面之前, 必須先檢查所有權(quán)是否正確: 寫入頁面需要在獨(dú)占模式下進(jìn)行, 而讀取頁面則可以在共享模式或獨(dú)占模式下進(jìn)行. 在確認(rèn)所有權(quán)正確后, 就可以對(duì)頁面進(jìn)行加鎖并進(jìn)行訪問. 而在進(jìn)行遠(yuǎn)程節(jié)點(diǎn)訪問時(shí), 如果頁面不在本節(jié)點(diǎn)的緩存中, 就需要向該頁面的目錄節(jié)點(diǎn)發(fā)送請(qǐng)求. 目錄節(jié)點(diǎn)的消息處理程序在收到請(qǐng)求后, 也需要先檢查頁面的所有權(quán)是否正確. 如果所有權(quán)正確, 它會(huì)修改緩存目錄, 將該頁面的目錄和頁面數(shù)據(jù)發(fā)送給請(qǐng)求節(jié)點(diǎn).
本章展示了TampoDB 在優(yōu)化事務(wù)執(zhí)行流程和時(shí)間戳后的性能表現(xiàn). 通過與NAM-DB 進(jìn)行對(duì)比,評(píng)估了 TampoDB 在不同負(fù)載場(chǎng)景下的吞吐表現(xiàn). NAM-DB 是一個(gè)兩層的 (計(jì)算層和內(nèi)存層) 共享內(nèi)存數(shù)據(jù)庫, 其不依賴于緩存一致性協(xié)議而是通過RDMA 單邊讀和寫分別讀取和更新遠(yuǎn)程數(shù)據(jù), 以此來保證數(shù)據(jù)的一致性. 此外NAM-DB 在事務(wù)執(zhí)行中采用向量時(shí)間戳并使用結(jié)合RDMA 的SI 協(xié)議以進(jìn)一步提高事務(wù)可擴(kuò)展性.
實(shí)驗(yàn)在兩臺(tái)相同配置的服務(wù)器上進(jìn)行, 操作系統(tǒng)為CentOS Linux release 7.9.2009, 服務(wù)器硬件配置為 Intel(R) Xeon(R) Silver 4 110 CPU @ 2.10 GHz 16 核心, 32 線程; 內(nèi)存容量為512 GB; 持久化內(nèi)存容量為2 TB; SSD 容量為8 TB.
為了對(duì)比TampoDB 在讀密集負(fù)載場(chǎng)景下的性能, 本文使用YCSB 1B 記錄 (300 GB)的負(fù)載, 設(shè)置90%讀取和10%寫入訪問分布在2 臺(tái)節(jié)點(diǎn)上, 圖4 顯示量均勻(uniform)和傾斜(zipf-1)訪問下的吞吐量表現(xiàn), 在均勻訪問時(shí)二者性能接近, 然而在傾斜訪問時(shí)由于更多的數(shù)據(jù)會(huì)分布在TampoDB 本節(jié)點(diǎn)緩存, 因此性能表現(xiàn)顯著優(yōu)于NAM-DB.
圖4 TampoDB 在讀密集負(fù)載場(chǎng)景下的吞吐Fig. 4 Throughput of TampoDB in read-intensive workload scenarios
為了對(duì)比TampoDB 在寫密集負(fù)載場(chǎng)景下的性能, 本文同樣使用YCSB 1B 記錄 (300 GB)的負(fù)載, 設(shè)置90%寫入和10%讀取訪問分布在2 臺(tái)節(jié)點(diǎn)上, 圖5 顯示了均勻(uniform)和傾斜(zipf-1)訪問下的吞吐量表現(xiàn), 在兩種情況下TampoDB 表現(xiàn)均優(yōu)于NAM-DB, 在均勻訪問的情況下寫入速度依然提升了25%. 由于NAM-DB 在寫入時(shí)使用RDMA 原子寫的方式, 在傾斜訪問時(shí)由于競爭嚴(yán)重導(dǎo)致性能下降. 在數(shù)據(jù)均勻分布時(shí), 由于NAM-DB 需要在事務(wù)寫集更新前將日志寫入到內(nèi)存服務(wù)器, 而TampoDB事務(wù)執(zhí)行時(shí)對(duì)頁面更新和日志持久化是解耦的, 因此寫入性能依舊優(yōu)于NAM-DB.
圖5 TampoDB 在寫密集負(fù)載場(chǎng)景下的吞吐Fig. 5 Throughput of TampoDB in write-intensive workload scenarios
為對(duì)比分布式向量時(shí)間戳在不同負(fù)載場(chǎng)景下的性能表現(xiàn), 本文同樣使用YCSB 1B 記錄 (300 GB)的負(fù)載, 設(shè)置在2 臺(tái)節(jié)點(diǎn)上, 圖6 顯示了在TampoDB 中使用VTS 和DVTS 分別在讀密集和寫密集負(fù)載下并且數(shù)據(jù)均勻分布的吞吐量表現(xiàn). DVTS 在讀密集訪問和寫密集訪問負(fù)載下相較于VTS 吞吐量分別提高了16%和13%. DVTS 將單臺(tái)時(shí)間戳服務(wù)器的讀寫請(qǐng)求分布到兩臺(tái)時(shí)間戳服務(wù)器上, 減少了單臺(tái)服務(wù)器的時(shí)間戳通信開銷.
圖6 分布式向量時(shí)間戳在讀寫密集負(fù)載下的吞吐Fig. 6 Throughput of DVTS in read-intensive and write-intensive workload scenarios
本文針對(duì)共享緩存架構(gòu)中的數(shù)據(jù)持久化速度慢、事務(wù)時(shí)間戳的可擴(kuò)展性瓶頸、維護(hù)緩存一致性協(xié)議目錄的高延遲等問題, 基于共享緩存架構(gòu)設(shè)計(jì)了TampoDB. 為了解決持久化速度慢的問題,TampoDB 添加了一個(gè)共享持久化內(nèi)存層, 并將事務(wù)的執(zhí)行和持久化過程進(jìn)行了解耦. 此外,TampoDB 還重新設(shè)計(jì)了分布式向量時(shí)間戳, 并利用PM 加速了緩存目錄的修改, 從而提高了事務(wù)的可擴(kuò)展性. 實(shí)驗(yàn)證明, TampoDB 能高效地執(zhí)行事務(wù). 當(dāng)前的研究主要集中在持久化日志方面, 而在后續(xù)的研究中, 共享緩存架構(gòu)下的數(shù)據(jù)遷移和驅(qū)逐策略也是值得探討的問題.