1. 程式人生 > >谷歌三大核心技術(三)Google_BigTable中文版

谷歌三大核心技術(三)Google_BigTable中文版

谷歌三大核心技術(三)Google_BigTable中文版

Bigtable:一個分散式的結構化資料儲存系統

譯者:alex

摘要

Bigtable是一個分散式的結構化資料儲存系統,它被設計用來處理海量資料:通常是分佈在數千臺普通伺服器上的PB級的資料。Google的很多專案使用Bigtable儲存資料,包括Web索引、Google EarthGoogle Finance。這些應用對Bigtable提出的要求差異非常大,無論是在資料量上(從URL到網頁到衛星影象)還是在響應速度上(從後端的批量處理到實時資料服務)。儘管應用需求差異很大,但是,針對Google的這些產品,

Bigtable還是成功的提供了一個靈活的、高效能的解決方案。本論文描述Bigtable提供的簡單的資料模型,利用這個模型,使用者可以動態的控制資料的分佈和格式;我們還將描述Bigtable的設計和實現。

1 介紹

在過去兩年半時間裡,我們設計、實現並部署了一個分散式的結構化資料儲存系統Google,我們稱之為BigtableBigtable的設計目的是可靠的處理PB級別的資料,並且能夠部署到上千臺機器上。Bigtable經實現了下面的幾個目標:適用性廣泛、可擴充套件、高效能和高可用性。Bigtable已經在超過60Google的產品和專案上得到了應用,包括 Google Analytics

Google FinanceOrkutPersonalizedSearchWritelyGoogle Earth。這些產品對Bigtable提出了迥異的需求,有的需要高吞吐量的批處理,有的則需要及時響應,快速返回資料給終端使用者。它們使用的Bigtable叢集的配置也有很大的差異,有的叢集只有幾臺伺服器,而有的則需要上千臺伺服器、儲存幾百TB的資料。

在很多方面,Bigtable和資料庫很類似:它使用了很多資料庫的實現策略。並行資料庫【14】和記憶體資料庫【13】已經具備可擴充套件性和高效能,但是Bigtable提供了一個和這些系統完全不同的介面。Bigtable不支援完整的關係資料模型;與之相反,

Bigtable為客戶提供了簡單的數據模型,利用這個模型,客戶可以動態控制資料的分佈和格式alex注:也就是對BigTable而言,資料是沒有格式的,用資料庫領域的術語說,就是資料沒有Schema,使用者自己去定義Schema),使用者也可以自己推測(alex注:reasonabout)底層儲存資料的位置相關性(alex注:位置相關性可以這樣理解,比如樹狀結構,具有相同字首的資料的存放位置接近。在讀取的時候,可以把這些資料一次讀取出來)。資料的下標是行和列的名字,名字可以是任意的字串。Bigtable將儲存的資料都視為字串,但是Bigtable本身不去解析這些字串,客戶程式通常會在把各種結構化或者半結構化的資料序列化到這些字串裡。通過仔細選擇資料的模式,客戶可以控制資料的位置相關性。最後,可以通過BigTable的模式引數來控制資料是存放在記憶體中、還是硬碟上。

第二節描述關於資料模型更多細節方面的東西;第三節概要介紹了客戶端API;第四節簡要介紹了BigTable底層使用的Google的基礎框架;第五節描述了BigTable實現的關鍵部分;第6節描述了我們為了提高BigTable的效能採用的一些精細的調優方法;第7節提供了BigTable 的效能資料;第8節講述了幾個Google內部使用BigTable的例子;第9節是我們在設計和後期支援過程中得到一些經驗和教訓;最後,在第10節列出我們的相關研究工作,第11節是我們的結論。

2 資料模型

Bigtable是一個稀疏的、分散式的、持久化儲存的多維度排序Mapalex注:對於程式設計師來說,Map應該不用翻譯了吧。Mapkeyvalue組成,後面我們直接使用keyvalue,不再另外翻譯了)。Map的索引是行關鍵字、列關鍵字以及時間戳;Map中的每個value都是一個未經解析的byte陣列。

(row:string,column:string,time:int64)->string

我們在仔細分析了一個類似Bigtable的系統的種種潛在用途之後,決定使用這個資料模型。我們先舉個具體的例子,這個例子促使我們做了很多設計決策;假設我們想要儲存海量的網頁及相關資訊,這些資料可以用於很多不同的專案,我們姑且稱這個特殊的表為Webtable。在Webtable裡,我們使用URL作為行關鍵字,使用網頁的某些屬性作為列名,網頁的內容存在“contents:”列中,並用獲取該網頁的時間戳作為標識(alex注:即按照獲取時間不同,儲存了多個版本的網頁資料),如圖一所示。

圖一:一個儲存Web網頁的例子的表的片斷。行名是一個反向URLcontents列族存放的是網頁的內容,anchor列族存放引用該網頁的錨鏈接文字alex注:如果不知道HTMLAnchor,請Google一把)。CNN的主頁被Sports IllustraterMY-look的主頁引用,因此該行包含了名為“anchor:cnnsi.com” “anchhor:my.look.ca”的列。每個錨鏈接只有一個版本alex注:注意時間戳標識了列的版本,t9t8分別標識了兩個錨鏈接的版本);contents列則有三個版本,分別由時間戳t3t5,和t6標識。

表中的行關鍵字可以是任意的字串(目前支援最大64KB的字串,但是對大多數使用者,10-100個位元組就足夠了)。對同一個行關鍵字的讀或者寫操作都是原子的(不管讀或者寫這一行裡多少個不同列),這個設計決策能夠使使用者很容易的理解程式在對同一個行進行併發更新操作時的行為。

Bigtable通過行關鍵字的字典順序來組織資料。表中的每個行都可以動態分割槽。每個分割槽叫做一個”Tablet”Tablet資料分佈和負載均衡調整的最小單位。這樣做的結果是,當操作只讀取行中很少幾列的資料時效率很高,通常只需要很少幾次機器間的通訊即可完成。使用者可以通過選擇合適的行關鍵字,在資料訪問時有效利用資料的位置相關性,從而更好的利用這個特性。舉例來說,在Webtable裡,通過反轉URL中主機名的方式,可以把同一個域名下的網頁聚集起來組織成連續的行。具體來說,我們可以把maps.google.com/index.html的資料存放在關鍵字 com.google.maps/index.html下。把相同的域中的網頁儲存在連續的區域可以讓基於主機和域名的分析更加有效。

列族

列關鍵字組成的集合叫做列族,列族是訪問控制的基本單位。存放在同一列族下的所有資料通常都屬於同一個型別(我們可以把同一個列族下的資料壓縮在一起)。列族在使用之前必須先建立,然後才能在列族中任何的列關鍵字下存放資料;列族建立後,其中的任何一個列關鍵字下都可以存放資料。根據我們的設計意圖,一張表中的列族不能太多(最多幾百個),並且列族在執行期間很少改變。與之相對應的,一張表可以有無限多個列。

列關鍵字的命名語法如下:列族:限定詞。列族的名字必須是可列印的字串,而限定詞的名字可以是任意的字串。比如,Webtable有個列族languagelanguage 列族用來存放撰寫網頁的語言。我們在language列族中只使用一個列關鍵字,用來存放每個網頁的語言標識IDWebtable中另一個有用的列族是 anchor;這個列族的每一個列關鍵字代表一個錨鏈接,如圖一所示。Anchor列族的限定詞是引用該網頁的站點名;Anchor列族每列的資料項存放的是連結文字。

訪問控制、磁碟和記憶體的使用統計都是在列族層面進行的。在我們的Webtable的例子中,上述的控制權限能幫助我們管理不同型別的應用:我們允許一些應用可以新增新的基本資料、一些應用可以讀取基本資料並建立繼承的列族、一些應用則只允許瀏覽資料(甚至可能因為隱私的原因不能瀏覽所有資料)。

時間戳

Bigtable中,表的每一個數據項都可以包含同一份資料的不同版本;不同版本的資料通過時間戳來索引。Bigtable時間戳的型別是64整型。Bigtable可以給時間戳賦值,用來表示精確到毫秒的實時時間;使用者程式也可以給時間戳賦值。如果應用程式需要避免資料版本衝突,那麼它必須自己生成具有唯一性的時間戳。資料項中,不同版本的資料按照時間戳倒序排序,即最新的資料排在最前面。

為了減輕多個版本資料的管理負擔,我們對每一個列族配有兩個設定引數,Bigtable通過這兩個引數可以對廢棄版本的資料自動進行垃圾收集。使用者可以指定只儲存最後n個版本的資料,或者只儲存足夠新的版本的資料(比如,只儲存最近7天的內容寫入的資料)。

Webtable的舉例裡,contents:列儲存的時間戳資訊是網路爬蟲抓取一個頁面的時間。上面提及的垃圾收集機制可以讓我們只保留最近三個版本的網頁資料。

3 API

Bigtable提供了建立和刪除表以及列族的API函式。Bigtable還提供了修改叢集、表和列族的元資料的API,比如修改訪問許可權。

// Open the table

Table *T = OpenOrDie(“/bigtable/web/webtable”);

// Write a new anchor and delete an old anchor

RowMutation r1(T, “com.cnn.www”);

r1.Set(“anchor:www.c-span.org”, “CNN”);

r1.Delete(“anchor:www.abc.com”);

Operation op;

Apply(&op, &r1)

Figure 2: Writing to Bigtable.

客戶程式可以對Bigtable進行如下的操作:寫入或者刪除Bigtable中的值、從每個行中查詢值、或者遍歷表中的一個數據子集。圖2中的++程式碼使用RowMutation抽象物件進行了一系列的更新操作。(為了保持示例程式碼的簡潔,我們忽略了一些細節相關程式碼)。呼叫Apply函式對ebtable進行了一個原子修改操作:它為增加了一個錨點,同時刪除了另外一個錨點。

Scanner scanner(T);

ScanStream *stream;

stream = scanner.FetchColumnFamily(“anchor”);

stream->SetReturnAllVersions();

scanner.Lookup(“com.cnn.www”);

for (; !stream->Done(); stream->Next()) {

printf(“%s %s %lld %s\n”,

scanner.RowName(),

stream->ColumnName(),

stream->MicroTimestamp(),

stream->Value());

}

Figure3: Reading from Bigtable.

3中的C++程式碼使用Scanner抽象物件遍歷一個行內的所有錨點。客戶程式可以遍歷多個列族,有幾種方法可以對掃描輸出的行、列和時間戳進行限制。例如,我們可以限制上面的掃描,讓它只輸出那些匹配正則表示式*.cnn.com的錨點,或者那些時間戳在當前時間前10天的錨點。

Bigtable還支援一些其它的特性,利用這些特性,使用者可以對資料進行更復雜的處理。首先,Bigtable支援單行上的事務處理,利用這個功能,使用者可以對儲存在一個行關鍵字下的資料進行原子性的讀-更新-寫操作。雖然Bigtable提供了一個允許使用者跨行批量寫入資料的介面,但是,Bigtable目前還不支援通用的跨行事務處理。其次,Bigtable允許把資料項用做整數計數器。最後,Bigtable允許使用者在伺服器的地址空間內執行指令碼程式。指令碼程式使用Google開發的Sawzall28】資料處理語言。雖然目前我們基於的Sawzall語言的API函式還不允許客戶的指令碼程式寫入資料到Bigtable,但是它允許多種形式的資料轉換、基於任意表達式的資料過濾、以及使用多種操作符的進行資料彙總。

Bigtable可以和MapReduce12】一起使用,MapReduceGoogle開發的大規模平行計算框架。我們已經開發了一些Wrapper類,通過使用這些Wrapper類,Bigtable可以作為MapReduce框架的輸入和輸出。

Bigtable是建立在其它的幾個Google基礎構件上的。BigTable使用Google的分散式檔案系統(GFS)17】儲存日誌檔案和資料檔案。BigTable叢集通常執行在一個共享的機器池中,池中的機器還會執行其它的各種各樣的分散式應用程式,BigTable的程序經常要和其它應用的程序共享機器。BigTable依賴叢集管理系統來排程任務、管理共享的機器上的資源、處理機器的故障、以及監視機器的狀態。

BigTable內部儲存資料的檔案是GoogleSSTable格式的。SSTable是一個持久化的、排序的、不可更改的Map結構,而Map是一個key-value 對映的資料結構,keyvalue的值都是任意的Byte串。可以對SSTable進行如下的操作:查詢與一個key值相關的