引言
BigTable是google研发一个管理结构化数据的分布式存储系统,构建在GFS、Chubby等技术之上。其中:
- GFS:是谷歌的分布式文件系统,开源分布式文件系统HDFS思想与之相似;
- Chubby:是谷歌基于paxos算法实现的分布式锁服务,此外,它还提供一致性的分布式数据读写功能;
1 数据模型
1.1 存储方式
BigTable按key(row:string, column:string, time:int64) -> value(string)方式排序,方便快速索引。更细节地说,先按行名升序、如果行名相同再按列名升序、最后按时间戳为版本号降序排列。最后在文件系统中GFS中按lsm方式存储。
1.2 数据拆分
为了实现集群,BigTable以行名范围对数据拆分片存储,每个分片叫tablet。每个tablet是相同行键前缀的数据集合。假设用户的数据行健以用户id开头、用户id为9位,那么以行健前9位划分tablet,就可以让相同用户的数据内聚到一个tablet中。
1.3 与SQL的对比
首先,BigTable是用于管理结构化数据。但它与传统的SQL又有一些差异:
- 每个SQL表的列是固定的,且列存储的数据类型也是固定的;但是BigTable的列数目、各行的列都可以不相同,所以BigTable是具备稀疏特征的说法。
- SQL表的行号是数字型的;BigTable的行是字符串类型,即行名称,且各行的行名在写入时动态指定。
- 在底层存储结构上,很多传统SQL存储引擎(例如Innodb)采用B+树,而BigTable采用的LSM方式,从存储方式看,BigTable是以key(row:string, column:string, time:int64) -> value(string)方式的KV存储。
2 体系架构
2.1 整体架构
整个BigTable由三部分组成,即client(客户端lib库)、master系统、tablet服务;然后基于Chubby和GFS实现。其中:
- master服务只负责给tablet分配tablet、管理tablet服务器的状态等集群状态相关的工作;
- client库是内嵌在客户端的库,为应用提供API;
- tablet服务是处理数据请求的服务集群节点。每个tablet服务器处理至少一个、或多个tablet分片,然后转发给GFS持久化。
2.2 元数据管理
从前面可以看出BigTable最终数据是存储在GFS中,那么它是如何找到每个tablet分片在哪个GFS文件中的呢?其实元数据也是按tablet方式分片、分级存储的。与ceph自包含(或者说自存储)文件元数据一个原理。在Chubby中只记录顶级元数据的tablet位置或文件名。然后通过级联二级元数据的tablet,最终可以定位到用户数据的tablet。具体如下:
因为每个tablet由若干个sst文件组成,所以location在实现细节方面可以是一个文件序列,也可以像leveldb一样指向一个manifest文件,然后由manifest文件存储相关的多个sst文件。
3 读写流程
- 写入流程
每个tablet服务器维护一个或多个tablet分片,每个tablet服务器使用一个WAL日志文件,用来记录接收的所管理分片的数据写入;然后将数据插入到内存中;当内存中数据达到上限,就会写入到对应的tablet分片的新sst文件中。此外,tablet服务还会处理后台sst的合并。整个过程与leveldb类似。
- 读取流程
读取流程与leveldb也是类似的过程。先读取tablet服务内存中是否有数据;若没有就会读取tablet分片的sst文件中是否有数据;最后都没有才会返回查找失败。