閱讀291 返回首頁    go 阿裏雲 go 技術社區[雲棲]


Greenplum介紹

本文介紹了Greenplum的一些內部架構。

GP的官方文檔請參見:https://gpdb.docs.pivotal.io/4380/admin_guide/intro/arch_overview.html

阿裏雲GP的產品介紹參見:https://help.aliyun.com/document_detail/35387.html

由於後麵討論的所有的分布式數據庫,包括Greenplum Database是基於單機版關係型數據庫PostgreSQL的,所以我們首先簡單介紹一下PostgreSQL,作為後續討論的基礎。

PostgreSQL

screenshot

每個PostgreSQL數據庫的實例包含一個PostMaster的damon進程和多個子進程,包括負責寫出髒數據的BG Writer進程,收集統計信息的Stats Collector進程,寫事務日誌的WAL Writer進程,等等。

客戶端應用通過libpq協議連接到PostMaster進程;PostMaster收到連接請求後,fork出一個子進程Postgres Server來處理來自這個連接的查詢語句。Postgres Server進程的功能組件可以分成兩大類:查詢執行和存儲管理。查詢執行組件包括解析器、分析器、優化器以及執行器。在查詢執行過程中,需要訪問和更新係統狀態和數據,包括緩存,鎖,文件和頁麵等等。

Greenplum

screenshot

作為一個單機版的關係型數據庫,PostgreSQL更多地是作為聯機事務處理(OLTP)係統使用的。當然,由於其豐富的分析功能,很多企業也會基於PostgreSQL來構建數據倉庫,特別是在數據量不大的情況下。但是,隨著數據量的增大,基於單機PostgreSQL構建的數據倉庫就無法滿足企業用戶對查詢響應時間的要求:低延遲。

為了解決這個問題,MPP架構就被引入了。這是MPP架構分布式數據庫的簡單示意圖。MPP數據庫通過將數據切片分布到各個計算節點後並行處理來解決海量數據分析的難題。每個MPP數據庫集群由一個主節點(為了提供高可用性,通常還會有一個從主節點)和多個計算節點組成。主節點和每個計算節點都有自己獨立的CPU,內存和外部存儲。主節點負責接收客戶端的請求,生成查詢計劃,並將計劃下發到每個計算節點,協調查詢計劃的完成,最後匯總查詢結果返回給客戶端。計算節點負責數據的存儲以及查詢計劃的執行。計算節點之間是沒有任何共享依賴的(shared nothing)。查詢在每個計算節點上麵並行執行,大大提升了查詢的效率。

我們接下來要講的開源Greenplum Database就是基於PostgreSQL的MPP數據庫。對應到這個架構圖,每個節點上麵的數據庫實例可以簡單的認為是一個PostgreSQL實例。

screenshot

我們首先通過一條簡單的查詢,感性地認識一下Greenplum Database是如何執行一條查詢的。

這是一條簡單的兩表等值連接語句。其中,customer表是維度表,表數據以cust_id作為hash分布的key;sales表是事實表,在這個例子中,我們可以認為它的表數據是round-robin的方式隨機分布的,不影響查詢的執行。

每個查詢執行是一個由操作符組成的樹。隻看其中一個節點的話(如前麵所說,每個計算節點就是一個PostgreSQL的實例),為了執行兩表的等值連接,我們首先會將兩表的數據分別掃描出來,然後基於維度表customer建立hash桶。對於每一條從sales表掃描出來的紀錄,我們都會到hash桶去查。如果滿足匹配條件,數據連接結果;否則,直接pass。

如前麵提到的,在Greenplum Database中,每張表的數據按照hash分布或者隨機分布打散到每個計算節點上麵。在這個例子中,由於sales表是隨機分布的,為了正確執行基於cust_id的等值連接,生成的執行計劃會在table scan上麵添加一個Redistribution motion節點。這個motion節點根據cust_id的hash值對數據作重分布,類似MapReduce中的shuffling。由於hash join操作是在每個節點上麵分布式執行的,在將結果返回給客戶端的時候,需要在主節點上麵執行匯總操作。Gather motion的作用就在於將每個節點上麵的中間結果集中到主節點上麵。

對於這樣一個並行的查詢計劃,我們會根據數據重分布的操作將整棵查詢執行樹切割成不同的子樹。每個子樹對應查詢計劃的一個階段,我們稱為slice。查詢計劃和slice是邏輯上的概念。

screenshot

在物理層麵,對應的是並行執行計劃和gang。gang指的是執行同一個slice操作的一組進程。MPP數據庫的一個重要特征是,計算和存儲是緊耦合的。每一張表的數據打散存儲到每個計算節點上麵。為了確保查詢結果的正確性,每個計算節點都需要參與每條查詢的執行中。在Greenplum Database的架構設計中,對於每個slice執行子樹,在每個計算節點中會啟動一個相應的Postgres Server進程(這裏稱為QE進程)來執行對應的操作。執行同一個slice的一組QE進程我們稱為gang。對應於查詢計劃中的三個slice,在執行計劃中,相應有三組gang。其中底下的兩個gang,我們稱之為N-gang,因為這種類型的gang中,包含了每個計算節點上麵啟動的一個QE進程。頂上的gang,我們稱之為1-gang,因為它隻包含了一個進程。

screenshot

一般來說,對於N張表的關聯操作,執行計劃中會包含2N個gang,其中1個1-gang,對應主節點上麵的進程;2N-1個N-gang,對應每個計算節點上麵啟動的2N-1個QE進程。在這2N-1個gang中,其中N個用於掃描N張表,中間N-1個gang用於兩表關聯。也就是說,對於一條涉及到N表關聯操作的查詢語句,我們需要在每個計算節點上麵啟動2N-1個QE進程。

很多用戶在評估Greenplum Database的並發數,也就是支持的最大同時運行的查詢數量,首先會擔心主節點會成為瓶頸,直觀原因是所有用戶連接請求都首先會到主節點。其實,從資源使用的角度看,計算節點會首先成為瓶頸。因為在執行涉及多表關聯的複雜查詢時,計算節點上麵啟動的進程數量會遠多於主節點。所以,Greenplum Database係統架構決定了它不能支持非常高的並發訪問。

screenshot

前麵我們簡單闡述了MPP分布式數據庫的架構,並通過一條簡單的查詢語句解釋了分布式的執行計劃。接下來我們深入討論一下Greenplum Database的重要組件。

首先是解析器。從使用者的角度看,Greenplum Database跟PostgreSQL沒有明顯差別。主節點作為整個分布式係統集群的大腦,負責接收客戶連接,處理請求。跟PostgreSQL一樣,對於每一個連接請求,Greenplum Database都會在主節點上麵fork一個Postgres Server(我們稱之為QD)進程出來,負責處理這個連接提交的查詢語句。對於每一條進來的查詢語句,QD進程中的解析器執行語法分析和詞法分析,生成解析樹。雖然在一些DDL語句上麵,Greenplum Database跟PostgreSQL會有一些語法上的小不同,例如建表語句可以指定數據進行hash分布的key,但總體上,在解析器這個組件上麵,兩者的差別不大。

screenshot

優化器根據解析器生成的解析樹,生成查詢計劃。查詢計劃描述了如何執行查詢。查詢計劃的優劣直接影響查詢的執行效率。對於同樣一條查詢語句,一個好的查詢執行效率比一個次好的查詢計劃快上100倍,也是一個很正常的事情。從PostgreSQL到MPP架構的Greenplum Database,優化器做了重大改動。雖然兩者都是基於代價來生成最優的查詢計劃,但是Greenplum Database除了需要常規的表掃描代價、連接和聚合的執行方式外,還需要考慮數據的分布式狀態、數據重分布的代價,以及集群計算節點數量對執行效率的影響,因為它最終是要生成一個分布式的查詢計劃。

screenshot

調度器是Greenplum Database在PostgreSQL上新增的一個組件,負責分配處理查詢需要的計算資源,將查詢計劃發送到每個計算節點。在Greenplum Database中,我們稱計算節點為Segment節點。前麵也提過,每一個Segment實例實際上就是一個PostgreSQL實例。調度器根據優化器生成的查詢計劃確定執行計劃需要的計算資源,然後通過libpg(修改過的libpg協議)協議給每個Segment實例發送連接請求,通過Segment實例上的PostMaster進程fork出前麵提到過的QE進程。調度器同時負責這些fork出來的QE進程的整個生命周期。

screenshot

每個QE進程接收到從調度器發送過來的查詢計劃之後,通過執行器執行分配給自己的任務。除了增加一個新的稱謂Motion的操作節點(負責不同QE進程間的數據交換)之外,總體上看,Greenplum Database的執行器跟PostgreSQL的執行器差別不大。

screenshot

MPP數據庫在執行查詢語句的時候,跟單機數據庫的一個重要差別在於,它會涉及到不同計算節點間的數據交換。在Greenplum Database係統架構中,我們引入了Interconnect組件負責數據交換,作用類似於MapReduce中的shuffling階段。不過與MapReduce基於HTTP協議不一樣,Greenplum Database出於數據傳輸效率和係統擴展性方麵的考慮,實現了基於UDP協議的數據交換組件。前麵在解析執行器的時候提到,Greenplum Database引入了一個叫Motion的操作節點。Motion操作節點就是通過Interconnect組件在不同的計算節點之間實現數據的重分布。

screenshot

前麵講到的解析器、優化器、調度器、執行器和Interconnect都是跟計算相關的組件,屬於無狀態組件。下麵我們再看一下跟係統狀態相關的組件。首先是,係統表。係統表負責存儲和管理數據庫、表、字段等元數據。主節點上麵的係統表是全局數據庫對象的元數據,稱為全局係統表;每個Segment實例上也有一份本地數據庫對象的元數據,稱為本地係統表。解析器、優化器、調度器、執行器和Interconenct等無狀態組件在運行過程中需要訪問係統表信息,決定執行的邏輯。由於係統表分布式地存儲在不同的節點中,如何保持係統表中信息的一致性是極具挑戰的任務。一旦出現係統表不一致的情況,整個分布式數據庫係統是無法正常工作的。

screenshot

跟很多分布式係統一樣,Greenplum Database是通過分布式事務來確保係統信息一致的,更確切地說,通過兩階段提交來確保係統元數據的一致性。主節點上的分布式事務管理器協調Segment節點上的提交和回滾操作。每個Segment實例有自己的事務日誌,確定何時提交和回滾自己的事務。本地事務狀態保存在本地的事務日誌中。

screenshot

介紹完Greenplum Database的查詢組件和係統狀態組件後,我們再看看它是如何提供高可用性的。首先是管理節點的高可用。我們采取的方式是,啟動一個稱為Standby的從主節點作為主節點的備份,通過同步進程同步主節點和Standby節點兩者的事務日誌,在Standby節點上重做係統表的更新操作,從而實現兩者在全局係統表上麵的信息同步。當主節點出故障的時候,我們能夠切換到Standby節點,係統繼續正常工作,從而實現管理節點的高可用。

計算節點高可用性的實現類似於管理節點,但是細節上有些小不同。每個Segment實例都會有另外一個Segment實例作為備份。處於正常工作狀態的Segment實例我們稱為Primary,它的備份稱為Mirror。不同於管理節點日誌重放方式,計算節點的高可用是通過文件複製。對於每一個Segment實例,它的狀態以文件的形式保存在本地存儲介質中。這些本地狀態可以分成三大類:本地係統表、本地事務日誌和本地表分區數據。通過以文件複製的方式保證Primary和Mirror之間的狀態一致,我們能夠實現計算節點的高可用。

(轉載自https://segmentfault.com/a/1190000007419222?from=timeline&isappinstalled=0,有刪改)

最後更新:2017-04-01 20:01:29

  上一篇:go 子晗博客
  下一篇:go document.createElement()和document.createDocumentFragment()的比較