BigTable是谷歌設計的分布式數據存儲系統,用于處理大量的非結構化數據。它是一種高效、高可擴展的數據庫,基于Google檔案系統(GFS),適用于云端計算。BigTable不是傳統的關系型數據庫,不支持JOIN等SQL語法,而是更像今日的NoSQL的Table-oriented,優勢在于擴展性和性能。BigTable的表格數據結構包括row key、col key和timestamp,其中row key用于存儲倒轉的URL。BigTable使用大量的表,表之下還有表格(Tablets),每個Tablets大約有100-200MB,每臺機器有100個左右的Tablets。BigTable的表格是不可修改的SSTables,必須進行壓縮,分為表的壓縮或系統的壓縮。客戶端有一個指向META0的Tablets的指標,META0 tablets保存所有META1的tablets的數據記錄。
簡介
BigTable是非關系的數據庫,是一個稀疏的、分布式的、持久化存儲的多維度排序Map。Bigtable的設計目的是可靠的處理PB級別的數據,并且能夠部署到上千臺機器上。Bigtable已經實現了下面的幾個目標:適用性廣泛、可擴展、高性能和高可用性。Bigtable已經在超過60個谷歌的產品和項目上得到了應用,包括 Google Analytics、GoogleFinance、Orkut、Personalized Search、Writely和GoogleEarth。這些產品對Bigtable提出了迥異的需求,有的需要高吞吐量的批處理,有的則需要及時響應,快速返回數據給最終用戶。它們使用的Bigtable集群的配置也有很大的差異,有的集群只有幾臺服務器,而有的則需要上千臺服務器、存儲幾百TB的數據。
功能
在很多方面,Bigtable和數據庫很類似:它使用了很多數據庫的實現策略。并行數據庫【14】和內存數據庫【13】已經具備可擴展性和高性能,但是Bigtable提供了一個和這些系統完全不同的接口。Bigtable不支持完整的關系數據模型;與之相反,Bigtable為客戶提供了簡單的數據模型,利用這個模型,客戶可以動態控制數據的分布和格式(alex注:也就是對BigTable而言,數據是沒有格式的,用數據庫領域的術語說,就是數據沒有Schema,用戶自己去定義Schema),用戶也可以自己推測(alex注:reasonabout)底層存儲數據的位置相關性(alex注:位置相關性可以這樣理解,比如樹狀結構,具有相同前綴的數據的存放位置接近。在讀取的時候,可以把這些數據一次讀取出來)。數據的下標是行和列的名字,名字可以是任意的字符串。Bigtable將存儲的數據都視為字符串,但是Bigtable本身不去解析這些字符串,客戶程序通常會在把各種結構化或者半結構化的數據串行化到這些字符串里。通過仔細選擇數據的模式,客戶可以控制數據的位置相關性。最后,可以通過BigTable的模式參數來控制數據是存放在內存中、還是硬盤上。
特點:
1、適合大規模海量數據,PB級數據;
2、分布式、并發數據處理,效率極高;
3、易于擴展,支持動態伸縮;
4、適用于廉價設備;
5、適合于讀操作,不適合寫操作。
6、不適用于傳統關系數據庫;
應用:
BigTable為谷歌旗下的搜索、地圖、財經、打印、以及社交網站Orkut、視頻共享網站YouTube和博客網站Blogger等業務提供技術支持。
2010年9月,谷歌宣布將放棄MapReduce新索引系統將遷移至BigTable平臺。新平臺基于Colossus,也被稱為GFS2。
數據模型
Bigtable不是關系型數據庫,但是卻沿用了很多關系型數據庫的術語,像table(表)、row(行)、column(列)等。這容易讓讀者誤入歧途,將其與關系型數據庫的概念對應起來,從而難以理解。
本質上說,Bigtable是一個鍵值(key-value)映射。按作者的說法,Bigtable是一個稀疏的,分布式的,持久化的,多維的排序映射。
先來看看多維、排序、映射。Bigtable的鍵有三維,分別是行鍵(row key)、列鍵(column key)和時間戳(timestamp),行鍵和列鍵都是字節串,時間戳是64位整型;而值是一個字節串。可以用 (row:string, column:string, 時間:int64)→string 來表示一條鍵值對記錄。
行鍵可以是任意字節串,通常有10-100字節。行的讀寫都是原子性的。Bigtable按照行鍵的字典序存儲數據。Bigtable的表會根據行鍵自動劃分為片(tablet),片是負載均衡的單元。最初表都只有一個片,但隨著表不斷增大,片會自動分裂,片的大小控制在100-200MB。行是表的第一級索引,我們可以把該行的列、時間和值看成一個整體,簡化為一維鍵值映射,類似于:
table{
"1" : {sth.},//一行
"aaaaa" : {sth.},
"aaaab" : {sth.},
"xyz" : {sth.},
"zzzzz" : {sth.}
}
列是第二級索引,每行擁有的列是不受限制的,可以隨時增加減少。為了方便管理,列被分為多個列族(column family,是訪問控制的單元),一個列族里的列一般存儲相同類型的數據。一行的列族很少變化,但是列族里的列可以隨意添加刪除。列鍵按照family:qualifier格式命名的。這次我們將列拿出來,將時間和值看成一個整體,簡化為二維鍵值映射,類似于:
table{
// ...
"aaaaa" : { //一行
"A:foo" : {sth.},//一列
"A:勃朗寧自動步槍" : {sth.},//一列
"B:" : {sth.} //一列,列族名為B,但是列名是空字串
},
"aaaab" : { //一行
"A:foo" : {sth.},
"B:" : {sth.}
},
// ...
}
或者可以將列族當作一層新的索引,類似于:
table{
// ...
"aaaaa" : { //一行
"A" : { //列族A
"foo" : {sth.}, //一列
"bar" : {sth.}
},
"B" : { //列族B
"" : {sth.}
}
},
"aaaab" : { //一行
"A" : {
"foo" : {sth.},
},
"B" : {
"" : "ocean"
}
},
// ...
}
時間戳是第三級索引。Bigtable允許保存數據的多個版本,版本區分的依據就是時間戳。時間戳可以由Bigtable賦值,代表數據進入Bigtable的準確時間,也可以由客戶端賦值。數據的不同版本按照時間戳降序存儲,因此先讀到的是最新版本的數據。我們加入時間戳后,就得到了Bigtable的完整數據模型,類似于:
table{
// ...
"aaaaa" : { //一行
"A:foo" : { //一列
15 : "y", //一個版本
4 : "m"
},
"A:勃朗寧自動步槍" : { //一列
15 : "d",
},
"B:" : { //一列
6 : "w"
3 : "o"
1 : "w"
}
},
// ...
}
查詢時,如果只給出行列,那么返回的是最新版本的數據;如果給出了行列時間戳,那么返回的是時間小于或等于時間戳的數據。比如,我們查詢"aaaaa"/"A:foo",返回的值是"y";查詢"aaaaa"/"A:foo"/10,返回的結果就是"m";查詢"aaaaa"/"A:foo"/2,返回的結果是空。
Figure 1是Bigtable論文里給出的例子,Webtable表存儲了大量的網頁和相關信息。在Webtable,每一行存儲一個網頁,其反轉的url作為行鍵,比如”com.谷歌maps“,反轉的原因是為了讓同一個域名下的子域名網頁能聚集在一起。圖1中的列族"anchor"保存了該網頁的引用站點(比如引用了CNN主頁的站點),qualifier是引用站點的名稱,而數據是鏈接文本;列族"contents"保存的是網頁的內容,這個列族只有一個空列"contents:"。圖1中"contents:"列下保存了網頁的三個版本,我們可以用("com.cnn.www", "contents:", t5)來找到CNN主頁在t5時刻的內容。
再來看看作者說的其它特征:稀疏,分布式,持久化。持久化的意思很簡單,Bigtable的數據最終會以文件的形式放到GFS去。Bigtable建立在GFS之上本身就意味著分布式,當然分布式的意義并不僅限于此。稀疏的意思是,一個表里不同的行,列可能完完全全不一樣。
參考資料 >