掃二維碼與項(xiàng)目經(jīng)理溝通
我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢(xún)/運(yùn)營(yíng)咨詢(xún)/技術(shù)建議/互聯(lián)網(wǎng)交流
作者 | 馬浩翔

日前,字節(jié)跳動(dòng)技術(shù)社區(qū) ByteTech 舉辦的第四期字節(jié)跳動(dòng)技術(shù)沙龍圓滿(mǎn)落幕,本期沙龍以《字節(jié)云數(shù)據(jù)庫(kù)架構(gòu)設(shè)計(jì)與實(shí)戰(zhàn)》為主題。在沙龍中,字節(jié)跳動(dòng)基礎(chǔ)架構(gòu)數(shù)據(jù)庫(kù)開(kāi)發(fā)工程師馬浩翔,跟大家探討了 《從單機(jī)到分布式數(shù)據(jù)庫(kù)存儲(chǔ)系統(tǒng)的演進(jìn)》,本文根據(jù)分享整理而成。
存儲(chǔ)系統(tǒng)是指能高效存儲(chǔ),持久化用戶(hù)數(shù)據(jù)的一系列系統(tǒng)軟件。在眾多的存儲(chǔ)系統(tǒng)中,以下是三類(lèi)比較主流的存儲(chǔ)產(chǎn)品及其特點(diǎn)分析:
單機(jī)數(shù)據(jù)庫(kù)存儲(chǔ),要從內(nèi)存層和持久化層兩個(gè)方面來(lái)解析。在內(nèi)存層,僅說(shuō)關(guān)系型數(shù)據(jù)庫(kù),其內(nèi)存數(shù)據(jù)結(jié)構(gòu)特點(diǎn)可以總結(jié)為:一切都是“樹(shù)”。我們以最常見(jiàn)的 B+ 樹(shù)為例,B+ 樹(shù)具有以下突出的特點(diǎn):
僅有內(nèi)存數(shù)據(jù)結(jié)構(gòu)當(dāng)然是不夠的,我們還需要設(shè)計(jì)高效的磁盤(pán)數(shù)據(jù)結(jié)構(gòu),下圖展示了從內(nèi)存數(shù)據(jù)結(jié)構(gòu)到磁盤(pán)數(shù)據(jù)結(jié)構(gòu)的數(shù)據(jù)持久化過(guò)程:
左邊虛線(xiàn)框描繪的是 In Memory 結(jié)構(gòu)示意圖。舉個(gè)例子,如果我們要修改 Page A 的某一行數(shù)據(jù),對(duì)其中的一個(gè)字段進(jìn)行自增,自增值是 2。自然而然會(huì)產(chǎn)生一個(gè)數(shù)據(jù)庫(kù)的物理操作日志,即 Redo Log,用來(lái)描述我們對(duì) Page A 的修改。同時(shí),在數(shù)據(jù)庫(kù)的事務(wù)執(zhí)行過(guò)程中,可能還會(huì)產(chǎn)生大量臨時(shí)數(shù)據(jù)(圖里的 Temp data),當(dāng)內(nèi)存不夠用的時(shí)候也需要將其持久化。
右邊虛線(xiàn)框描繪的是 In Persistent Layer 的示意圖。假設(shè)我們使用比較友好的文件系統(tǒng)來(lái)將內(nèi)存數(shù)據(jù)持久化,我們需要設(shè)置不同的文件,讓它們各司其職。例如圖里的藍(lán)色文件存儲(chǔ) Page,綠色文件存儲(chǔ) Redo Log,粉色文件存儲(chǔ)臨時(shí)數(shù)據(jù)。如果數(shù)據(jù)庫(kù)發(fā)生 crash ,在恢復(fù)階段我們就在各類(lèi)文件中進(jìn)行數(shù)據(jù)定位,結(jié)合 Redo Log File 和 Page File ,進(jìn)行數(shù)據(jù)庫(kù)的數(shù)據(jù)恢復(fù)。除此之外,如果直接基于塊存儲(chǔ)進(jìn)行持久化,就需要數(shù)據(jù)庫(kù)本身的存儲(chǔ)引擎管理好 LBA,需要在用戶(hù)態(tài)里面實(shí)現(xiàn) buffer cache 等邏輯,這也是可行的。
那么基于單機(jī)的 FS / 塊存儲(chǔ)去做持久化,我們會(huì)遇到哪些問(wèn)題呢?通過(guò)下面的單機(jī)數(shù)據(jù)庫(kù)系統(tǒng)的典型架構(gòu)圖,我們可以發(fā)現(xiàn)三個(gè)問(wèn)題:
為了解決單機(jī)數(shù)據(jù)庫(kù)存儲(chǔ)系統(tǒng)面臨的問(wèn)題和挑戰(zhàn),字節(jié)跳動(dòng)的數(shù)據(jù)庫(kù)團(tuán)隊(duì)調(diào)研了一些業(yè)界主流的分布式數(shù)據(jù)庫(kù)方案。
需要說(shuō)明的是,MyRocks 不是分布式數(shù)據(jù)庫(kù)或者分布式解決方案,它是單機(jī) SQL over kv 的典型代表。
基于上述字節(jié)數(shù)據(jù)庫(kù)團(tuán)隊(duì)的調(diào)研結(jié)果,我們?cè)O(shè)計(jì)了 veDB 分布式存儲(chǔ)系統(tǒng)以解決單機(jī)數(shù)據(jù)庫(kù)存儲(chǔ)系統(tǒng)面臨的問(wèn)題與挑戰(zhàn),本節(jié)將主要介紹 veDB 分布式存儲(chǔ)系統(tǒng)的系統(tǒng)目標(biāo)與核心技術(shù)特點(diǎn)。
在設(shè)計(jì)理念上,我們期望存儲(chǔ)系統(tǒng)能夠?qū)崿F(xiàn)以下四個(gè)主要目標(biāo):
基于以上系統(tǒng)目標(biāo),數(shù)據(jù)庫(kù)團(tuán)隊(duì)設(shè)計(jì)并開(kāi)發(fā)了 veDB 分布式存儲(chǔ)系統(tǒng),如下圖所示:
從圖中可以看出,分布式存儲(chǔ)層基于 LogStore 和 PageStore 這兩個(gè)子系統(tǒng)構(gòu)建,其系統(tǒng)特點(diǎn)與我們的設(shè)計(jì)目標(biāo)相互呼應(yīng)。
以下主要從研發(fā)背景(Problem)、解決思路(Solution)、解決成效(Outcome)三個(gè)方面來(lái)分別介紹 veDB 分布式存儲(chǔ)系統(tǒng)的五個(gè)核心技術(shù)。
Distributed Data Model
Problem:從單機(jī) FS 到分布式存儲(chǔ),需要有高效的數(shù)據(jù)布局模型?;趩螜C(jī)的文件系統(tǒng)或塊存儲(chǔ)系統(tǒng)去實(shí)現(xiàn)數(shù)據(jù)持久化是比較簡(jiǎn)單的,我們可以直接通過(guò)申請(qǐng)一批 LBA 或者一批文件來(lái)存儲(chǔ)數(shù)據(jù),然后控制并發(fā)即可,但是這對(duì)于分布式存儲(chǔ)并不容易。從上面的示意圖可以看到,最上層的 Tablespace 代表一張數(shù)據(jù)庫(kù)表,里面可能包含上百萬(wàn)甚至上千萬(wàn)的 Page data(數(shù)據(jù)庫(kù)的基礎(chǔ)管理單元)。然而存儲(chǔ)系統(tǒng)的管理單元,卻不可能是 Page —— Page 的粒度過(guò)小,往往只有 KB 級(jí)別,如果存儲(chǔ)層以過(guò)小的粒度去管理數(shù)據(jù),可能會(huì)造成元數(shù)據(jù)膨脹,增加管理成本。
Solution:Tablespace -> Segement 分布式映射?;谏鲜鰡?wèn)題,我們可以在存儲(chǔ)層利用相對(duì)大的管理單元 Segment 去進(jìn)行數(shù)據(jù)管理。此時(shí),數(shù)據(jù)庫(kù)的管理單元是 Page,存儲(chǔ)系統(tǒng)的管理單元是 Segement。Tablespace 和 Segement 之間必然要存在一層映射關(guān)系,該映射關(guān)系可以根據(jù)不同數(shù)據(jù)庫(kù)引擎的數(shù)據(jù)管理空間大小要求進(jìn)行設(shè)置,可能 MySQL 和 PostgreSQL 的映射規(guī)則就大不相同。上述示意圖展示了最簡(jiǎn)單的模 2 規(guī)則,我們也可以發(fā)展出其他更加復(fù)雜的打散規(guī)則,此處不進(jìn)行贅述。當(dāng)我們將 Page 打散到對(duì)應(yīng)的 Segement 之后,數(shù)據(jù)庫(kù)就不需要管數(shù)據(jù) Replication 的邏輯,不管底層存儲(chǔ)是多副本還是 EC 策略,可以完全由存儲(chǔ)系統(tǒng)來(lái)做透明的 Replication ,數(shù)據(jù)庫(kù)就像在使用單機(jī)文件系統(tǒng)一樣簡(jiǎn)單。
Outcome
Log-Only Segement
Problem:數(shù)據(jù)冗余成本高,需要降低存儲(chǔ)成本。
Solution:開(kāi)發(fā) Log-Only Segement,節(jié)省非必要的 Page 副本空間。什么是 Log-only segement? 關(guān)系型數(shù)據(jù)庫(kù)中往往都包含 Log 數(shù)據(jù)和 Page 數(shù)據(jù)。在存儲(chǔ)層中,存了多副本的 Log 數(shù)據(jù)后,我們可以選擇性地只回放一部分 Log 數(shù)據(jù)來(lái)生成 Page,讓另一部分 Log 數(shù)據(jù)保持不動(dòng),不要生成任何 Page 數(shù)據(jù)。以上面的示意圖為例,Rep_0 和 Rep_1 都是 Log 數(shù)據(jù)生成的各種版本 Page 數(shù)據(jù),然而 Rep_2 是一個(gè)空的 Page 數(shù)據(jù)副本,它里面只有 Redo log。我們都知道 Redo log 和 Page data 的數(shù)據(jù)大小比例是比較夸張的,Page data 的大小可能是 Redo log 的幾倍甚至十幾倍,因此通過(guò)以上方法能夠較大的節(jié)省單機(jī)的 Page 存儲(chǔ)空間。
Outcome:結(jié)合單機(jī)引擎的壓縮算法,能將存儲(chǔ)空間放大倍數(shù)從 3.x -> 1.x,較好緩解成本問(wèn)題。
Problem:存儲(chǔ)層寫(xiě)性能容易成為系統(tǒng)性能瓶頸,如何解決?
Solution:全異步 IO + 無(wú)鎖結(jié)構(gòu) +并發(fā)打散。當(dāng)數(shù)據(jù)庫(kù)提交了一個(gè) Redo log 到 Log Storage 之后,Log Storage 中會(huì)有一個(gè)無(wú)鎖的 Ring buffer 去對(duì) Redo log 進(jìn)行有序組織,然后我們將 Redo Log 的 Ring buffer 進(jìn)行線(xiàn)性的定長(zhǎng)切割,并發(fā)打散到底層存儲(chǔ)的 Blob 單元。
Outcome:4KB + depth 8,write latency ~100+us,較好支撐了數(shù)據(jù)庫(kù)下發(fā)日志的性能剛需。
PITR
PITR(Point-in-time Recovery)是指我們都可以迅速地恢復(fù)在過(guò)去一段時(shí)間內(nèi)某個(gè)時(shí)間點(diǎn)的數(shù)據(jù)庫(kù)快照。
Problem:如何快速備份恢復(fù),且降低對(duì)前臺(tái)業(yè)務(wù)影響?
Solution:基于 Segement 的高并發(fā) PITR 機(jī)制,Segement 間互不影響。之前提到存儲(chǔ)層的管理單元是 Segement ,我們也可以基于 Segement 做備份恢復(fù)。這樣做有兩個(gè)好處:首先計(jì)算層是完全透明的,計(jì)算層完全不會(huì)感知,并且計(jì)算層的性能不會(huì)抖動(dòng)。其次基于 Segment 可以做到天然的并發(fā)打散,因此備份恢復(fù)也可以做到并發(fā)恢復(fù)。
Outcome
Problem:數(shù)據(jù)庫(kù)團(tuán)隊(duì)希望統(tǒng)一的存儲(chǔ)層能夠支持不同的數(shù)據(jù)庫(kù)引擎,做到 100% 兼容和快速接入。
Solution:Write Ahead Log + Log Replay = 任意 Page Data?;诒镜卮鎯?chǔ)引擎的 k-v 結(jié)構(gòu),或者基于裸的塊設(shè)備抽象出一種相對(duì)通用的數(shù)據(jù)結(jié)構(gòu),從而高效地存儲(chǔ) Page data。同時(shí),我們?cè)?SDK 側(cè)和 Server 側(cè)都做了 Log parse 的插件化,要接入新的數(shù)據(jù)庫(kù)引擎只需要其提供適配存儲(chǔ)接口的日志插件,從而可以快速接入各式各樣的數(shù)據(jù)庫(kù)計(jì)算引擎。
Outcome:
在談及數(shù)據(jù)庫(kù)存儲(chǔ)的未來(lái)演進(jìn)時(shí),首先我們可以思考一下哪些因素會(huì)觸發(fā)數(shù)據(jù)庫(kù)存儲(chǔ)架構(gòu)的變革和演進(jìn)?答案可能包含:存儲(chǔ)架構(gòu)自身的革命、數(shù)據(jù)庫(kù)理論的突破、或者新硬件沖擊引發(fā)存儲(chǔ)系統(tǒng)架構(gòu)迭代。基于這三個(gè)方向的思考,我們總結(jié)了以下幾個(gè)數(shù)據(jù)庫(kù)存儲(chǔ)系統(tǒng)的演進(jìn)趨勢(shì):
我們總結(jié)的第一個(gè)趨勢(shì)即 HTAP/HSAP 系統(tǒng)將會(huì)逐漸爆發(fā)。在 HTAP/HSAP 系統(tǒng)中,“實(shí)時(shí)”是第一關(guān)鍵詞。為了支持實(shí)時(shí),存儲(chǔ)系統(tǒng)可能會(huì)發(fā)生架構(gòu)演進(jìn)和變革,因此我們需要探索:
AI 技術(shù)運(yùn)用領(lǐng)域廣泛,具體在數(shù)據(jù)庫(kù)存儲(chǔ)領(lǐng)域,我們可以利用 AI 技術(shù)進(jìn)行以下工作:
在硬件變革趨勢(shì)上,我們總結(jié)了三個(gè)變革方向:

我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢(xún)/運(yùn)營(yíng)咨詢(xún)/技術(shù)建議/互聯(lián)網(wǎng)交流