摘要:前面我們簡(jiǎn)單闡述了分布式數(shù)據(jù)庫(kù)的架構(gòu),并通過(guò)一條簡(jiǎn)單的查詢(xún)語(yǔ)句解釋了分布式的執(zhí)行計(jì)劃。
引言
第八屆中國(guó)架構(gòu)師大會(huì)(SACC2016)10月27號(hào)到29號(hào)在北京萬(wàn)達(dá)索菲特大飯店成功舉辦。大會(huì)以“架構(gòu)創(chuàng)新之路“為主題,云集了國(guó)內(nèi)外頂尖專(zhuān)家,共同探討云計(jì)算和大數(shù)據(jù)等技術(shù)背景下,如何通過(guò)架構(gòu)創(chuàng)新及各種IT新技術(shù)來(lái)帶動(dòng)企業(yè)轉(zhuǎn)型增效。作為一家專(zhuān)注于云端數(shù)據(jù)倉(cāng)庫(kù)的初創(chuàng)公司,酷克數(shù)據(jù)受邀在SACC2016 “數(shù)據(jù)庫(kù)平臺(tái)架構(gòu)及變遷”分會(huì)場(chǎng)作了題為“數(shù)據(jù)倉(cāng)庫(kù)架構(gòu)及變遷”的演講。以下是這次演講的PPT。
這個(gè)日程安排同時(shí)也是我們公司核心團(tuán)隊(duì)的技術(shù)進(jìn)階史。公司創(chuàng)始團(tuán)隊(duì)成員有幸以核心開(kāi)發(fā)者的角色參與,從單機(jī)版的關(guān)系型數(shù)據(jù)庫(kù)(PostgreSQL),大規(guī)模并行處理(MPP)數(shù)據(jù)庫(kù)(Greenplum Database)到SQL on Hadoop解決方案(Apache HAWQ),以及最新的SQL on Cloud數(shù)據(jù)倉(cāng)庫(kù)(HashData)。通過(guò)回顧這個(gè)技術(shù)演進(jìn)的歷程,我們將闡述如何一步一步地解決聯(lián)機(jī)分析(OLAP)系統(tǒng)低延遲、高并發(fā)以及擴(kuò)展性問(wèn)題。
PostgreSQL由于后面討論的所有的分布式數(shù)據(jù)庫(kù),包括Greenplum Database,Apache HAWQ以及HashData云端數(shù)據(jù)倉(cāng)庫(kù),都是基于單機(jī)版關(guān)系型數(shù)據(jù)庫(kù)PostgreSQL的,所以我們首先簡(jiǎn)單介紹一下PostgreSQL,作為后續(xù)討論的基礎(chǔ)。
每個(gè)PostgreSQL數(shù)據(jù)庫(kù)的實(shí)例包含一個(gè)PostMaster的damon進(jìn)程和多個(gè)子進(jìn)程,包括負(fù)責(zé)寫(xiě)出臟數(shù)據(jù)的BG Writer進(jìn)程,收集統(tǒng)計(jì)信息的Stats Collector進(jìn)程,寫(xiě)事務(wù)日志的WAL Writer進(jìn)程,等等。
客戶(hù)端應(yīng)用通過(guò)libpq協(xié)議連接到PostMaster進(jìn)程;PostMaster收到連接請(qǐng)求后,fork出一個(gè)子進(jìn)程Postgres Server來(lái)處理來(lái)自這個(gè)連接的查詢(xún)語(yǔ)句。Postgres Server進(jìn)程的功能組件可以分成兩大類(lèi):查詢(xún)執(zhí)行和存儲(chǔ)管理。查詢(xún)執(zhí)行組件包括解析器、分析器、優(yōu)化器以及執(zhí)行器。在查詢(xún)執(zhí)行過(guò)程中,需要訪問(wèn)和更新系統(tǒng)狀態(tài)和數(shù)據(jù),包括緩存,鎖,文件和頁(yè)面等等。
Greenplum作為一個(gè)單機(jī)版的關(guān)系型數(shù)據(jù)庫(kù),PostgreSQL更多地是作為聯(lián)機(jī)事務(wù)處理(OLTP)系統(tǒng)使用的。當(dāng)然,由于其豐富的分析功能,很多企業(yè)也會(huì)基于PostgreSQL來(lái)構(gòu)建數(shù)據(jù)倉(cāng)庫(kù),特別是在數(shù)據(jù)量不大的情況下。但是,隨著數(shù)據(jù)量的增大,基于單機(jī)PostgreSQL構(gòu)建的數(shù)據(jù)倉(cāng)庫(kù)就無(wú)法滿(mǎn)足企業(yè)用戶(hù)對(duì)查詢(xún)響應(yīng)時(shí)間的要求:低延遲。
為了解決這個(gè)問(wèn)題,MPP架構(gòu)就被引入了。這是MPP架構(gòu)分布式數(shù)據(jù)庫(kù)的簡(jiǎn)單示意圖。MPP數(shù)據(jù)庫(kù)通過(guò)將數(shù)據(jù)切片分布到各個(gè)計(jì)算節(jié)點(diǎn)后并行處理來(lái)解決海量數(shù)據(jù)分析的難題。每個(gè)MPP數(shù)據(jù)庫(kù)集群由一個(gè)主節(jié)點(diǎn)(為了提供高可用性,通常還會(huì)有一個(gè)從主節(jié)點(diǎn))和多個(gè)計(jì)算節(jié)點(diǎn)組成。主節(jié)點(diǎn)和每個(gè)計(jì)算節(jié)點(diǎn)都有自己獨(dú)立的CPU,內(nèi)存和外部存儲(chǔ)。主節(jié)點(diǎn)負(fù)責(zé)接收客戶(hù)端的請(qǐng)求,生成查詢(xún)計(jì)劃,并將計(jì)劃下發(fā)到每個(gè)計(jì)算節(jié)點(diǎn),協(xié)調(diào)查詢(xún)計(jì)劃的完成,最后匯總查詢(xún)結(jié)果返回給客戶(hù)端。計(jì)算節(jié)點(diǎn)負(fù)責(zé)數(shù)據(jù)的存儲(chǔ)以及查詢(xún)計(jì)劃的執(zhí)行。計(jì)算節(jié)點(diǎn)之間是沒(méi)有任何共享依賴(lài)的(shared nothing)。查詢(xún)?cè)诿總€(gè)計(jì)算節(jié)點(diǎn)上面并行執(zhí)行,大大提升了查詢(xún)的效率。
我們接下來(lái)要講的開(kāi)源Greenplum Database就是基于PostgreSQL的MPP數(shù)據(jù)庫(kù)。對(duì)應(yīng)到這個(gè)架構(gòu)圖,每個(gè)節(jié)點(diǎn)上面的數(shù)據(jù)庫(kù)實(shí)例可以簡(jiǎn)單的認(rèn)為是一個(gè)PostgreSQL實(shí)例。
我們首先通過(guò)一條簡(jiǎn)單的查詢(xún),感性地認(rèn)識(shí)一下Greenplum Database是如何執(zhí)行一條查詢(xún)的。
這是一條簡(jiǎn)單的兩表等值連接語(yǔ)句。其中,customer表是維度表,表數(shù)據(jù)以cust_id作為hash分布的key;sales表是事實(shí)表,在這個(gè)例子中,我們可以認(rèn)為它的表數(shù)據(jù)是round-robin的方式隨機(jī)分布的,不影響查詢(xún)的執(zhí)行。
每個(gè)查詢(xún)執(zhí)行是一個(gè)由操作符組成的樹(shù)。只看其中一個(gè)節(jié)點(diǎn)的話(如前面所說(shuō),每個(gè)計(jì)算節(jié)點(diǎn)就是一個(gè)PostgreSQL的實(shí)例),為了執(zhí)行兩表的等值連接,我們首先會(huì)將兩表的數(shù)據(jù)分別掃描出來(lái),然后基于維度表customer建立hash桶。對(duì)于每一條從sales表掃描出來(lái)的紀(jì)錄,我們都會(huì)到hash桶去查。如果滿(mǎn)足匹配條件,數(shù)據(jù)連接結(jié)果;否則,直接pass。
如前面提到的,在Greenplum Database中,每張表的數(shù)據(jù)按照hash分布或者隨機(jī)分布打散到每個(gè)計(jì)算節(jié)點(diǎn)上面。在這個(gè)例子中,由于sales表是隨機(jī)分布的,為了正確執(zhí)行基于cust_id的等值連接,生成的執(zhí)行計(jì)劃會(huì)在table scan上面添加一個(gè)Redistribution motion節(jié)點(diǎn)。這個(gè)motion節(jié)點(diǎn)根據(jù)cust_id的hash值對(duì)數(shù)據(jù)作重分布,類(lèi)似MapReduce中的shuffling。由于hash join操作是在每個(gè)節(jié)點(diǎn)上面分布式執(zhí)行的,在將結(jié)果返回給客戶(hù)端的時(shí)候,需要在主節(jié)點(diǎn)上面執(zhí)行匯總操作。Gather motion的作用就在于將每個(gè)節(jié)點(diǎn)上面的中間結(jié)果集中到主節(jié)點(diǎn)上面。
對(duì)于這樣一個(gè)并行的查詢(xún)計(jì)劃,我們會(huì)根據(jù)數(shù)據(jù)重分布的操作將整棵查詢(xún)執(zhí)行樹(shù)切割成不同的子樹(shù)。每個(gè)子樹(shù)對(duì)應(yīng)查詢(xún)計(jì)劃的一個(gè)階段,我們稱(chēng)為slice。查詢(xún)計(jì)劃和slice是邏輯上的概念。
在物理層面,對(duì)應(yīng)的是并行執(zhí)行計(jì)劃和gang。gang指的是執(zhí)行同一個(gè)slice操作的一組進(jìn)程。MPP數(shù)據(jù)庫(kù)的一個(gè)重要特征是,計(jì)算和存儲(chǔ)是緊耦合的。每一張表的數(shù)據(jù)打散存儲(chǔ)到每個(gè)計(jì)算節(jié)點(diǎn)上面。為了確保查詢(xún)結(jié)果的正確性,每個(gè)計(jì)算節(jié)點(diǎn)都需要參與每條查詢(xún)的執(zhí)行中。在Greenplum Database的架構(gòu)設(shè)計(jì)中,對(duì)于每個(gè)slice執(zhí)行子樹(shù),在每個(gè)計(jì)算節(jié)點(diǎn)中會(huì)啟動(dòng)一個(gè)相應(yīng)的Postgres Server進(jìn)程(這里稱(chēng)為QE進(jìn)程)來(lái)執(zhí)行對(duì)應(yīng)的操作。執(zhí)行同一個(gè)slice的一組QE進(jìn)程我們稱(chēng)為gang。對(duì)應(yīng)于查詢(xún)計(jì)劃中的三個(gè)slice,在執(zhí)行計(jì)劃中,相應(yīng)有三組gang。其中底下的兩個(gè)gang,我們稱(chēng)之為N-gang,因?yàn)檫@種類(lèi)型的gang中,包含了每個(gè)計(jì)算節(jié)點(diǎn)上面啟動(dòng)的一個(gè)QE進(jìn)程。頂上的gang,我們稱(chēng)之為1-gang,因?yàn)樗话艘粋€(gè)進(jìn)程。
一般來(lái)說(shuō),對(duì)于N張表的關(guān)聯(lián)操作,執(zhí)行計(jì)劃中會(huì)包含2N個(gè)gang,其中1個(gè)1-gang,對(duì)應(yīng)主節(jié)點(diǎn)上面的進(jìn)程;2N-1個(gè)N-gang,對(duì)應(yīng)每個(gè)計(jì)算節(jié)點(diǎn)上面啟動(dòng)的2N-1個(gè)QE進(jìn)程。在這2N-1個(gè)gang中,其中N個(gè)用于掃描N張表,中間N-1個(gè)gang用于兩表關(guān)聯(lián)。也就是說(shuō),對(duì)于一條涉及到N表關(guān)聯(lián)操作的查詢(xún)語(yǔ)句,我們需要在每個(gè)計(jì)算節(jié)點(diǎn)上面啟動(dòng)2N-1個(gè)QE進(jìn)程。
很多用戶(hù)在評(píng)估Greenplum Database的并發(fā)數(shù),也就是支持的最大同時(shí)運(yùn)行的查詢(xún)數(shù)量,首先會(huì)擔(dān)心主節(jié)點(diǎn)會(huì)成為瓶頸,直觀原因是所有用戶(hù)連接請(qǐng)求都首先會(huì)到主節(jié)點(diǎn)。其實(shí),從資源使用的角度看,計(jì)算節(jié)點(diǎn)會(huì)首先成為瓶頸。因?yàn)樵趫?zhí)行涉及多表關(guān)聯(lián)的復(fù)雜查詢(xún)時(shí),計(jì)算節(jié)點(diǎn)上面啟動(dòng)的進(jìn)程數(shù)量會(huì)遠(yuǎn)多于主節(jié)點(diǎn)。所以,Greenplum Database系統(tǒng)架構(gòu)決定了它不能支持非常高的并發(fā)訪問(wèn)。
前面我們簡(jiǎn)單闡述了MPP分布式數(shù)據(jù)庫(kù)的架構(gòu),并通過(guò)一條簡(jiǎn)單的查詢(xún)語(yǔ)句解釋了分布式的執(zhí)行計(jì)劃。接下來(lái)我們深入討論一下Greenplum Database的重要組件。
首先是解析器。從使用者的角度看,Greenplum Database跟PostgreSQL沒(méi)有明顯差別。主節(jié)點(diǎn)作為整個(gè)分布式系統(tǒng)集群的大腦,負(fù)責(zé)接收客戶(hù)連接,處理請(qǐng)求。跟PostgreSQL一樣,對(duì)于每一個(gè)連接請(qǐng)求,Greenplum Database都會(huì)在主節(jié)點(diǎn)上面fork一個(gè)Postgres Server(我們稱(chēng)之為QD)進(jìn)程出來(lái),負(fù)責(zé)處理這個(gè)連接提交的查詢(xún)語(yǔ)句。對(duì)于每一條進(jìn)來(lái)的查詢(xún)語(yǔ)句,QD進(jìn)程中的解析器執(zhí)行語(yǔ)法分析和詞法分析,生成解析樹(shù)。雖然在一些DDL語(yǔ)句上面,Greenplum Database跟PostgreSQL會(huì)有一些語(yǔ)法上的小不同,例如建表語(yǔ)句可以指定數(shù)據(jù)進(jìn)行hash分布的key,但總體上,在解析器這個(gè)組件上面,兩者的差別不大。
優(yōu)化器根據(jù)解析器生成的解析樹(shù),生成查詢(xún)計(jì)劃。查詢(xún)計(jì)劃描述了如何執(zhí)行查詢(xún)。查詢(xún)計(jì)劃的優(yōu)劣直接影響查詢(xún)的執(zhí)行效率。對(duì)于同樣一條查詢(xún)語(yǔ)句,一個(gè)好的查詢(xún)執(zhí)行效率比一個(gè)次好的查詢(xún)計(jì)劃快上100倍,也是一個(gè)很正常的事情。從PostgreSQL到MPP架構(gòu)的Greenplum Database,優(yōu)化器做了重大改動(dòng)。雖然兩者都是基于代價(jià)來(lái)生成最優(yōu)的查詢(xún)計(jì)劃,但是Greenplum Database除了需要常規(guī)的表掃描代價(jià)、連接和聚合的執(zhí)行方式外,還需要考慮數(shù)據(jù)的分布式狀態(tài)、數(shù)據(jù)重分布的代價(jià),以及集群計(jì)算節(jié)點(diǎn)數(shù)量對(duì)執(zhí)行效率的影響,因?yàn)樗罱K是要生成一個(gè)分布式的查詢(xún)計(jì)劃。
調(diào)度器是Greenplum Database在PostgreSQL上新增的一個(gè)組件,負(fù)責(zé)分配處理查詢(xún)需要的計(jì)算資源,將查詢(xún)計(jì)劃發(fā)送到每個(gè)計(jì)算節(jié)點(diǎn)。在Greenplum Database中,我們稱(chēng)計(jì)算節(jié)點(diǎn)為Segment節(jié)點(diǎn)。前面也提過(guò),每一個(gè)Segment實(shí)例實(shí)際上就是一個(gè)PostgreSQL實(shí)例。調(diào)度器根據(jù)優(yōu)化器生成的查詢(xún)計(jì)劃確定執(zhí)行計(jì)劃需要的計(jì)算資源,然后通過(guò)libpg(修改過(guò)的libpg協(xié)議)協(xié)議給每個(gè)Segment實(shí)例發(fā)送連接請(qǐng)求,通過(guò)Segment實(shí)例上的PostMaster進(jìn)程fork出前面提到過(guò)的QE進(jìn)程。調(diào)度器同時(shí)負(fù)責(zé)這些fork出來(lái)的QE進(jìn)程的整個(gè)生命周期。
每個(gè)QE進(jìn)程接收到從調(diào)度器發(fā)送過(guò)來(lái)的查詢(xún)計(jì)劃之后,通過(guò)執(zhí)行器執(zhí)行分配給自己的任務(wù)。除了增加一個(gè)新的稱(chēng)謂Motion的操作節(jié)點(diǎn)(負(fù)責(zé)不同QE進(jìn)程間的數(shù)據(jù)交換)之外,總體上看,Greenplum Database的執(zhí)行器跟PostgreSQL的執(zhí)行器差別不大。
MPP數(shù)據(jù)庫(kù)在執(zhí)行查詢(xún)語(yǔ)句的時(shí)候,跟單機(jī)數(shù)據(jù)庫(kù)的一個(gè)重要差別在于,它會(huì)涉及到不同計(jì)算節(jié)點(diǎn)間的數(shù)據(jù)交換。在Greenplum Database系統(tǒng)架構(gòu)中,我們引入了Interconnect組件負(fù)責(zé)數(shù)據(jù)交換,作用類(lèi)似于MapReduce中的shuffling階段。不過(guò)與MapReduce基于HTTP協(xié)議不一樣,Greenplum Database出于數(shù)據(jù)傳輸效率和系統(tǒng)擴(kuò)展性方面的考慮,實(shí)現(xiàn)了基于UDP協(xié)議的數(shù)據(jù)交換組件。前面在解析執(zhí)行器的時(shí)候提到,Greenplum Database引入了一個(gè)叫Motion的操作節(jié)點(diǎn)。Motion操作節(jié)點(diǎn)就是通過(guò)Interconnect組件在不同的計(jì)算節(jié)點(diǎn)之間實(shí)現(xiàn)數(shù)據(jù)的重分布。
前面講到的解析器、優(yōu)化器、調(diào)度器、執(zhí)行器和Interconnect都是跟計(jì)算相關(guān)的組件,屬于無(wú)狀態(tài)組件。下面我們?cè)倏匆幌赂到y(tǒng)狀態(tài)相關(guān)的組件。首先是,系統(tǒng)表。系統(tǒng)表負(fù)責(zé)存儲(chǔ)和管理數(shù)據(jù)庫(kù)、表、字段等元數(shù)據(jù)。主節(jié)點(diǎn)上面的系統(tǒng)表是全局?jǐn)?shù)據(jù)庫(kù)對(duì)象的元數(shù)據(jù),稱(chēng)為全局系統(tǒng)表;每個(gè)Segment實(shí)例上也有一份本地?cái)?shù)據(jù)庫(kù)對(duì)象的元數(shù)據(jù),稱(chēng)為本地系統(tǒng)表。解析器、優(yōu)化器、調(diào)度器、執(zhí)行器和Interconenct等無(wú)狀態(tài)組件在運(yùn)行過(guò)程中需要訪問(wèn)系統(tǒng)表信息,決定執(zhí)行的邏輯。由于系統(tǒng)表分布式地存儲(chǔ)在不同的節(jié)點(diǎn)中,如何保持系統(tǒng)表中信息的一致性是極具挑戰(zhàn)的任務(wù)。一旦出現(xiàn)系統(tǒng)表不一致的情況,整個(gè)分布式數(shù)據(jù)庫(kù)系統(tǒng)是無(wú)法正常工作的。
跟很多分布式系統(tǒng)一樣,Greenplum Database是通過(guò)分布式事務(wù)來(lái)確保系統(tǒng)信息一致的,更確切地說(shuō),通過(guò)兩階段提交來(lái)確保系統(tǒng)元數(shù)據(jù)的一致性。主節(jié)點(diǎn)上的分布式事務(wù)管理器協(xié)調(diào)Segment節(jié)點(diǎn)上的提交和回滾操作。每個(gè)Segment實(shí)例有自己的事務(wù)日志,確定何時(shí)提交和回滾自己的事務(wù)。本地事務(wù)狀態(tài)保存在本地的事務(wù)日志中。
介紹完Greenplum Database的查詢(xún)組件和系統(tǒng)狀態(tài)組件后,我們?cè)倏纯此侨绾翁峁└呖捎眯缘摹J紫仁枪芾砉?jié)點(diǎn)的高可用。我們采取的方式是,啟動(dòng)一個(gè)稱(chēng)為Standby的從主節(jié)點(diǎn)作為主節(jié)點(diǎn)的備份,通過(guò)同步進(jìn)程同步主節(jié)點(diǎn)和Standby節(jié)點(diǎn)兩者的事務(wù)日志,在Standby節(jié)點(diǎn)上重做系統(tǒng)表的更新操作,從而實(shí)現(xiàn)兩者在全局系統(tǒng)表上面的信息同步。當(dāng)主節(jié)點(diǎn)出故障的時(shí)候,我們能夠切換到Standby節(jié)點(diǎn),系統(tǒng)繼續(xù)正常工作,從而實(shí)現(xiàn)管理節(jié)點(diǎn)的高可用。
計(jì)算節(jié)點(diǎn)高可用性的實(shí)現(xiàn)類(lèi)似于管理節(jié)點(diǎn),但是細(xì)節(jié)上有些小不同。每個(gè)Segment實(shí)例都會(huì)有另外一個(gè)Segment實(shí)例作為備份。處于正常工作狀態(tài)的Segment實(shí)例我們稱(chēng)為Primary,它的備份稱(chēng)為Mirror。不同于管理節(jié)點(diǎn)日志重放方式,計(jì)算節(jié)點(diǎn)的高可用是通過(guò)文件復(fù)制。對(duì)于每一個(gè)Segment實(shí)例,它的狀態(tài)以文件的形式保存在本地存儲(chǔ)介質(zhì)中。這些本地狀態(tài)可以分成三大類(lèi):本地系統(tǒng)表、本地事務(wù)日志和本地表分區(qū)數(shù)據(jù)。通過(guò)以文件復(fù)制的方式保證Primary和Mirror之間的狀態(tài)一致,我們能夠?qū)崿F(xiàn)計(jì)算節(jié)點(diǎn)的高可用。
HAWQHadoop出現(xiàn)之前,MPP數(shù)據(jù)庫(kù)是為數(shù)不多的大數(shù)據(jù)處理技術(shù)之一。隨著Hadoop的興起,特別是HDFS的成熟,越來(lái)越多的數(shù)據(jù)被保存在HDFS上面。一個(gè)自然的問(wèn)題出現(xiàn)了:我們?cè)鯓硬拍芨咝У胤治霰4嬖贖DFS上面的數(shù)據(jù),挖掘其中的價(jià)值。4,5年前,SQL-on-Hadoop遠(yuǎn)沒(méi)有現(xiàn)在這么火,市場(chǎng)上的解決方案也只有耶魯大學(xué)團(tuán)隊(duì)做的Hadapt和Facebook做的Hive,像Impala,Drill,Presto,SparkSQL等都是后來(lái)才出現(xiàn)的。而Hadapt和Hive兩個(gè)產(chǎn)品,在當(dāng)時(shí)無(wú)論是易用性還是查詢(xún)性能方面都差強(qiáng)人意。
我們當(dāng)時(shí)的想法是將Greenplum Database跟HDFS結(jié)合起來(lái)。與其他基于connector連接器的方式不同,我們希望讓HDFS,而不是本地存儲(chǔ),成為MPP數(shù)據(jù)庫(kù)的數(shù)據(jù)持久層。這就是后來(lái)的Apache HAWQ項(xiàng)目。但在當(dāng)時(shí),我們把它叫做Greenplum on Hadoop,其實(shí)更準(zhǔn)確的說(shuō)法應(yīng)該是,Greenplum on HDFS。當(dāng)時(shí)的想法非常簡(jiǎn)單,就是將Greenplum Database和HDFS部署在同一個(gè)物理機(jī)器集群中,同時(shí)將Greenplum Database中的Append-only表的數(shù)據(jù)放到HDFS上面。Append-only表指的是只能追加,不能更新和刪除的表,這是因?yàn)镠DFS本身只能Append的屬性決定的。
除了Append-only表之外,Greenplum Database還支持Heap表,這是一種能夠支持增刪改查的表類(lèi)型。結(jié)合前面提到的Segment實(shí)例的本地狀態(tài),我們可以將本地存儲(chǔ)分成四大類(lèi):系統(tǒng)表、日志、Append-only表分區(qū)數(shù)據(jù)和非Append-only表分區(qū)數(shù)據(jù)。我們將其中的Append-only表分區(qū)數(shù)據(jù)放到了HDFS上面。每個(gè)Segment實(shí)例對(duì)應(yīng)一個(gè)HDFS的目錄,非常直觀。其它三類(lèi)數(shù)據(jù)還是保存在本地的磁盤(pán)中。
總體上說(shuō),相對(duì)于傳統(tǒng)的Greenplum Database, Greenplum on HDFS架構(gòu)上并沒(méi)有太多的改動(dòng),只是將一部分?jǐn)?shù)據(jù)從本地存儲(chǔ)放到了HDFS上面,但是每個(gè)Segment實(shí)例還是需要通過(guò)本地存儲(chǔ)保存本地狀態(tài)數(shù)據(jù)。所以,從高可用性的角度看,我們還是需要為每個(gè)實(shí)例提供備份,只是需要備份的數(shù)據(jù)少了,因?yàn)锳ppend-only表的數(shù)據(jù)現(xiàn)在我們是通過(guò)HDFS本身的高可用性提供的。
Greenplum on HDFS作為一個(gè)原型系統(tǒng),驗(yàn)證了MPP數(shù)據(jù)庫(kù)和HDFS是可以很好地整合起來(lái)工作的。基于這個(gè)原型系統(tǒng),我們開(kāi)始將它當(dāng)成一個(gè)真正的產(chǎn)品來(lái)打造,也就是后來(lái)的HAWQ。
從Greenplum on HDFS到HAWQ,我們主要針對(duì)本地存儲(chǔ)做了系統(tǒng)架構(gòu)上的調(diào)整。我們希望將計(jì)算節(jié)點(diǎn)的本地狀態(tài)徹底去掉。本地狀態(tài)除了前面提到的系統(tǒng)表(系統(tǒng)表又可以細(xì)分成只讀系統(tǒng)表(系統(tǒng)完成初始化后不會(huì)再發(fā)生更改的元數(shù)據(jù),主要是數(shù)據(jù)庫(kù)內(nèi)置的數(shù)據(jù)類(lèi)型和函數(shù))和可寫(xiě)系統(tǒng)表(主要是通過(guò)DDL語(yǔ)句對(duì)元數(shù)據(jù)的修改,如創(chuàng)建新的數(shù)據(jù)庫(kù)和表))、事務(wù)日志、Append-only表分區(qū)數(shù)據(jù)和非Append-only表分區(qū)數(shù)據(jù),同時(shí)還有系統(tǒng)在執(zhí)行查詢(xún)過(guò)程中產(chǎn)生的臨時(shí)數(shù)據(jù),如外部排序時(shí)用到的臨時(shí)文件。其中臨時(shí)數(shù)據(jù)和本地只讀系統(tǒng)表的數(shù)據(jù)都是不需要持久化的。我們需要考慮的是如何在Segment節(jié)點(diǎn)上面移除另外四類(lèi)狀態(tài)數(shù)據(jù)。
Append-only表分區(qū)數(shù)據(jù)前面已經(jīng)提到過(guò),交給HDFS處理。為了提高訪問(wèn)HDFS的效率,我們沒(méi)有采用Hadoop自動(dòng)的HDFS訪問(wèn)接口,而是用C++實(shí)現(xiàn)了原生的HDFS訪問(wèn)庫(kù),libhdfs3。針對(duì)非Append-only表數(shù)據(jù)的問(wèn)題,我們的解決方案就比較簡(jiǎn)單粗暴了:通過(guò)修改DDL,我們徹底禁止用戶(hù)創(chuàng)建Heap表,因?yàn)镠eap表支持更新和刪除。所以,從那時(shí)起到現(xiàn)在最新的Apache HAWQ,都只支持表數(shù)據(jù)的追加,不支持更新和刪除。沒(méi)有了表數(shù)據(jù)的更新和刪除,分布式事務(wù)就變得非常簡(jiǎn)單了。通過(guò)為每個(gè)Append-only表文件對(duì)應(yīng)的元數(shù)據(jù)增加一列,邏輯EoF,即有效的文件結(jié)尾。只要能夠保證EoF的正確性,我們就能夠保證事務(wù)的正確性。而且Append-only表文件的邏輯EoF信息是保存在主節(jié)點(diǎn)的全局系統(tǒng)表中的,它的正確性通過(guò)主節(jié)點(diǎn)的本地事務(wù)保證。為了清理Append-only表文件在追加新數(shù)據(jù)時(shí)事務(wù)abort造成的臟數(shù)據(jù),我們實(shí)現(xiàn)了HDFS Truncate功能。
對(duì)于本地可寫(xiě)系統(tǒng)表,我們的做法是將Segment實(shí)例上面的本地可寫(xiě)系統(tǒng)表放到主節(jié)點(diǎn)的全局系統(tǒng)表中。這樣主節(jié)點(diǎn)就擁有了全局唯一的一份系統(tǒng)表數(shù)據(jù)。查詢(xún)執(zhí)行過(guò)程中需要用到的系統(tǒng)元數(shù)據(jù),我們通過(guò)Metadata Dispatch的方式和查詢(xún)計(jì)劃一起分發(fā)給每個(gè)Segment實(shí)例。
通過(guò)上述的一系列策略,我們徹底擺脫了Segment節(jié)點(diǎn)的本地狀態(tài),也就是實(shí)現(xiàn)了無(wú)狀態(tài)Segment。整個(gè)系統(tǒng)的高可用性策略就簡(jiǎn)單了很多,而且也不需要再為Segment節(jié)點(diǎn)提供Mirror了,系統(tǒng)的利用率大大提升。
數(shù)據(jù)的高可用交給了HDFS來(lái)保證。當(dāng)一個(gè)Segment節(jié)點(diǎn)出故障后,我們可以在任意一臺(tái)有空閑資源的機(jī)器上重新創(chuàng)始化一個(gè)新的Segment節(jié)點(diǎn),加入到集群中替代原來(lái)出故障的節(jié)點(diǎn),整個(gè)集群就能夠恢復(fù)正常工作。
我們也做到了計(jì)算和存儲(chǔ)物理上的解耦合,往徹底擺脫傳統(tǒng)MPP數(shù)據(jù)庫(kù)(例如Greenplum Database)計(jì)算和存儲(chǔ)緊耦合的目標(biāo)邁出了有著實(shí)質(zhì)意義的一步。
雖然在HAWQ 1.x的階段,我們做到了計(jì)算和存儲(chǔ)物理上的分離,但是邏輯上兩者還是集成的。原因是,在將本地表分區(qū)數(shù)據(jù)往HDFS上面遷移的時(shí)候,為了不改變?cè)瓉?lái)Segment實(shí)例的執(zhí)行邏輯流程,我們?yōu)槊總€(gè)Segment指定了一個(gè)其專(zhuān)有的HDFS目錄,以便跟原來(lái)本地?cái)?shù)據(jù)目錄一一對(duì)應(yīng)。每個(gè)Segment負(fù)責(zé)存儲(chǔ)和管理的數(shù)據(jù)都放在其對(duì)應(yīng)的目錄的底下,而且該目錄底下的文件,也只有它自身能夠訪問(wèn)。這種HDFS數(shù)據(jù)跟計(jì)算節(jié)點(diǎn)邏輯上的集成關(guān)系,使得HAWQ 1.x版本依然沒(méi)有擺脫傳統(tǒng)MPP數(shù)據(jù)庫(kù)剛性的并發(fā)執(zhí)行策略:無(wú)論查詢(xún)的復(fù)雜度如何,所有的計(jì)算節(jié)點(diǎn)都需要參與到每條查詢(xún)的執(zhí)行中。這意味著,系統(tǒng)執(zhí)行一條單行插入語(yǔ)句所使用的計(jì)算資源,和執(zhí)行一條對(duì)幾TB數(shù)據(jù)進(jìn)行復(fù)雜多表連接和聚合的語(yǔ)句所使用的資源是一樣的。這種剛性的并行執(zhí)行策略,極大地約束了系統(tǒng)的擴(kuò)展性和吞吐量,同時(shí)與Hadoop基于查詢(xún)復(fù)雜度來(lái)調(diào)度計(jì)算資源的彈性策略也是相違背的。
我們決心對(duì)HAWQ的系統(tǒng)架構(gòu)做一次大的調(diào)整,使其更加地Hadoop Native,Hadoop原生,而不僅僅是簡(jiǎn)單地將數(shù)據(jù)放到HDFS上面。當(dāng)時(shí),我們內(nèi)部成為HAWQ 2.0,也就是大家現(xiàn)在在github上面看到的Apache HAWQ。
其中最重要的一步是,我們希望計(jì)算和存儲(chǔ)不僅物理上分離,邏輯上也是分離。數(shù)據(jù)庫(kù)中的用戶(hù)表數(shù)據(jù)在HDFS上不再按照每個(gè)Segment多帶帶來(lái)組織,而是按照全局的數(shù)據(jù)庫(kù)對(duì)象來(lái)組織。舉個(gè)例子,我們將一張用戶(hù)表對(duì)應(yīng)的多個(gè)數(shù)據(jù)文件(因?yàn)楫?dāng)往該表插入數(shù)據(jù)的時(shí)候,為了提高數(shù)據(jù)插入的速度,系統(tǒng)會(huì)啟動(dòng)了多個(gè)QE進(jìn)程同時(shí)往HDFS寫(xiě)數(shù)據(jù),每個(gè)QE寫(xiě)一個(gè)多帶帶文件)放到同一個(gè)目錄底下,而不是像原來(lái)那樣,每個(gè)QE進(jìn)程將文件寫(xiě)到自己對(duì)應(yīng)的Segment目錄底下。這種改變帶來(lái)的一個(gè)直觀結(jié)果就是,由于所有文件的數(shù)據(jù)文件都放一起了,查詢(xún)執(zhí)行的時(shí)候,根據(jù)需要掃描的數(shù)據(jù)量不同,我們既可以使用一個(gè)Segment實(shí)例去完成表掃描操作,也可以使用多個(gè)Segment實(shí)例去做,徹底擺脫了原來(lái)只能使用固定個(gè)Segment實(shí)例來(lái)執(zhí)行查詢(xún)的剛性并行執(zhí)行策略。
當(dāng)然,HDFS數(shù)據(jù)目錄組織的改變只是實(shí)現(xiàn)HAWQ 2.0彈性執(zhí)行引擎的一步,但是卻是最重要的一步。計(jì)算和存儲(chǔ)的徹底分離,使得HAWQ可以像MapReduce一樣根據(jù)查詢(xún)的復(fù)雜度靈活地調(diào)度計(jì)算資源,極大地提升了系統(tǒng)的擴(kuò)展性和吞吐量。
我們簡(jiǎn)單比較一下HAWQ 1.x和HAWQ 2.0的資源調(diào)度。
左邊展現(xiàn)的是HAWQ 1.x在同時(shí)處理三個(gè)查詢(xún)(分別來(lái)自三個(gè)不同的會(huì)話)時(shí)的資源調(diào)度情況。與傳統(tǒng)的MPP數(shù)據(jù)庫(kù)一樣,無(wú)論查詢(xún)的復(fù)雜度怎樣,每個(gè)Segment實(shí)例都會(huì)參與到這條查詢(xún)的執(zhí)行中。換句話說(shuō),每個(gè)Segment實(shí)例都會(huì)啟動(dòng)一個(gè)QE進(jìn)程處理分配給它的任務(wù)。在這種情況下,系統(tǒng)能夠支持的并發(fā)查詢(xún)數(shù)量,跟集群的計(jì)算節(jié)點(diǎn)數(shù)沒(méi)有任何關(guān)系,完全由一個(gè)計(jì)算節(jié)點(diǎn)決定(這里,我們先不考慮主節(jié)點(diǎn)成為瓶頸的問(wèn)題)。一個(gè)4個(gè)節(jié)點(diǎn)的HAWQ集群能夠支持的并發(fā)查詢(xún)數(shù)量和一個(gè)400個(gè)節(jié)點(diǎn)的集群是一樣的。
右邊展現(xiàn)的是HAWQ 2.0在同樣并發(fā)查詢(xún)下的資源調(diào)度情況。和Hadoop的MapReduce一樣,我們能夠根據(jù)查詢(xún)的復(fù)雜度決定需要調(diào)度多少計(jì)算資源參與到每條查詢(xún)的執(zhí)行中。為了簡(jiǎn)化闡述,我們這里假設(shè)每條查詢(xún)只需要兩個(gè)計(jì)算資源單元。而且,執(zhí)行單元可以根據(jù)資源管理器的調(diào)度算法分配到不同的物理計(jì)算節(jié)點(diǎn)上面。這兩點(diǎn)靈活性:計(jì)算資源的數(shù)量可變和計(jì)算資源的位置可變,正是HAWQ 2.0彈性執(zhí)行引擎的核心。在這種情況下,系統(tǒng)能夠支持的并發(fā)查詢(xún)數(shù)量,跟集群的計(jì)算節(jié)點(diǎn)數(shù)量呈線性關(guān)系:計(jì)算節(jié)點(diǎn)越多,系統(tǒng)能夠支持的并發(fā)查詢(xún)數(shù)量越多(再次提醒,這里,我們先不考慮主節(jié)點(diǎn)成為瓶頸的問(wèn)題)。
所以,可以說(shuō),HAWQ 2.0成功解決了傳統(tǒng)MPP數(shù)據(jù)倉(cāng)庫(kù)中計(jì)算節(jié)點(diǎn)首先成為吞吐量瓶頸的問(wèn)題。同時(shí),由于并不是所有計(jì)算節(jié)點(diǎn)都需要參與到每條查詢(xún)的執(zhí)行中,HAWQ 2.0同時(shí)也解決了傳統(tǒng)MPP數(shù)據(jù)庫(kù)由于單個(gè)計(jì)算節(jié)點(diǎn)性能下降直接影響整個(gè)集群性能的問(wèn)題(這導(dǎo)致MPP集群不能包含太多的計(jì)算節(jié)點(diǎn),因?yàn)楦鶕?jù)概率,集群節(jié)點(diǎn)到達(dá)一定值后,出現(xiàn)單個(gè)計(jì)算節(jié)點(diǎn)性能下降的概率將會(huì)非常高),從而也很大程度上解決了擴(kuò)展性問(wèn)題。
云端數(shù)據(jù)倉(cāng)庫(kù)通過(guò)將計(jì)算和存儲(chǔ)徹底分離成功解決了計(jì)算節(jié)點(diǎn)成為系統(tǒng)吞吐量瓶頸的問(wèn)題后,現(xiàn)在系統(tǒng)的唯一瓶頸就剩下主節(jié)點(diǎn)。
如前面提到,主節(jié)點(diǎn)的功能主要分成兩類(lèi):元數(shù)據(jù)管理,包括系統(tǒng)表存儲(chǔ)和管理、鎖管理和分布式事務(wù)等等,和計(jì)算資源調(diào)度管理和執(zhí)行。前者我們可以看成是狀態(tài)管理,后者是沒(méi)有狀態(tài)的組件。通過(guò)將狀態(tài)管理提取出來(lái)成為多帶帶一個(gè)功能層,我們讓主節(jié)點(diǎn)跟計(jì)算節(jié)點(diǎn)一樣變得沒(méi)有狀態(tài)。這樣,我們能夠根據(jù)系統(tǒng)并發(fā)查詢(xún)的變化,動(dòng)態(tài)增加或者減少主節(jié)點(diǎn)的數(shù)量。這個(gè)設(shè)計(jì)借鑒了Hadoop YARN的設(shè)計(jì),將原來(lái)的Job Manager的功能分成了Resource Manager和Application Manager,從而解決Hadoop集群吞吐量的問(wèn)題。
這是一個(gè)云端數(shù)據(jù)倉(cāng)庫(kù)的架構(gòu)圖。其實(shí),我們?cè)贖ashData希望通過(guò)云端數(shù)據(jù)倉(cāng)庫(kù)解決企業(yè)用戶(hù)使用數(shù)據(jù)倉(cāng)庫(kù)時(shí)碰到的多種難題,包括商業(yè)上和技術(shù)上。在這里,我們只關(guān)注技術(shù)上的。
在這個(gè)系統(tǒng)架構(gòu)中,我們將管理即元數(shù)據(jù)、計(jì)算和存儲(chǔ)三者分離了,每一層都能多帶帶動(dòng)態(tài)伸縮,在解決系統(tǒng)吞吐量和擴(kuò)展性問(wèn)題的同時(shí),提供了多維度的彈性。
我們利用云平臺(tái)的對(duì)象存儲(chǔ)服務(wù),如AWS的S3和青云QingCloud的QingStor,作為系統(tǒng)數(shù)據(jù)的持久層。除了按需付費(fèi)的經(jīng)濟(jì)特性外,云平臺(tái)的對(duì)象存儲(chǔ)服務(wù)在可擴(kuò)展性、穩(wěn)定性和高可用性等方面遠(yuǎn)勝于我們自己維護(hù)的分布式文件系統(tǒng)(如HDFS)。雖然對(duì)象存儲(chǔ)的訪問(wèn)延遲遠(yuǎn)高于本地磁盤(pán)訪問(wèn),但是我們可以通過(guò)本地緩存的策略很大程度減輕延遲問(wèn)題。
同樣的,我們利用云平臺(tái)提供的虛擬機(jī)作為我們的計(jì)算資源,也能夠一定程度上實(shí)現(xiàn)資源的隔離,從而保證不同的工作負(fù)載之間沒(méi)有相互影響。
云平臺(tái)提供的近乎無(wú)限的計(jì)算和存儲(chǔ)資源(相對(duì)于數(shù)據(jù)倉(cāng)庫(kù)應(yīng)用來(lái)說(shuō)),使得云端數(shù)據(jù)倉(cāng)庫(kù)能夠存儲(chǔ)和處理的數(shù)據(jù)達(dá)到一個(gè)全新的高度。
總結(jié)最后,我們做一個(gè)簡(jiǎn)單的總結(jié)。從PostgreSQL到Greenplum Database,我們通過(guò)大規(guī)模并行處理(MPP)技術(shù),實(shí)現(xiàn)了處理海量數(shù)據(jù)時(shí)的低延遲目標(biāo)。從Greenplum Database到Apache HAWQ,通過(guò)計(jì)算和存儲(chǔ)分析的策略,我們提升了系統(tǒng)的并發(fā)處理能力和擴(kuò)展性。從Apache HAWQ到Cloud Data Warehouse,我們借助云平臺(tái)近乎無(wú)限的計(jì)算資源和存儲(chǔ)資源,以及管理、計(jì)算和數(shù)據(jù)三者分離,還有計(jì)算資源嚴(yán)格隔離,我們能夠取得近乎無(wú)限的并發(fā)處理能力和擴(kuò)展性。
MPP數(shù)據(jù)庫(kù)采取的是流水式的執(zhí)行引擎,中間的每個(gè)階段是不帶檢查點(diǎn)的。這意味著,只有有一個(gè)參與到查詢(xún)執(zhí)行的QE進(jìn)程出錯(cuò),整條查詢(xún)將會(huì)失敗,只能從頭開(kāi)始重新執(zhí)行這條查詢(xún)。而我們知道,當(dāng)參與到查詢(xún)執(zhí)行的QE進(jìn)程達(dá)到一定數(shù)量的時(shí)候,QE進(jìn)程出錯(cuò)將是必然的,特別是在一個(gè)資源共享的環(huán)境中。這時(shí)候,即使是重新提交查詢(xún)重跑,失敗還是必然的。換句話說(shuō),我們幾乎無(wú)法成功執(zhí)行需要調(diào)度大量計(jì)算資源的查詢(xún)。
展望未來(lái),我們希望實(shí)現(xiàn)帶檢查點(diǎn)的流水式執(zhí)行引擎,從而使得系統(tǒng)能夠處理任意大的查詢(xún)(單個(gè)查詢(xún)需要同時(shí)調(diào)度成千上萬(wàn)的計(jì)算資源)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/38972.html
摘要:本文作者是矛盾螺旋隊(duì)的成員劉瑋,他們的項(xiàng)目在中獲得了三等獎(jiǎng)。博康負(fù)責(zé)后端框架以及相應(yīng)的修改,我負(fù)責(zé)后端查詢(xún),振靖負(fù)責(zé)前端可視化。次日返回賽場(chǎng),抽簽確定時(shí)間,最終為第四個(gè)出場(chǎng)。 本文作者是矛盾螺旋隊(duì)的成員劉瑋,他們的項(xiàng)目?TiEye?在 TiDB Hackathon 2018 中獲得了三等獎(jiǎng)。TiEye 是?Region 信息變遷歷史可視化工具,通過(guò) PD記錄 Region 的Split...
閱讀 1428·2021-10-08 10:05
閱讀 3079·2021-09-26 10:10
閱讀 890·2019-08-30 15:55
閱讀 515·2019-08-26 11:51
閱讀 451·2019-08-23 18:10
閱讀 3870·2019-08-23 15:39
閱讀 672·2019-08-23 14:50
閱讀 777·2019-08-23 14:46