/* 版權聲明:能夠隨意轉載,轉載時請務必標明文章原始出處和作者信息 .*/
author: 張俊林
節選自《大數據日知錄:架構與算法》十四章。書籍文件夾在此
Pregel是Google提出的大規模分布式圖計算平台,專門用來解決網頁鏈接分析、社交數據挖掘等實際應用中涉及的大規模分布式圖計算問題。
1.計算模型
Pregel在概念模型上遵循BSP模型。整個計算過程由若干順序運行的超級步(Super Step)組成,系統從一個“超級步”邁向下一個“超級步”,直到達到算法的終止條件(見圖14-13)。
Pregel在編程模型上遵循以圖節點為中心的模式,在超級步S中。每一個圖節點能夠匯總從超級步S-1中其它節點傳遞過來的消息,改變圖節點自身的狀態。並向其它節點發送消息。這些消息經過同步后。會在超級步S+1中被其它節點接收並做出處理。用戶僅僅須要自己定義一個針對圖節點的計算函數F(vertex),用來實現上述的圖節點計算功能。至於其它的任務,比方任務分配、任務管理、系統容錯等都交由Pregel系統來實現。
典型的Pregel計算由圖信息輸入、圖初始化操作,以及由全局同步點分割開的連續運行的超級步組成,最后可將計算結果進行輸出。
每一個節點有兩種狀態:活躍與不活躍,剛開始計算的時候,每一個節點都處於活躍狀態,隨着計算的進行,某些節點完畢計算任務轉為不活躍狀態,假設處於不活躍狀態的節點接收到新的消息,則再次轉為活躍,假設圖中全部的節點都處於不活躍狀態,則計算任務完畢,Pregel輸出計算結果。
以下以一個詳細的計算任務來作為Pregel圖計算模型的實例進行介紹,這個任務要求將圖中節點的最大值傳播給圖中全部的其它節點,圖14-14是其示意圖,圖中的實線箭頭表明了圖的鏈接關系,而圖中節點內的數值代表了節點的當前數值,圖中虛線代表了不同超級步之間的消息傳遞關系,同一時候,帶有斜紋標記的圖節點是不活躍節點。
從圖中能夠看出。數值6是圖中的最大值。在第0步超級步中,全部的節點都是活躍的,系統運行用戶函數F(vertex):節點將自身的數值通過鏈接關系傳播出去,接收到消息的節點選擇當中的最大值,並和自身的數值進行比較,假設比自身的數值大。則更新為新的數值。假設不比自身的數值大,則轉為不活躍狀態。
在第0個超級步中,每一個節點都將自身的數值通過鏈接傳播出去,系統進入第1個超級步。運行F(vertex)函數。第一行和第四行的節點由於接收到了比自身數值大的數值。所以更新為新的數值6。
第二行和第三行的節點沒有接收到比自身數值大的數,所以轉為不活躍狀態。
在運行完函數后。處於活躍狀態的節點再次發出消息。系統進入第2個超級步。第二行節點本來處於不活躍狀態。由於接收到新消息。所以更新數值到6。又一次處於活躍狀態,而其它節點都進入了不活躍狀態。Pregel進入第3個超級步,全部的節點處於不活躍狀態,所以計算任務結束,這樣就完畢了整個任務,最大數值通過4個超級步傳遞給圖中全部其它的節點。
算法14.1是體現這一過程的Pregel C++代碼。

2.系統架構
Pregel採用了“主從結構”來實現總體功能,圖14-15是其架構圖,當中一台server充當“主控server”,負責整個圖結構的任務切分,採用“切邊法”將其分割成子圖(Hash(ID)=ID mod n ,n是工作server個數)。並把任務分配給眾多的“工作server”,“主控server”命令“工作server”進行每一個超級步的計算。並進行障礙點同步和收集計算結果。“主控server”僅僅進行系統管理工作,不負責詳細的圖計算。
每台“工作server”負責維護分配給自己的子圖節點和邊的狀態信息,在運算的最初階段。將全部的圖節點狀態置為活躍狀態,對於眼下處於活躍狀態的節點依次調用用戶定義函數F(Vertex)。
須要說明的是。全部的數據都是載入到內存進行計算的。除此之外,“工作server”還管理本機子圖和其它“工作server”所維護子圖之間的通信工作。
在興許的計算過程中,“主控server”通過命令通知“工作server”開始一輪超級步的運算。“工作server”依次對活躍節點調用F(Vertex),當全部的活躍節點運算完畢,“工作server”通知“主控server”本輪計算結束后剩余的活躍節點數,直到全部的圖節點都處於非活躍狀態為止。計算到此結束。
Pregel採用“檢查點”(CheckPoint)作為其容錯機制。
在超級步開始前,“主控server”能夠命令“工作server”將其負責的數據分片內容寫入存儲點。內容包含節點值、邊值以及節點相應的消息。
“主控server”通過心跳監測的方式監控“工作server”的狀態。當某台“工作server”發生問題時。“主控server”將其負責的相應數據分片又一次分配給其它“工作server”,接收又一次計算任務的“工作server”從存儲點讀出相應數據分片的近期“檢查點”以恢復工作。“檢查點”所處的超級步可能比方今系統所處的超級步慢若干步。此時,全部的“工作server”回退到與“檢查點”一致的超級步又一次開始計算。
從上述描寫敘述能夠看出,Pregel是一個消息驅動的、遵循以圖節點為中心的編程模型的同步圖計算框架。
考慮到“主控server”的功能獨特性和物理唯一性。非常明顯,Pregel存在單點失效的可能。
請思考:在容錯周期選擇方面,每一輪超級步都能夠進行一次,也能夠選擇相隔若干超級步進行一次,那么這兩種做法各自有何優缺點?
解答:假設選擇較短周期的容錯措施,在完畢任務的過程中。須要的額外開銷會較多,可是優點在於假設機器發生問題,整個系統回退歷史較近,有利於任務盡快完畢;較長周期的容錯措施正好相反,由於頻次低。所以尋常開銷小,可是假設機器發生問題,則須要回退較多的超級步。導致拉長任務的運行過程。
所以這里也有一個總體的權衡。
3.Pregel應用
本節通過若干常見的圖計算應用,來說明Pregel框架下怎樣構造詳細的應用程序。
(1)PageRank計算
PageRank是搜索引擎排序中重要的參考因子,其基本思路和計算原理在本章前面有所說明。此處不再贅述。以下是利用Pregel進行PageRank計算的C++演示樣例代碼。
Compute()函數即為前面介紹的針對S超級步中圖節點的計算函數F(Vertex)。用戶通過繼承接口類Vertex並改寫Compute(MessageIterator* msgs)接口函數,就可以高速完畢應用開發。當中MessageIterator* msgs是S-1超級步傳遞給當前節點的消息隊列。該計算函數首先累加消息隊列中傳遞給當前節點的部分PageRank得分,之后依據計算公式得到圖節點當前的PageRank得分,假設當前超級步未達循環終止條件30次。則繼續將新的PageRank值通過邊傳遞給鄰接節點,否則發出結束通知。使得當前節點轉為不活躍狀態。
(2)單源最短路徑
在圖中節點間查找最短的路徑是非經常見的圖算法。所謂“單源最短路徑”,就是指給定初始節點StartV,計算圖中其它隨意節點到該節點的最短距離。以下是怎樣在Pregel平台下計算圖節點的單源最短路徑的C++代碼演示樣例。
從代碼中可看出,某個圖節點v從之前的超級步中接收到的消息隊列中查找眼下看到的最短路徑,假設這個值比節點v當前獲得的最短路徑小。說明找到更短的路徑,則更新節點數值為新的最短路徑,之后將新值通過鄰接節點傳播出去。否則將當前節點轉換為不活躍狀態。在計算完畢后,假設某個節點的最短路徑仍然標為INF,說明這個節點到源節點之間不存在可達通路。
(3)二部圖最大匹配
二部圖最大匹配也是經典的圖計算問題,以下給出Pregel利用隨機匹配思想解決該問題的一個思路。
上面的Pregel程序採用隨機匹配的方式來解決二部圖最大匹配問題。每一個圖節點維護一個二元組:('L/R',匹配節點ID),'L/R'指明節點是二部圖中的左端節點還是右端節點,以此作為身份識別標記。二元組的還有一維記載匹配上的節點ID。
算法運行經過以下四個階段。
階段一:對於二部圖中左端尚未匹配的節點。向其鄰接節點發出消息,要求進行匹配。之后轉入非活躍狀態。
階段二:對於二部圖中右端尚未匹配的節點。從接收到的請求匹配消息中隨機選擇一個接收。並向接收請求的左端節點發出確認信息,之后主動轉入非活躍狀態。
階段三:左端尚未匹配的節點接收到確認信息后,從中選擇一個節點接收,寫入匹配節點ID以表明已經匹配,然后向右端相應的節點發送接收請求的消息。左端節點已經匹配的節點在本階段不會有不論什么動作,由於這類節點在第一階段中根本就沒有發送不論什么消息。
階段四:右端尚未匹配的節點至多選擇一個階段三發過來的請求,然后寫入匹配節點ID以表明已經匹配。
通過上述相似於兩次握手的四個階段的不斷迭代,就可以獲得一個二部圖最大匹配結果。