Bigtable不是关系型数据库,但是却沿用了很多关系型数据库的术语,像table(表)、row(行)、column(列)等。这容易让读者误入歧途,将其与关系型数据库的概念对应起来,从而难以理解论文。Understanding HBase and BigTable是篇很优秀的文章,可以帮助读者从关系型数据模型的思维定势中走出来。
本质上说,Bigtable是一个键值(key-value)映射。按作者的说法,Bigtable是一个稀疏的,分布式的,持久化的,多维的排序映射。
先来看看多维、排序、映射。Bigtable的键有三维,分别是行键(row key)、列键(column key)和时间戳(timestamp),行键和列键都是字节串,时间戳是64位整型;而值是一个字节串。可以用 (row:string, column:string, time: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:bar" : {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:bar" : { //一列
- 15 : "d",
- },
- "B:" : { //一列
- 6 : "w"
- 3 : "o"
- 1 : "w"
- }
- },
- // ...
- }
图1是Bigtable论文里给出的例子,Webtable表存储了大量的网页和相关信息。在Webtable,每一行存储一个网页,其反转的url作为行键,比如maps.google.com/index.html的数据存储在键为com.google.maps/index.html的行里,反转的原因是为了让同一个域名下的子域名网页能聚集在一起。图1中的列族"anchor"保存了该网页的引用站点(比如引用了CNN主页的站点),qualifier是引用站点的名称,而数据是链接文本;列族"contents"保存的是网页的内容,这个列族只有一个空列"contents:"。图1中"contents:"列下保存了网页的三个版本,我们可以用("com.cnn.www", "contents:", t5)来找到CNN主页在t5时刻的内容。
再来看看作者说的其它特征:稀疏,分布式,持久化。持久化的意思很简单,Bigtable的数据最终会以文件的形式放到GFS去。Bigtable建立在GFS之上本身就意味着分布式,当然分布式的意义还不仅限于此。稀疏的意思是,一个表里不同的行,列可能完完全全不一样。