良心博文: http://blog.csdn.net/opennaive/article/details/7532589

这里只是基础简述


众人说:

链接:http://blog.csdn.net/opennaive/article/details/7532589

2006年的OSDI有两篇google的论文,分别是BigTableChubby

  • Chubby是一个分布式锁服务,基于Paxos算法;
  • BigTable是一个用于管理结构化数据的分布式存储系统,构建在GFS、Chubby、SSTable等google技术之上。

相当多的google应用使用了BigTable,比如Google Earth和Google Analytics,因此它和GFSMapReduce并称为谷歌技术"三宝"。

链接:https://www.zhihu.com/question/19551534/answer/116874719

Bigtable 论文已经十年了。论文的第一大贡献是编程模型方面,当时大家都还在摸索在这种大 PC 机群环境下存储系统应该提供怎样的编程模型,要简单易理解,满足产品开发需求,又要在实现上能水平扩展支持海量存储。Bigtable 的「排序大表 + Column Family」在当时就不是什么新东西,但被证明了是一个非常成功的设计,能概括从线上到线下很多的业务需求,并且有很好的灵活性和扩展性。到今天 Bigtable 还有极广泛的应用,之后 MegaStore(公开版本是 AppEngine 上的 DataStore) 直接基于 Bigtable 构建,再后来的 Spanner 在单 tablet 上的存储干脆复用了 Bigtable 的版本。

在当时,人们对这种大规模分布式系统环境的认识还并不系统,谈得最多的是 CAP —— CAP (Consistency Availability Partition) 不可兼得是一个定律,但它没有告诉你应该怎么根据业务特点取舍。当时另一个有趣的项目是 Amazon 的 Dynamo, 它基于不同的取舍方向,追求 A 和 P(Bigtable 的 A 并不是特别好),让程序员自己动手解决写冲突问题。从今天看,就不及 Bigtable 的模型成功。(私货:我一直不看好 Cassandra)

在实现上,Bigtable 的另一点贡献是把 LSM (Log-Structured Merge) Tree 这种古老的技术带回前台。它和当时全部机械硬盘的现状以及 GFS 的编程模型极搭。把随机写全部转化为顺序写,实现了非常好的吞吐和即使对线上应用也可以接受的延迟(有坑,论文里就隐藏了坑),只读 SSTable dump 极大简化了设计。用 GFS 解决底层存储备份一系列问题,也大大简化了 Bigtable 自身的实现。SSTable + LSM Tree 这一部分的成果开源在了 LevelDB, 有广泛的应用,也启发了其他的很多开源项目。

Jeff Dean 自己对 Bigtable 最不满意的是没有提供跨行事务支持。这个故事很有趣:跨行事务天生是不可扩展,你没它办法,Bigtable 一开始并没有提供跨行事务就是这个原因。但是,它不可扩展是个实现问题,业务就是需要啊,你不提供官方实现,业务就会在上层企图自己搞事务,不出所料绝大部分分布式事务实现都是错的。Jeff Dean 后来实在看不过去在 Spanner 提供了官方分布式事务支持。

Bigtable 论文出来后不久,国内应该不止一个团队在企图复制它。当时 Bigtable 论文给我的感受倒不是它有多大创新,而是它在有机群管理软件(当时还不知道它叫 borg)有 GFS 有 Chubby 做基础,实现起来并不困难(论文里说了大概就10万行C++),有了 Bigtable 的基础,Google 实现其他的东西可以更快更得心应手。这是拿机群当操作系统做的思路,这种打法,你想要跟着打,会追得很辛苦,你想要走捷径取得局部成果,又必然后劲不足。稍微有点毁三观,这么多年之后我不用翻原文都能记起 Bigtable 等老三篇的细节,就是那时被碾压的印记。


Data Model

本质上说,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{
"" : {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" : { //一列
: "y", //一个版本
: "m"
},
"A:bar" : { //一列
: "d",
},
"B:" : { //一列
: "w"
: "o"
: "w"
}
},
// ...
}

查询时,如果只给出行列,那么返回的是最新版本的数据;

如果给出了行列时间戳,那么返回的是时间小于或等于时间戳的数据。

查询:"aaaaa"/"A:foo",返回的值是"y"

查询:"aaaaa"/"A:foo"/10,返回的结果就是"m";  // 小于10的至于4

查询:"aaaaa"/"A:foo"/2,返回的结果是空。     // 小于2的为null

APIs:

• Metadata operations
  – Create/delete tables, column families, change metadata
• Writes
  – Set(): write cells in a row
  – DeleteCells(): delete cells in a row
  – DeleteRow(): delete all cells in a row
• Reads
  – Scanner: read arbitrary cells in a bigtable
  • Each row read is atomic
  • Can restrict returned rows to a particular range
  • Can ask for just data from 1 row, all rows, etc.
  • Can ask for all columns, just certain column families, or specific columns

Building blocks:

• Google File System (GFS)
  – stores persistent data (SSTable file format)  // Sorted String Table
• Scheduler  // 分配任务
  – schedules jobs onto machines
• Chubby    // lock management
  – Lock service: distributed lock manager
  – master election, location bootstrapping
• MapReduce (optional)  // 分布式计算 --> 当然,spark是its替代品
  – Data processing
  – Read/write Bigtable data

Bigtable依赖于google的几项技术:(1) 用GFS来存储日志和数据文件;(2) 按SSTable文件格式存储数据;(3) 用Chubby管理元数据。

  • BigTable的数据和日志都是写入GFS的。
  • SSTable的全称是Sorted Strings Table,是一种不可修改的有序的键值映射,提供了查询、遍历等功能。每个SSTable由一系列的块(block)组成,Bigtable将块默认设为64KB。在SSTable的尾部存储着块索引,在访问SSTable时,整个索引会被读入内存。BigTable论文没有提到SSTable的具体结构,LevelDb日知录之四: SSTable文件这篇文章对LevelDb的SSTable格式进行了介绍,因为LevelDB的作者JeffreyDean正是BigTable的设计师,所以极具参考价值。每一个片(tablet)在GFS里都是按照SSTable的格式存储的,每个片可能对应多个SSTable。
  • Chubby是一种高可用的分布式锁服务,Chubby有五个活跃副本,同时只有一个主要的副本提供服务,副本之间用Paxos算法维持一致性。
    • Chubby提供了一个命名空间(包括一些目录和文件),每个目录和文件就是一个锁。Chubby的客户端必须和Chubby保持会话,客户端的会话若过期则会丢失所有的锁。
    • 关于Chubby的详细信息可以看google的另一篇论文:The Chubby lock service for loosely-coupled distributed systems。Chubby用于片定位,片服务器的状态监控,访问控制列表存储等任务。

Implementation:

Bigtable集群包括三个主要部分:一个供客户端使用的库,一个主服务器(master server),许多片服务器(tablet server)。

正如数据模型小节所说,Bigtable会将表(table)进行分片,片(tablet)的大小维持在100-200MB范围,一旦超出范围就将分裂成符合要求的片,或者合并成更大的片。 --> 下一节

1. 每个片服务器负责一定量的片,处理对其片的读写请求,以及片的分裂或合并。

片服务器可以根据负载随时添加和删除。这里片服务器并不真实存储数据,而相当于一个连接Bigtable和GFS的代理,客户端的一些数据操作都通过片服务器代理间接访问GFS。

2. 主服务器负责将片分配给片服务器,监控片服务器的添加和删除,平衡片服务器的负载,处理表和列族的创建等。注意,主服务器不存储任何片,不提供任何数据服务,也不提供片的定位信息。

客户端需要读写数据时,直接与片服务器联系。因为客户端并不需要从主服务器获取片的位置信息,所以大多数客户端从来不需要访问主服务器,主服务器的负载一般很轻。

Tablets

• Each Tablet is assigned to one tablet server.
  – Tablet holds contiguous range of rows
    • Clients can often choose row keys to achieve locality
  – Aim for ~100MB to 200MB of data per tablet
• Tablet server is responsible for ~100 tablets
  – Fast recovery:
    • 100 machines each pick up 1 tablet for failed machine
  – Fine-grained load balancing:
    • Migrate tablets away from overloaded machine
    • Master makes load-balancing decisions

One Tablt server: 100 tablets * 100~200MB = 10~20G

前面提到主服务器不提供片的位置信息,那么客户端是如何访问片的呢?来看看论文给的示意图,Bigtable使用一个类似B+树的数据结构存储片的位置信息。

第一层,Chubby file。这一层是一个Chubby文件,它保存着root tablet的位置。这个Chubby文件属于Chubby服务的一部分,一旦Chubby不可用,就意味着丢失了root tablet的位置,整个Bigtable也就不可用了。

第二层,root tablet。root tablet其实是元数据表(METADATA table)的第一个分片,它保存着元数据表其它片的位置。root tablet很特别,为了保证树的深度不变,root tablet从不分裂。

第三层,其它的元数据片,它们和root tablet一起组成完整的元数据表。每个元数据片都包含了许多用户片的位置信息。

可以看出整个定位系统其实只是两部分,一个Chubby文件一个元数据表。注意元数据表虽然特殊,但也仍然服从前文的数据模型,每个分片也都是由专门的片服务器负责,这就是不需要主服务器提供位置信息的原因。

客户端会缓存片的位置信息,如果在缓存里找不到一个片的位置信息,就需要查找这个三层结构了,包括访问一次Chubby服务,访问两次片服务器。

Tablet Assignment

• Each tablet is assigned to one tablet server at a time.
Master server keeps track of the set of live tablet servers and current assignments of tablets to servers.
• When a tablet is unassigned, master assigns the tablet to an tablet server with sufficient room.
• It uses Chubby to monitor health of tablet servers, and restart/replace failed servers.

About Chubby:

– Tablet server registers itself by getting a lock in a specific directory chubby
  • Chubby gives 㵰lease㵱 on lock, must be renewed periodically
  • Server loses lock if it gets disconnected

– Master monitors this directory to find which servers exist/are alive
  • If server not contactable/has lost lock, master grabs lock and reassigns tablets
  • GFS replicates data. Prefer to start tablet server on same machine that the data is already at.

Compression
– Many opportunities for compression
  • Similar values in the cell at different timestamps  不同的时间序列
  • Similar values in different columns  不同的列
  • Similar values across adjacent rows  邻接行

片的存储和访问

片的数据最终还是写到GFS里的,片(tablet)在GFS里的物理形态就是若干个SSTable文件。图5展示了读写操作基本情况。

当片服务器收到一个写请求,片服务器首先检查请求是否合法。

如果合法,先将写请求提交到日志去,然后将数据写入内存中的memtable。

memtable相当于SSTable的缓存,当memtable成长到一定规模会被冻结,Bigtable随之创建一个新的memtable,并且将冻结的memtable转换为SSTable格式写入GFS,这个操作称为minor compaction。

当片服务器收到一个读请求,同样要检查请求是否合法。

如果合法,这个读操作会查看所有SSTable文件和memtable的合并视图,

因为SSTable和memtable本身都是已排序的,所以合并相当快。

每一次minor compaction都会产生一个新的SSTable文件,SSTable文件太多读操作的效率就降低了,所以Bigtable定期执行merging compaction操作,将几个SSTable和memtable合并为一个新的SSTable。

BigTable还有个更厉害的叫major compaction,它将所有SSTable合并为一个新的SSTable。遗憾的是,BigTable作者没有介绍memtable和SSTable的详细数据结构。

BigTable和GFS的关系

集群包括主服务器和片服务器,主服务器负责将片分配给片服务器,而具体的数据服务则全权由片服务器负责。

但是不要误以为片服务器真的存储了数据(除了内存中memtable的数据),数据的真实位置只有GFS才知道。

主服务器将片分配给片服务器的意思应该是,

  • 片服务器获取了片的所有SSTable文件名,
  • 片服务器通过一些索引机制可以知道所需要的数据在哪个SSTable文件,
  • 然后从GFS中读取SSTable文件的数据,
  • 这个SSTable文件可能分布在好几台chunkserver上。  // 只有GFS掌管具体的物理存储操作。

Performance - Scaling

Reason: Load Imbalance
– Competitions with other processes
  • Network
  • CPU
– Rebalancing algorithm does not work perfectly
  • Reduce the number of tablet movement
  • Load shifted around as the benchmark progresses

[IR] Bigtable: A Distributed Storage System for Semi-Structured Data的更多相关文章

  1. Bigtable: A Distributed Storage System for Structured Data

    https://static.googleusercontent.com/media/research.google.com/en//archive/bigtable-osdi06.pdf Abstr ...

  2. Note: Bigtable, A Distributed Storage System for Structured Data

    Abstract Introduction::  Bigtable设计主旨:可扩地扩展到pByte级别和数千台机器的系统, 通用.可伸缩.高性能.高可用性.  不实现完整的关系数据模型,而是支持一个可 ...

  3. Bigtable:A Distributed Storage System for Strctured Data

    2006 年10 月Google 发布三架马车之一的<Bigtable:A Distributed Storage System for Strctured Data>论文之后,Power ...

  4. Storage System and File System Courses

    I researched a lot about storage system classes given at good universities this year. This had two r ...

  5. HDFS分布式文件系统(The Hadoop Distributed File System)

    The Hadoop Distributed File System (HDFS) is designed to store very large data sets reliably, and to ...

  6. PacificA: Replication in Log-Based Distributed Storage Systems

    PacificA: Replication in Log-Based Distributed Storage Systems - Microsoft Research https://www.micr ...

  7. 1.1 Introduction中 Kafka as a Storage System官网剖析(博主推荐)

    不多说,直接上干货! 一切来源于官网 http://kafka.apache.org/documentation/ Kafka as a Storage System kafka作为一个存储系统 An ...

  8. f4: Facebook’s Warm BLOB Storage System——Erasure Code

    Facebook在OSDI 2014上发表论文f4: Facebook's Warm BLOB Storage System,这个系统主要目的就是降低存储成本,在容忍磁盘,主机,机架,数据中心的同时提 ...

  9. HDFS(Hadoop Distributed File System )

    HDFS(Hadoop Distributed File System ) HDFS(Hadoop Distributed File System )Hadoop分布式文件系统.是根据google发表 ...

随机推荐

  1. SharePoint 2019 图文安装教程

    前言 SharePoint 2019刚刚发布,很多群友在寻找安装教程,霖雨正好也下载了进行体验,就把完整的安装过程做成图文教程,分享给大家了,有需要的人可以有个参考. 文章从创建虚拟机开始,可能有点啰 ...

  2. Js 判断浏览器类型整理

    判断原理 JavaScript是前端开发的主要语言,我们可以通过 编写JavaScript程序来判断浏览器的类型及版本.JavaScript判断浏览器类型一般有两种办法,一种是根据各种浏览器独有的属性 ...

  3. C# windows 桌面控件的扩展

    今天一同事 需要一个Windows from下 GridView的嵌套的控件,于是就去找了以前自己写的一些form 控件,发现居然没有人下载.同时查找以前的下载包也比较费时,于是乎就搞一个文章. 运行 ...

  4. iOS开发-模板方法模式

    模板方法模式定义一个操作中的算法的骨架,而将步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义算法的某些特定步骤.模板方法模式是由子类决定实现算法中的步骤,工厂方法由子类决定实现哪一 ...

  5. python的匿名函数lambda解释及用法

    lambda函数的语法只包含一个语句,如下:    lambda arg1,arg2,.....argn:expression(主要是看下面的例子)代码示例: #-*- coding:utf-8 -* ...

  6. 树莓派(RespberryPi)安装手记

    购买了两台树莓派,显示器接口是HDMI的,所以需要HDMI高清线连接到显示器,再加上SD卡做硬盘以及无线USB-WIFI,就可以玩一玩树莓派这个小东西了.以下是安装手记. 首先是制作“启动光盘”,其实 ...

  7. ANTLR flex/bison

    https://stackoverflow.com/questions/29971097/how-to-create-ast-with-antlr4 这个很值得仔细看 https://github.c ...

  8. 【Zookeeper】源码分析之网络通信(三)之NettyServerCnxn

    一.前言 前面已经学习了NIOServerCnxn,接着继续学习NettyServerCnxn. 二.NettyServerCnxn源码分析 2.1 类的继承关系 public class Netty ...

  9. VirtualBox安装64位系统

    2010-04-29    到引导区报错: This kernel requires an X86-64  CPU,but only detected an i686 CPU. 以我小学水平的英语理解 ...

  10. 安装babel遇到的异常

    Error: Requires Babel "^7.0.0-0", but was loaded with "6.26.3". If you are sure ...