诣在管理结构话得数据,BigTable与数据库非常相似,但是:BigTable不提供数据库的关系模型;它使用行列字符串定位数据,将数据看做一个字符串流。
BigTable是一个稀疏的分布式多维有序图,它使用行关键字,列关键字以及一个时间戳作为数据的索引。(row:string, column:string, time:int64) àstring
以一个webtable为例,如上图所示:使用URL作为行关键字,而将网页的各个方面作为列关键字,将网页的内容保存到”content”中。
行
对一个行的写/读操作必须是原子的,不论该操作跨越了多少列。BigTable将数据按照行关键字的字典序排列。一个范围内的行被归纳为一个table,它是任务分发和负载均衡的基本单元。
列簇(column family)
多个列关键字组合形成column family,它是访问控制的基本单元。所有保存在同一个列簇中的数据类型是一致的。我们试图控制一个table所包含的列簇的数量,但是一个table包含的列的数量是没有限制的。每个列使用family:qualify命名,
BigTable数据使用GFS存储,内部使用SSTable文件保存BigTable数据。一个SSTable文件被划分为若干个block,每个block通过block索引查找,当一个SSTable文件被打开后,它的索引被读到缓存中。
BigTable使用chubby管理。Chubby提供一个名字空间,其中包括目录和小文件,他们可以作为锁使用,对他们的读写操作都是原子的。
系统主要由以下部件构成:一个供客户端连接的库,一个master服务器,许多tablet服务器。Tablet服务器能够动态加入或者删除。
Master:为tablet分配tablet server;监测tablet server的加入和失效;管理tabletserver上的负载均衡;GFS中文件的垃圾回收;当新建table或者column family时维护schema的改变。
Tabletserver:管理一组tablet。处理对它所管理的tablet的读写请求,当tablet增长过大时,将一个tablet分裂为两个。
Client对tablet的访问不需要进过master,可以直接与tablet server交互,client不需要通过master查找tablet的位置信息。
BigTable集群ß许多tableß一组tabletß与一组row range相关的数据:初始时,一个table仅有一个tablet组成。当table增长时,它被分割为多个tablet。
?my ideaè
一个tablet server可以管理一到多个table,如果一个table很大,也可以将table放置在多个tablet server上。每个table划分为若干个tablet,一个tablet只能放置在一个tablet server上,而每个tabletserver则是由如果个row range构成的。
Tabletlocation
使用三层结构,类似于B+树。第一层是保存在chubby上的文件,记录了root tablet的位置;第二层是METADATAtablets,root tablet是METADATA表的首个表项,METADATA表记录了将所有tablet的元数据信息;METADATA表项记录了tablet信息,tablet的row key通过对table他的table标示符和它的最末行编码求得。
客户端library缓存tablet的位置信息。如果一个client不知道tablet的位置,或者发现自己缓存的信息时错误的,则递归地查找tablet的位置层次。如果客户端的缓存为空,则定位算法需要三次网络开销,包括一次读chubby。如果客户的缓存失效,则定位算法需要6次网络开销,因为只有当访问出错时客户端才能发现缓存信息失效了。为了减少开销,我们让客户端library预取table的位置信息:当客户端读METADATA table时,不止读取需要的一个tablet,而是多读取几个。
TabletAssignment
Master记录哪些tablet已经被分配,对于没有分配的tablet,这找到一个适合的server将tablet分配给它。
BigTable使用chubby机制跟踪table server。启动一个tablet server后,它新建一个排他锁并且申请该锁.master通过管理chubby上的相应目录管理tablet servers。如果tablet server失去它上面的锁,则该tabletserver将无法对外提供服务。但是该tabletserver将继续申请该锁,直到相应的文件已经被删除了。此时,该tablet server将无法再继续服务了,此时它将killitself。当tablet server终止时,它将释放它所持有的锁,以便master能够更快地将他上面的tablets重新分配。
master需要监测不能再提供服务的tablet server,并且能够尽快将它上面的tablet重新分配。master定期向tablet server查询锁信息。如果tablet server显示它已经失去了锁,或者当master无法访问某个tablet server时,master将试图获取该server上的文件锁。如果master成功获取该锁,则证明Chubby是活跃的并且tablet server已经失效或者无法访问Chubby,则master确认tablet server无法服务,并将tabletserver删除。当server的文件被删除后,master将该server上的所有tablet设置为“未分配”。如果master的Chubby过期,则master将kill itself。master失效并不影响tablet server上的tablet分布。
Master启动流程:1.master向chubby申请一个master锁;2.master遍历chubby的server目录获取活跃server的信息;3.master与所有tablet server交互,获取tablet的分配情况;4.master遍历METADATA表获取tablet的组信息,当发现某个tablet没有分配时,为其指定一个server。
TabletServing
最近提交的更新保存在内存中,以有序的buffer组织;旧的提交的更新则被保存在一个顺序的SSTable中,SSTable可以保存在内存中,也可以存放在磁盘上。
恢复tablet:tablet server从METADATA表中读取它的元数据信息,该元数据包含了组成该tablet的SSTtable表,已经一组恢复点。server将部分SSTable读入内存中,通过提交检查点以后的恢复点重构memtable。
写访问到达时,server对访问权限进行检查。有效的修改被写入到commit日志。Group commit机制用来提高小写的性能。当写操作提交后,它的内容被插入到memtable中。读访问到达时,同样先做权限检查。有效的读操作被执行。
Compactions
当memtable的size达到阈值时,将memtable冻结,并且创建一个新的memtable,冻结的memtable被转换为SSTable同时写入GFS。成为minor压缩,主要优点有:1.减少了tablet server的内存使用;2.减少了server失效时需要读出的log的数量。minor压缩操作可能会创建新的SSTable,如果不对该操作进行限制的话,可能导致对一个文件的访问需要跨越多个SSTable。所以,我们将在后台执行一个压缩程序,将跨多个SSTable和memtable的文件从这些SSTable和memtable中读出,然后保存到一个新的SSTable中,完成压缩后,就可以将原来的SSTable和memtable删除了,该过程称为major压缩。
Localitygroups
client将多个column famliy集合在一起形成localitygroup。为每个tablet中的locality group新建一个SSTable。不经常一起被访问的column family可以将它们放在不同的localitygroup中,这样可以优化读性能。同时,还可以分别为每个localitygroup指定不同的特性参数,如让某些localitygroup放在内存中,优化经常访问的小文件的性能。
Compression
压缩的对象是一个SSTable,虽然这样的压缩不能保证压缩空间最小,但是当我们读取一个SSTable的一部分时,能够保证该信息是未被压缩的。我们使用了两步压缩:第一步Bentley and McIlroy;第二步fastcompression algorithm。
Commit-logimplementation
两种log记录方式:
1.为每个tablet server分配一个commit log;
2.将不同的tablets合并到一个物理文件中;
将多个tablet保存到一个log文件中:当tablet server失效后,其管理的tablet将被分散到多个server上,这些server为了恢复原来tablet server上的修改,需要从commitlog文件中读取log信息,则这些server都需要读取log文件,如果原来的tablet被分散到100个sever上,则该log文件将被读取100次。为了减少读log file的次数:将log file中提交的log条目按照关键字排序。经过处理后,tablet在log files中将是连续有序的。为了并发排序,我们将log file划分成64MB的段,并且让tablet server并发地对这些段排序。排序过程由master控制,当某个tablet server申请恢复commit log中的日志信息时,触发该排序过程。
为了避免写log对系统写性能的影响,每个tabletserver有两个写日志线程,都是将日志写入自己的logfile;一个时刻只有一个线程有效。如果写active日志性能糟糕,则log file写进程将切换到另一个线程,修改操作的日志记录将又另一个线程写入log file中。每个log条目有一个顺序编号,这样使得恢复进程能够识别重复的日志条目是否是由于日志进程切换所导致的。