sina
Bigtable 是一個(gè)分布式的結(jié)構(gòu)化數(shù)據(jù)存儲(chǔ)系統(tǒng),它被設(shè)計(jì)用來處理海量數(shù)據(jù):通常是分布在數(shù)千臺(tái)普通服務(wù)器上的PB 級(jí)的數(shù)據(jù)。Google 的很多項(xiàng)目使用Bigtable 存儲(chǔ)數(shù)據(jù),包括Web 索引、GoogleEarth、Google Finance。這些應(yīng)用對Bigtable 提出的要求差異非常大,無論是在數(shù)據(jù)量上(從URL到網(wǎng)頁到衛(wèi)星圖像)還是在響應(yīng)速度上(從后端的批量處理到實(shí)時(shí)數(shù)據(jù)服務(wù))。
Bigtable 已經(jīng)實(shí)現(xiàn)了下面的幾個(gè)目標(biāo):適用性廣泛、可擴(kuò)展、高性能和高可用性,Bigtable 是一個(gè)稀疏的、分布式的、持久化存儲(chǔ)的多維度排序Map。
圖一:一個(gè)存儲(chǔ)Web 網(wǎng)頁的例子的表的片斷。行名是一個(gè)反向URL。contents 列族存放的是網(wǎng)頁的內(nèi)容,anchor 列族存放引用該網(wǎng)頁的錨鏈接文本(alex 注:如果不知道HTML 的Anchor,請Google一把)。CNN 的主頁被Sports Illustrater和MY-look 的主頁引用,因此該行包含了名為“anchor:cnnsi.com”和“anchhor:my.look.ca”的列。每個(gè)錨鏈接只有一個(gè)版本(alex 注:注意時(shí)間戳標(biāo)識(shí)了列的版本,t9 和t8 分別標(biāo)識(shí)了兩個(gè)錨鏈接的版本);而contents 列則有三個(gè)版本,分別由時(shí)間戳t3,t5,和t6 標(biāo)識(shí)。
行
Bigtable 通過行關(guān)鍵字的字典順序來組織數(shù)據(jù)。表中的每個(gè)行都可以動(dòng)態(tài)分區(qū)。每個(gè)分區(qū)叫做一個(gè)”Tablet”,Tablet 是數(shù)據(jù)分布和負(fù)載均衡調(diào)整的最小單位。
列族
Webtable 有個(gè)列族language,language 列族用來存放撰寫網(wǎng)頁的語言。
我們在language 列族中只使用一個(gè)列關(guān)鍵字,用來存放每個(gè)網(wǎng)頁的語言標(biāo)識(shí)ID。Webtable 中另一個(gè)有用的列族是anchor;這個(gè)列族的每一個(gè)列關(guān)鍵字代表一個(gè)錨鏈接,如圖一所示。Anchor 列族的限定詞是引用該網(wǎng)頁的站點(diǎn)名;Anchor 列族每列的數(shù)據(jù)項(xiàng)存放的是鏈接文本。訪問控制、磁盤和內(nèi)存的使用統(tǒng)計(jì)都是在列族層面進(jìn)行的。
時(shí)間戳
不同版本的數(shù)據(jù)通過時(shí)間戳來索引。Bigtable 時(shí)間戳的類型是64 位整型。
Bigtable 可以給時(shí)間戳賦值,用來表示精確到毫秒的“實(shí)時(shí)”時(shí)間;用戶程序也可以給時(shí)間戳賦值。如果應(yīng)用程序需要避免數(shù)據(jù)版本沖突,那么它必須自己生成具有唯一性的時(shí)間戳。數(shù)據(jù)項(xiàng)中,不同版本的數(shù)據(jù)按照時(shí)間戳倒序排序,即最新的數(shù)據(jù)排在最前面。為了減輕多個(gè)版本數(shù)據(jù)的管理負(fù)擔(dān),我們對每一個(gè)列族配有兩個(gè)設(shè)置參數(shù), Bigtable 通過這兩個(gè)參數(shù)可以對廢棄版本的數(shù)據(jù)自動(dòng)進(jìn)行垃圾收集。用戶可以指定只保存最后n 個(gè)版本的數(shù)據(jù),或者只保存“足夠新”的版本的數(shù)據(jù)(比如,只保存最近7 天的內(nèi)容寫入的數(shù)據(jù))。
Bigtable支持的其他特性
1、Bigtable 支持單行上的事務(wù)處理,利用這個(gè)功能,用戶可以對存儲(chǔ)在一個(gè)行關(guān)鍵字下的數(shù)據(jù)進(jìn)行原子性的讀-更新-寫操作。
2、Bigtable 允許把數(shù)據(jù)項(xiàng)用做整數(shù)計(jì)數(shù)器。
3、Bigtable 允許用戶在服務(wù)器的地址空間內(nèi)執(zhí)行腳本程序
4、Bigtable 可以和MapReduce一起使用,MapReduce 是Google 開發(fā)的大規(guī)模并行計(jì)算框架。我們已經(jīng)開發(fā)了一些Wrapper 類,通過使用這些Wrapper 類,Bigtable 可以作為MapReduce 框架的輸入和輸出。
Bigtable依賴于google的幾項(xiàng)技術(shù)。用GFS來存儲(chǔ)日志和數(shù)據(jù)文件;按SSTable文件格式存儲(chǔ)數(shù)據(jù);用Chubby管理元數(shù)據(jù):
Bigtable是建立在其它的幾個(gè)Google基礎(chǔ)構(gòu)件上的。BigTable 使用Google 的分布式文件系統(tǒng)(GFS)存儲(chǔ)日志文件和數(shù)據(jù)文件。BigTable 集群通常運(yùn)行在一個(gè)共享的機(jī)器池中,池中的機(jī)器還會(huì)運(yùn)行其它的各種各樣的分布式應(yīng)用程序,BigTable 的進(jìn)程經(jīng)常要和其它應(yīng)用的進(jìn)程共享機(jī)器。BigTable 依賴集群管理系統(tǒng)來調(diào)度任務(wù)、管理共享的機(jī)器上的資源、處理機(jī)器的故障、以及監(jiān)視機(jī)器的狀態(tài)。
BigTable 內(nèi)部存儲(chǔ)數(shù)據(jù)的文件是Google SSTable 格式的。SSTable 是一個(gè)持久化的、排序的、不可更改的Map 結(jié)構(gòu),而Map 是一個(gè)key-value 映射的數(shù)據(jù)結(jié)構(gòu),key 和value 的值都是任意的Byte串,從內(nèi)部看,SSTable 是一系列的數(shù)據(jù)塊(通常每個(gè)塊的大小是64KB,這個(gè)大小是可以配置的)。。SSTable 使用塊索引(通常存儲(chǔ)在SSTable 的最后)來定位數(shù)據(jù)塊;在打開SSTable的時(shí)候,索引被加載到內(nèi)存。每次查找都可以通過一次磁盤搜索完成:首先使用二分查找法在內(nèi)存中的索引里找到數(shù)據(jù)塊的位置,然后再從硬盤讀取相應(yīng)的數(shù)據(jù)塊。也可以選擇把整個(gè)SSTable 都放在內(nèi)存中,這樣就不必訪問硬盤了。
BigTable 還依賴一個(gè)高可用的、序列化的分布式鎖服務(wù)組件,叫做Chubby。Chubby有五個(gè)活躍副本,同時(shí)只有一個(gè)主副本提供服務(wù),副本之間用Paxos算法維持一致性,Chubby提供了一個(gè)命名空間(包括一些目錄和文件),每個(gè)目錄和文件就是一個(gè)鎖,Chubby的客戶端必須和Chubby保持會(huì)話,客戶端的會(huì)話若過期則會(huì)丟失所有的鎖。
Bigtable 包括了三個(gè)主要的組件:鏈接到客戶程序中的庫、一個(gè)Master主服務(wù)器和多個(gè)Tablet片 服務(wù)器。
Bigtable會(huì)將表(table)進(jìn)行分片,片(tablet)的大小維持在100-200MB范圍,一旦超出范圍就將分裂成更小的片,或者合并成更大的片。每個(gè)片服務(wù)器負(fù)責(zé)一定量的片,處理對其片的讀寫請求,以及片的分裂或合并。片服務(wù)器可以根據(jù)負(fù)載隨時(shí)添加和刪除。這里片服務(wù)器并不真實(shí)存儲(chǔ)數(shù)據(jù),而相當(dāng)于一個(gè)連接Bigtable和GFS的代理,客戶端的一些數(shù)據(jù)操作都通過片服務(wù)器代理間接訪問GFS。主服務(wù)器負(fù)責(zé)將片分配給片服務(wù)器,監(jiān)控片服務(wù)器的添加和刪除,平衡片服務(wù)器的負(fù)載,處理表和列族的創(chuàng)建等。注意,主服務(wù)器不存儲(chǔ)任何片,不提供任何數(shù)據(jù)服務(wù),也不提供片的定位信息。
客戶端需要讀寫數(shù)據(jù)時(shí),直接與片服務(wù)器聯(lián)系。因?yàn)榭蛻舳瞬⒉恍枰獜闹鞣?wù)器獲取片的位置信息,所以大多數(shù)客戶端從來不需要訪問主服務(wù)器,主服務(wù)器的負(fù)載一般很輕。
Master 服務(wù)器主要負(fù)責(zé)以下工作:為Tablet 服務(wù)器分配Tablets、檢測新加入的或者過期失效的Table 服務(wù)器、對Tablet 服務(wù)器進(jìn)行負(fù)載均衡、以及對保存在GFS 上的文件進(jìn)行垃圾收集。除此之外,它還處理對模式的相關(guān)修改操作,例如建立表和列族。
我們使用一個(gè)三層的、類似B+樹的結(jié)構(gòu)存儲(chǔ)Tablet 的位置信息。
第一層是一個(gè)存儲(chǔ)在Chubby 中的文件,它包含了Root Tablet 的位置信息。這個(gè)Chubby文件屬于Chubby服務(wù)的一部分,一旦Chubby不可用,就意味著丟失了root tablet的位置,整個(gè)Bigtable也就不可用了。
第二層是root tablet。root tablet其實(shí)是元數(shù)據(jù)表(METADATA table)的第一個(gè)分片,它保存著元數(shù)據(jù)表其它片的位置。root tablet很特別,為了保證樹的深度不變,root tablet從不分裂。
第三層是其它的元數(shù)據(jù)片,它們和root tablet一起組成完整的元數(shù)據(jù)表。每個(gè)元數(shù)據(jù)片都包含了許多用戶片的位置信息。
片的數(shù)據(jù)最終還是寫到GFS里的,片在GFS里的物理形態(tài)就是若干個(gè)SSTable文件。下圖展示了讀寫操作基本情況。
BigTable和GFS的關(guān)系
集群包括主服務(wù)器和片服務(wù)器,主服務(wù)器負(fù)責(zé)將片分配給片服務(wù)器,而具體的數(shù)據(jù)服務(wù)則全權(quán)由片服務(wù)器負(fù)責(zé)。但是不要誤以為片服務(wù)器真的存儲(chǔ)了數(shù)據(jù)(除了內(nèi)存中memtable的數(shù)據(jù)),數(shù)據(jù)的真實(shí)位置只有GFS才知道,主服務(wù)器將片分配給片服務(wù)器的意思應(yīng)該是,片服務(wù)器獲取了片的所有SSTable文件名,片服務(wù)器通過一些索引機(jī)制可以知道所需要的數(shù)據(jù)在哪個(gè)SSTable文件,然后從GFS中讀取SSTable文件的數(shù)據(jù),這個(gè)SSTable文件可能分布在好幾臺(tái)chunkserver上。
一個(gè)簡化的Bigtable結(jié)構(gòu)圖:
結(jié)構(gòu)圖以Webtable表為例,表中存儲(chǔ)了網(wǎng)易、百度和豆瓣的幾個(gè)網(wǎng)頁。當(dāng)我們想查找百度貼吧昨天的網(wǎng)頁內(nèi)容,可以向Bigtable發(fā)出查詢Webtable表的(com.baidu.tieba, contents:, yesterday)。
假設(shè)客戶端沒有該緩存,那么Bigtable訪問root tablet的片服務(wù)器,希望得到該網(wǎng)頁所屬的片的位置信息在哪個(gè)元數(shù)據(jù)片中。使用METADATA.Webtable.com.baidu.tieba為行鍵在root tablet中查找,定位到最后一個(gè)比它大的是METADATA.Webtable.com.baidu.www,于是確定需要的就是元數(shù)據(jù)表的片A。訪問片A的片服務(wù)器,繼續(xù)查找Webtable.com.baidu.tieba,定位到Webtable.com.baidu.www是比它大的,確定需要的是Webtable表的片B。訪問片B的片服務(wù)器,獲得數(shù)據(jù)。
這里需要注意的是,每個(gè)片實(shí)際都由若干SSTable文件和memtable組成,而且這些SSTable和memtable都是已排序的。這就導(dǎo)致查找片B時(shí),可能需要將所有SSTable和memtable都查找一遍;另外客戶端應(yīng)該不會(huì)直接從元數(shù)據(jù)表獲得SSTable的文件名,而只是獲得片屬于片服務(wù)器的信息,通過片服務(wù)器為代理訪問SSTable。