Bigtable Notes
Google bigtable paper: http://labs.google.com/papers/bigtable.html
0.设计目标:
管理海量结构化数据
使用廉价的服务器
性能上不但能满足高吞吐量,也能满足低延迟
1.介绍
广泛适应性
可伸缩
高性能
高可用
Bigtable没有提供完整的关系数据库模型。
它实现了一个简单的模型,但是支持动态控制模型的布局和格式。
支持locality(通过设计schema,可以把要经常一起访问的数据放在一起)
2.数据模型
简单的说,就是一个排序的多维的map.
map的key是由rowkey+column name+timestamp组成的
Rows
每一行的rowkey可以是任意字符,最多64KB。
对一行的读写是原子的(无论涉及到几个column),这样做的好处就是简化了并发机制,用户也能很容易理解。
Column Family
基本的访问控制单位,由多个column组成。
CF必须预先创建好,并且通常不会很多(数以百计的),而且一般很少改动。
用户访问控制的单位是基于CF的。也就是说对于一个CF,不同的用户可能有不同的访问权限。
Column
Column的格式是"family:qualifier",family必须是由可打印的字符组成的,qualifier可以是任意字符。
Timestamps
64bit整型,由系统决定或者用户指定。
用户可以指定对于每个CF存贮几个版本的数据,或者指定最多保留的时间(TTL)。
3.Dependency
GFS
分布式文件系统(相比较HBase是HDFS)
Bigtable使用GFS来存贮日志和数据。
Bigtable数据存贮格式的是SSTable.
SSTable 是由排序的,不可修改的key-value对组成的。
SSTable是由很多block组成,每个block的是64KB.
SSTable有一个block index在文件的末尾,这样就能快速定位block(使用二分法)
SSTable可以完整的映射到memory,这样读的时候可以不用读磁盘。
Cubby使用Paxos算法来保证数据的一致性。(Paxos 算法解决的问题是一个分布式系统如何就某个值(决议)达成一致)
Cubby提供了目录和小文件,他们都可以用做锁,读写一个文件都是原子的。
每一个Cubby Client维护找一个session,当session过期,它就会失去拥有的锁和句柄。
Cubby Client可以设置callback,这样当文件改变就能得到通知。
Bigtable用Cubby:
保证最多只有一个活动的master node
存贮启动的数据
存贮表的schema
存贮CF的访问控制列表
检查新加的或者过期的tablet server
平衡tablet server的负载
回收GFS上面的过期数据
处理表的创建或者schema的修改
由于大部分Bigtable client并不需要和Master server通讯,而是直接和tablet server通讯,所以master server的负载相对较轻。
切分tablet,当tablet过大
Chubby file-->ROOT tablet(never split)-->METADATA tablet-->User Tablet
The Chubby file contains the location of ROOT tablet.
Master server保留着活着的tablet server的列表以及tablet和tablet server的对应关系。
Bigtable使用Cubby来跟踪tablet server的状态
每一个tablet server启动的时候,会在Cubby特定的文件夹生成一个文件,并得到这个文件锁。
当这个tablet server下线的时候,这个文件就会被删除。反之,如果删除该文件,tablet server也会结束自己。
Master server的失败不会影响对现有tablet的分配。
新的Master server启动的时候,会做以下动作:
1.获得master锁,这样避免有多个master server起来
2.扫描Clubby里server的目录,这样就知道所有活着的tablet server
3.询问每一个tablet server,这样就知道每一个tablet server处理的tablet
4.扫描METADATA tablet,获得tablet列表
当更新时,首先会写入commit log(放在GFS),用于记录
最近的更新都是放在memory里面,memtable
老的更新才会写到SSTable中
当发生异常情况,比如掉电,内存的数据丢失,这时候就可以根据commit log来恢复Tablet
读操作:
会合并所有的SSTable和memtable的结果
当Tablet进行合并和split,读写操作都可以正常进行
major compaction:把一个Tablet所有的SSTable合成一个SSTable,删除过期数据
这样就可以减少磁盘IO,不必一次读到所有数据
另外,对于一个locaity groups 有一个 in-memory属性,这个属性对那些数据量不大,但是频繁读写,可以提高性能。
这样做的好处是,不需要解压整个SSTable文件
用户可以指定两步的压缩算法,可以达到更好的压缩比(10:1),这是因为相临的数据一般比较相似
Scan cache(highlevel)-
cache由SSTable返回的key-value对
对那些重复的读操作很有用
Block cache (lowlevel)-
cache SSTable
对那些读附近的数据比较有用(顺序读)
布隆过滤器可以用来减少对磁盘的读操作。
尤其对于查询一个不存在的rowkey,可以不需要访问磁盘。
所以BigTable对同一个Tablet server使用同一个commit log
使用“table; row name; log sequence number"三元组作为log的key
这样的好处就是相同table的log将在一起,以便于tablet的恢复
考虑到GFS的latency问题,Bigtable使用两个线程来写log,每一个线程都写自己的log,这样就会有两份commit log,但两个线程同时只有一个active
源tablet server做一次minor compaction,把memory写到磁盘
源tablet server停止服务该tablet
源tablet server再做一次minor compaction,这次会很快
正式转移到另外一个tablet server
另外,SSTable的不可修改性,使得回收过期的SSTable变得简单。
最后,不可修改使得tablet split起来非常迅速,子tablet可以跟父tablet share相同的SSTable文件
而memtable是可以修改的,对每一行使用了copy-on-write,这样读写就可以并行处理
Bigtable数据存贮格式的是SSTable.
SSTable 是由排序的,不可修改的key-value对组成的。
SSTable是由很多block组成,每个block的是64KB.
SSTable有一个block index在文件的末尾,这样就能快速定位block(使用二分法)
SSTable可以完整的映射到memory,这样读的时候可以不用读磁盘。
Cubby
高可用的分布式锁服务 (相比较HBase是zookeeper)Cubby使用Paxos算法来保证数据的一致性。(Paxos 算法解决的问题是一个分布式系统如何就某个值(决议)达成一致)
Cubby提供了目录和小文件,他们都可以用做锁,读写一个文件都是原子的。
每一个Cubby Client维护找一个session,当session过期,它就会失去拥有的锁和句柄。
Cubby Client可以设置callback,这样当文件改变就能得到通知。
Bigtable用Cubby:
保证最多只有一个活动的master node
存贮启动的数据
存贮表的schema
存贮CF的访问控制列表
4.实现
Bigtable实现由三部分组成Client端、一个master server和多个tablet server。Master server
把tablet指配给某个tablet server处理检查新加的或者过期的tablet server
平衡tablet server的负载
回收GFS上面的过期数据
处理表的创建或者schema的修改
由于大部分Bigtable client并不需要和Master server通讯,而是直接和tablet server通讯,所以master server的负载相对较轻。
Tablet server
读写数据切分tablet,当tablet过大
Tablet location
Bigtable使用了三层结构。Chubby file-->ROOT tablet(never split)-->METADATA tablet-->User Tablet
The Chubby file contains the location of ROOT tablet.
Tablet Assignment
每一个tablet被分配给一个tablet server.Master server保留着活着的tablet server的列表以及tablet和tablet server的对应关系。
Bigtable使用Cubby来跟踪tablet server的状态
每一个tablet server启动的时候,会在Cubby特定的文件夹生成一个文件,并得到这个文件锁。
当这个tablet server下线的时候,这个文件就会被删除。反之,如果删除该文件,tablet server也会结束自己。
Master server的失败不会影响对现有tablet的分配。
新的Master server启动的时候,会做以下动作:
1.获得master锁,这样避免有多个master server起来
2.扫描Clubby里server的目录,这样就知道所有活着的tablet server
3.询问每一个tablet server,这样就知道每一个tablet server处理的tablet
4.扫描METADATA tablet,获得tablet列表
Tablet Serving
写操作:当更新时,首先会写入commit log(放在GFS),用于记录
最近的更新都是放在memory里面,memtable
老的更新才会写到SSTable中
当发生异常情况,比如掉电,内存的数据丢失,这时候就可以根据commit log来恢复Tablet
读操作:
会合并所有的SSTable和memtable的结果
当Tablet进行合并和split,读写操作都可以正常进行
Compaction
minor compaction:把memtable转成SSTable,减少内存使用major compaction:把一个Tablet所有的SSTable合成一个SSTable,删除过期数据
5.优化
Locality groups
用户可以把多个CF绑在一个Locality groups里面,相对应于一个SSTable这样就可以减少磁盘IO,不必一次读到所有数据
另外,对于一个locaity groups 有一个 in-memory属性,这个属性对那些数据量不大,但是频繁读写,可以提高性能。
Compression
用户可以指定压缩算法,这个用来压缩每一个SSTable的每一个block。这样做的好处是,不需要解压整个SSTable文件
用户可以指定两步的压缩算法,可以达到更好的压缩比(10:1),这是因为相临的数据一般比较相似
读操作cache
两级cache:Scan cache(highlevel)-
cache由SSTable返回的key-value对
对那些重复的读操作很有用
Block cache (lowlevel)-
cache SSTable
对那些读附近的数据比较有用(顺序读)
布隆过滤器(Bloom Filter)
布隆过滤器可以用于检索一个元素是否在一个集合中。布隆过滤器可以用来减少对磁盘的读操作。
尤其对于查询一个不存在的rowkey,可以不需要访问磁盘。
commit-log的实现
如果对于每一个Tablet都有一个commit log的话,这样会导致同时会写多个log文件所以BigTable对同一个Tablet server使用同一个commit log
使用“table; row name; log sequence number"三元组作为log的key
这样的好处就是相同table的log将在一起,以便于tablet的恢复
考虑到GFS的latency问题,Bigtable使用两个线程来写log,每一个线程都写自己的log,这样就会有两份commit log,但两个线程同时只有一个active
加速tablet的恢复
当master把一个tablet从一个tablet server移到另外一个tablet serer,分为四步:源tablet server做一次minor compaction,把memory写到磁盘
源tablet server停止服务该tablet
源tablet server再做一次minor compaction,这次会很快
正式转移到另外一个tablet server
利用不可修改性
SSTable被设计成不可修改的,这样做的主要好处是不需要同步。另外,SSTable的不可修改性,使得回收过期的SSTable变得简单。
最后,不可修改使得tablet split起来非常迅速,子tablet可以跟父tablet share相同的SSTable文件
而memtable是可以修改的,对每一行使用了copy-on-write,这样读写就可以并行处理