下一代大規模增量索引平臺 – Percolator

本文作者:百度 劉景龍   原文刊登於《程序員》雜誌2011年第二期。覺得寫的非常好!所以轉過來跟大家分享分享!


下一代大規模增量索引平臺 – Percolator

 

簡介

繼google的3大基石GFS, MapReduce,BigTables之後,Google在10月份osdi會議上公佈了論文《Large-scale Incremental Processing Using Distributed Transactions and Notification》,介紹了他們最新的內容索引技術。這項技術是Google下一代內容索引系統Caffeine的核心。該框架在抓取網頁的同時進行對文檔的處理,將平均延遲降低爲原來的百分之一,平均文檔壽命(document age)降低50%。

 

傳統索引系統通常採用了多級索引的方式,按照網頁的重要性將網頁進行分級,分別按照小時,天,周對網頁庫進行更新。其特點是將網頁收錄到各級網頁庫時需要對全庫進行處理。這種模式最大的缺點是新產生的網頁或者信息不能被及時的收錄到網頁庫中,而且定期做全庫掃描也會造成計算資源的浪費。根源在於現有MapReduce框架對於網頁庫的處理粒度過粗,一次全庫的更新需要幾天的時間才能完成。針對這個問題Percolator細化了更新粒度,提供了對文檔的隨機訪問,實現了對單個文檔的處理,避免了MapReduce對全庫的遍歷。下面我們介紹下Percolator的設計及實現。

 

設計

在最初的Percolator設計中曾經考慮過直接使用BigTable存儲網頁庫,但是對於構建網頁庫而言,需要比BigTable行原子性更強的一致性語義。而BigTable的可擴展性,容錯以及負載均衡等設計是非常優秀的,爲了避免重新發明“輪子”,Percolator在BigTable基礎上,通過兩階段提交實現了跨行,跨表事務以及notifiication框架。

 

Percolator提供了對PB級網頁庫的隨機訪問功能。我們可以單獨的處理每一個頁面,從而避免使用mapreduce框架重建索引庫時對全庫的scan操作。此外爲了實現高吞吐以及高併發下的同步,Percolator支持ACID兼容的事務語義。

 

對增量索引系統而言除了用戶觸發的操作外,很多處理流程是數據觸發的。 Percolator中數據的變化,並且根據數據的變化進行觸發後續的一系列操作(比如:頁面解析,內容抽取等)。爲了滿足此需求,Percolator提供了notification語義。notification語義類似DBMS中的觸發器,當Percolator中的某個cell數據發生變化,就觸發應用開發者指定的Observer程序。一系列Observer程序通過“責任鏈”的方式級聯,並完成各自邏輯。

 

作爲一個基礎架構,Percolator繼承了BigTable的一致性和容錯模型,並且可以通過增加機器實現集羣的線性擴展。此外,它提供了友好的開發接口,使索引系統的開發者專注於頁面解析,抽取,分詞等算法的開發,而不必被分佈式系統中常見的一致性,容錯等問題所困擾。

 

                  圖1 Percolcator主要組件


如圖1所示,Percolcator是構建在GFS和BigTable之上,主要包含3個組件。 timestamp server,Percolcator worker,Chubby。
Timestamp server提供了統一時間的服務,它保證每次獲取的時間戳單調遞增,timestamp server會持久化時間戳,以保證服務重啓時時間戳的順序性。Chubby 服務提供了分佈式鎖服務,保證Percolcator在處理全局臨界資源時,可以互斥訪問。Percolcator worker是Percolator中的主要部分,實現了跨行/跨表事務和notification機制。爲獲得更好的吞吐量,Percolcator worker啓動了多個BigTable client對BigTable進行併發訪問。Percolcator worker不持久化任何數據,換言之每個Percolcator worker都是無狀態的,如果Percolator worker節點失效,Percolator client可以通過重試切換到另一個Percolator worker,從而不影響服務。


Percolator的設計主要針對大規模數據存儲,以及對網頁索引具有實時性更新需求的應用。相對於傳統的OLTP,Percolator沒有集中的事務管理機制,如果有機器在進行事務的過程中失效,失效事務中的鎖釋放是一件比較大的挑戰。由於Percolator用於網頁庫建索引這樣的線下服務,放鬆了對實時性的要求,採用一種延遲的方式清理鎖。

 

實現
Percolator提供了類似BigTable的用戶接口,Percolator中的cell通過BigTable中5列來表示。其中lock, write,data 3列用於實現Percolator事務的功能。Notify和ack_O這2列是爲了實現Percolator的notification機制。
下表爲Percolator在BigTable中的schema。

下面我們通過Percolator中的兩個主要的feature:事務和notification框架來介紹下Percolator的實現機制。


事務
Percolaor在BigTable的基礎上,提供了跨行,跨表的ACID語義。Percolator中的事務是通過傳統的兩階段提交實現。
下面我們用一個例子來說明Percolator是如何實現事務的。Bob賬戶中有$10, Joe 賬戶中有$2,Bob轉$7給Joe。

1. 初始狀態, joe賬戶有$2 ,Bob有$10 ;write 列中的 6:data @ 5 表示當前的數據寫入的時間戳是5;

2. 開始事務,在時間點7對Bob的賬戶加Primary lock並且向Bob賬戶寫入轉賬結果$3;

3. 在時間點7對joe的賬戶加secondary  lock,並且向joe賬戶寫入轉賬結果$9.(secondary lock列中包含對primary lock的引用,row key爲Bob);

4. 事務提交的第一階段, 提交 primary, 移除lock 列的內容,在 write 列寫入事務commit點的時間戳;

5. 事務提交的第二階段,在Joe行中刪除secondary lock,並且在Joe行寫入commit點的時間戳;

 

      Percolator就是通過以上5步完成事務的兩階段提交。對於分佈式事務來講,由於沒有集中事務管理機制,其較大的困難就是在處理事務的過程中,Percolator client如果出現異常crash,如何清除已有的鎖並重新使用被加鎖的行。


      Percolator採用的是比較消極的鎖釋放機制。如果事務A在執行的過程中,Percolator client crash掉了,Percolator 並不會主動釋放事務A所佔有的鎖。如果事務B 在進行的過程中,使用到了事務A佔有的數據,則由事務B負責鎖的釋放。

     此時,有件比較棘手的事情就是:我們應當如何區分事務A是由於Percolator client crash導致不能完成,還是事務A長時間處於commit 的狀態。爲了避免此類競態條件,我們需要一種鎖機制來同步應該執行事務B cleanup任務或者事務A的commit任務。由於BigTable能夠保證行的原子性,Percolator 很自然的使用BigTable的一個cell作爲鎖(稱爲primary lock),先搶到primary lock的則可以執行,否則退出。


Notification機制
      粗略的講,Notification機制類似於DBMS中的觸發器,即用戶對cell的修改都會觸發觀察該cell的程序(我們把這個程序稱爲”Observer”)。多個Observer組成一個”責任鏈”,當被觀察的cell被修改的時候,Observer鏈上的全部Observer將被觸發。
      在實現上,爲了能夠及時發現被修改的cell,Percolator在其每一行中增加了一個BigTable列notify,用於標識被修改且沒有觸發執行Observer的cell。爲了發現被標識爲notify的cell,每個Percolator worker都會隨機選取tablet,並進行scan。對於被標識爲notify的dirty cell,則觸發observer鏈。爲了避免多個worker同時scan相同的tablet,worker使用分佈式鎖服務(Chubby)在開始scan一個tablet的時候對tablet進行加鎖。對於網頁庫而言,這種週期性的對全表上P級數據進行scan是一個非常低效的操作,爲了對其優化減少每次scan的數據量,Percolator利用了BigTable按列存儲的優勢,將notify列指定爲單獨的locality group,保證worker只對notify列進行scan,避免了全表掃描造成的對多餘數據的加載。

 

       此外,爲了區分已被觸發的Observer,Percolator增加了列ack_O,(表示名字爲O的Observer對應的ack),該列的內容爲對應Observer的最後啓動時間。當被觀察的列被修改,Percolator啓動一個事務來處理notification。該事務讀取被觀察的列以及其相關聯的ack列,如果該column最後寫時間大於ack_O中的時間戳,則認爲該column對應的Observer需要被觸發。否則,認爲Observer已經被觸發。


 在Notification機制的實現上需要考慮以下幾個重要問題:
1. 如何防止多個notification事務的無限循環?
2. 如果多個notification事務觸發了對同一個cell的修改,如何避免併發修改造成的正確性問題?


      對於問題1當前Percolator實現中並未對notification事務的無限循環進行檢測和防止,所以應用開發者必須在Observer開發中警惕此種情況,避免notification循環的出現。
      對於問題2,Percolator的解決方法是使每一個被觸發的Observer爲一個事務,如果啓動了多個Observer,同時修改一個cell,則事務鎖機制可以避免重複修改引入的正確性問題。

 

總結
     本文簡單介紹了下一代大規模增量索引平臺-Percolator所要解決的問題,實現的方法。該平臺構建在Big Table和GFS上,利用了GFS的數據安全,BigTable的行原子性,負載均衡以及服務容錯等優越特性,提供了穩定,可擴展的增量索引構建平臺,並且相對於傳統索引技術而言,帶來了搜索結果的實時性和集羣資源利用率的全面提升。在一窺Google基礎架構的同時,我們可喜的看到,作爲Percolator中最主要的2大功能的身影已經出現在HBase社區的開發計劃中(Transaction和Coprocessor),下一代大規模增量索引平臺離我們並不遙遠。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章