Bigtable: a distributed storage system for structured data论文阅读

Bigtable: a distributed storage system for structured data

1.Data Model

一个Bigtable集群是运行Bigtable软件的一组进程。每个集群为一组表提供服务。在Bigtable中,一个表是一个稀疏的、分布式的、持久化的多维排序映射。数据被组织成三个维度:行、列和时间戳。

(row:string, column:string, time:int64) → string

我们将由特定行键、列键和时间戳引用的存储称为单元格(cell)。行被分组在一起形成负载均衡的单位(分组结果称为Tablet),列被分组在一起形成访问控制和资源计量的单位(分组结果称为column family)。

1.1 Rows

Bigtable按行键的字典序维护数据。表中的行键是任意字符串(目前最大为64KB,尽管对于大多数用户,10-100字节是典型大小)。每个单行键下的数据读写都是可串行化的(无论在该行中读取或写入多少不同的列),这是一种设计决策,使得客户端更容易推断在同时更新同一行时系统的行为。换句话说,行是Bigtable中事务一致性的单位,目前不支持跨行的事务。

具有连续键的行被分组成tablet,这形成了分布和负载均衡的单位。因此,短行范围的读取效率高,通常只需要与少量机器通信。客户端可以通过选择其行键来利用此属性,以便在数据访问方面获得良好的局部性。例如,在Webtable中,相同域中的页面通过反转URL的主机名组成连续的行。我们将来自maps.google.com/index.html的数据存储在键com.google.maps/index.html下。将相同域的页面存储在相邻的位置可以使一些主机和域分析更加高效。

1.2 Columns

列键被分组成称为列族(column family)的集合,列族形成访问控制的单位。存储在列族中的所有数据通常都是相同类型的(我们将同一列族中的数据压缩在一起)。必须在存储在该列族中的任何列键之前显式创建列族。创建列族后,可以使用该族中的任何列键:可以在该列键下存储数据,而不影响表的模式。我们希望表中不同列族的数量很少(最多只有几百个),并且在操作期间很少更改列族;这个限制使得广泛共享的元数据不会太大。相比之下,一个表可以有无限数量的列。

可以通过更改表的模式(schema)来删除整个列族(5.5有具体说明),在这种情况下,存储在该列族中的任何列键下的数据都将被删除。然而,由于Bigtable不支持跨多行的事务,如果存储在多个行中的特定列键下的数据,则无法以原子方式删除该数据。

image-20230515101722124

列键使用以下语法命名:family:qualifier。列族名称必须是可打印的,但qualifier可以是任意字符串。Webtable的一个示例列族是language,它存储网页所使用的语言。我们在language列族中仅使用一个空限定符的列键来存储每个网页的语言ID。

对于这个表来说,另一个有用的列族是anchor;该列族中的每个列键表示单个anchor,如上图所示。限定符是引用站点的名称;cell包含与链接相关联的文本。

访问控制和磁盘和内存计量都在列族级别上执行。在我们的Webtable示例中,这些控件允许我们管理几种不同类型的应用程序:一些添加新基础数据,一些读取基础数据并创建派生列族,还有一些只允许查看现有数据(可能甚至不允许查看所有的现有列族,出于隐私原因)。

1.3 Timestamps

表中的不同单元格(cells)可以包含相同数据的多个版本,这些版本由时间戳索引。Bigtable时间戳是64位整数。它们可以由Bigtable隐式分配,此时它们表示微秒级的“实时”,或者它们可以由客户端应用程序显式分配。需要避免冲突的应用程序必须自己生成唯一的时间戳。单元格的不同版本按时间戳递减的顺序存储,以便先读取最近的版本。

为了使版本化数据的管理不那么繁琐,我们对每一个列族配有两个设置参数, Bigtable 通过这两个参数可以对废弃版本的数据自动进行垃圾收集。它们告诉Bigtable自动对版本化数据进行垃圾收集。客户端可以指定仅保留数据的最后n个版本,或仅保留足够新的版本(例如,仅保留在最近七天内写入的值)。

在我们的Webtable示例中,我们可以将存储在contents:列中的爬取页面的时间戳设置为实际爬取这些页面版本的时间。上述的垃圾回收机制使我们能够告诉Bigtable仅保留每个页面的最近三个版本。(同样是上图例子)

客户端应用程序可以在Bigtable中写入或删除值,从单个行中查找值,或迭代表中的数据子集。图2显示了使用RowMutation(行锁)抽象执行一系列更新的C++代码。(为了保持示例简短,省略了不相关的细节。)调用Apply对Webtable执行原子更改:它将一个anchor添加到www.cnn.com并删除不同的锚。

图3显示了使用Scanner抽象迭代特定行中的所有锚的C++代码。客户端可以迭代多个列族,并且有几种机制可以限制扫描遍历的行、列和时间戳。例如,我们可以限制上面的扫描,仅生成列与正则表达式anchor:*.cnn.com匹配的锚,或仅生成时间戳在当前时间十天内的锚。

1.4 API

Bigtable支持几个其他功能,允许用户以更复杂的方式操作数据。

首先,Bigtable支持单行事务,可用于在单个行键下存储的数据上执行原子读取-修改-写入序列。Bigtable目前不支持跨行键的一般事务,尽管它提供了一个界面,用于在客户端跨行键批量写入。

其次,Bigtable允许将单元格用作整数计数器。最后,Bigtable支持在服务器的地址空间中执行客户端提供的脚本。这些脚本是用一个称为Sawzall的语言编写的[Pike等人,2005],该语言是Google用于处理数据开发的。

目前,我们基于Sawzall的API不允许客户端脚本写回到Bigtable,但它允许各种形式的数据转换、基于任意表达式的过滤以及通过各种运算符进行汇总。

1.5 Google SSTable

Google SSTable不可变文件格式被用于存储Bigtable数据文件。SSTable提供了一个持久的、有序的不可变映射,从键到值,其中键和值都是任意字节字符串。提供了查找与指定键相关联的值和迭代指定键范围内的所有键/值对的操作。在内部,每个SSTable包含一系列块(默认情况下,每个块的大小为64KB,但大小是可配置的)。块索引(存储在SSTable末尾)用于定位块;在打开SSTable时,索引将被加载到内存中。可以使用单个磁盘查找执行查找:我们首先通过在内存索引中执行二分搜索来找到适当的块,然后从磁盘中读取适当的块。可选地,SSTable可以完全映射到内存中,这允许我们在不触及磁盘的情况下执行查找和扫描操作。

此处涉及到了内存映射文件(Memory Mapped File)的知识点,需要额外的进行学习。

1.5.1 Memory Mapped File

内存映射文件的作用是使一个磁盘文件与存储空间中的一个缓冲区建立映射关系,然后当从缓冲区中取数据,就相当于读文件中的相应字节;而将数据存入缓冲区,就相当于写文件中的相应字节。这样就可以不使用read和write直接执行I/O了。即通过操作内存来操作文件,省了从磁盘文件拷贝数据到用户缓冲区的步骤,所以十分高效。

即做完映射后,用户只在用户缓冲区进行操作即可,磁盘部分的同步就不用用户操心了。

img

但是有个问题:映射就是把文件拷到内存里,然后操作内存,但最终内存里的数据还是要写到文件里,这个和直接操作文件不一样吗?既然还是需要把文件拷贝到用户缓冲区,最后同样需要进行写盘操作,那么区别在哪?

答:映射完了以后,文件就可以关闭了。你所做的操作仅仅是操作内存,内存数据什么时候同步到文件中,你不必再关心了。访存是很快的。如果是原来的写法,往文件里存数据需要三步,先写到用户缓冲区,再从用户缓冲区写到内核缓冲区,最后内核缓冲区的文件到硬盘上需要额外的步骤。性能不好,不如交给操作系统,而用户只要做一次对用户缓冲区的操作即可,后续的不用管。

注:fflush()把进程缓冲区的数据刷新到内核缓冲区,fsync()把内核缓冲区的数据刷新到物理媒介上。

所以数据的流向应该是:用户缓冲区->内核缓冲区->物理媒介。

TODO:这里只是大概的说一下,后续必须进行操作系统方面知识的具体系统学习。

2.implementation

Bigtable实现有三个主要组件:一个被链接到每个客户端的库、一个主服务器和多个分片服务器。分片服务器可以动态地添加(或删除)到集群中以适应工作负载的变化。

2.1 distributed lock service-Chubby

Bigtable 依赖于一个高可用性和持久性的分布式锁服务,名为 Chubby [Burrows 2006]。一个 Chubby 服务由五个活跃的副本组成,其中一个被选为主节点并主动响应请求。当大多数副本正常运行并且可以相互通信时,服务处于活动状态。在面对故障时,Chubby 使用 Paxos 算法 [Chandra et al. 2007; Lamport 1998] 保持其副本的一致性。Chubby 提供由目录和小文件组成的命名空间。每个目录或文件都可以用作锁,对文件的读写操作是原子的。Chubby 客户端库提供对 Chubby 文件的一致性缓存。每个 Chubby 客户端都与 Chubby 服务维持一个会话。如果客户端无法在租约到期时续订其会话租约,则其会话将过期。当客户端的会话过期时,它将失去任何锁和打开的句柄。Chubby 客户端还可以在 Chubby 文件和目录上注册回调以便接收更改或会话过期的通知。

有点像Zookeeper的机制,毕竟ZK被称为开源的Chubby实现。

2.2 master/tablet server

主服务器负责分配分片到分片服务器、检测分片服务器的添加和过期、平衡分片服务器的负载以及在 GFS 中进行文件垃圾回收。此外,它还处理架构更改,如表和列族的创建和删除。

每个分片服务器管理一组分片(通常每个分片服务器有10到1000个分片)。分片服务器处理对其加载的分片的读写请求,还会对已经变得太大的分片进行拆分。

与许多单主分布式存储系统 [Ghemawat et al. 2003; Hartman and Ousterhout 1993] 一样,客户端数据不会通过主节点进行传输:客户端直接与分片服务器通信进行读写操作。由于 Bigtable 客户端也不依赖于主服务器获取分片位置信息,因此大多数客户端不会与主服务器通信。因此,在实践中主服务器的负载较轻。

2.3 Tablet machanism(分片机制)

Bigtable集群存储多个表。每个表由一组分片组成,每个分片包含与行范围相关联的所有数据。最初,每个表只包含一个分片。随着表的增长,它会自动拆分成多个分片,默认情况下每个分片大小约为1GB。

image-20230516151902072

我们使用类似于 B±tree [Comer 1979] 的三层层次结构来存储分片位置信息(图5)。第一层是存储在 Chubby 中的文件,其中包含根分片的位置。根分片包含特殊的METADATA表:该表中包含了所有分片的位置。每个METADATA分片包含一组用户分片的位置。根分片被特别处理——它永远不会被拆分——以确保分片位置层次结构不超过三层。

METADATA 表将一个分片的位置存储在行键下,该行键是对分片的表标识符和结束行进行编码的,每个行代表了一个用户表的分片元数据的情况(即某个用户表的具体分片信息)。每个 METADATA 行在内存中存储约1KB的数据。通过限制 METADATA 分片大小不超过128MB,我们的三级位置方案足以处理234个分片(或在128MB分片中存储261字节)。

每个METADATA分片不超过128MB(227B ),而一个METADATA行占用1KB数据(210B),所以一个METADATA分片做多存储217个METADATA行,三级结构,故三级方案最多可以处理217*217=234个分片,而每个用户分片相关元数据表的大小说到底也是METADATA分片,故在这种情况下一共可以存储234 * 227 = 261字节的元数据信息。

2.3.1 Tablet Assignments

每个分片一次只分配给一个分片服务器。主服务器跟踪活动的分片服务器的集合,以及当前分片的分配给分片服务器的情况,包括未分配的分片。当一个分片未分配,并且当有一个分片服务器有足够的空间容纳该分片时,主服务器通过向分片服务器发送分片加载请求来分配该分片。只有在下一次主服务器故障转移之前,如果分片加载请求未被目标分片服务器接收,这种分配才会失败:分片服务器只会接受当前主服务器的分片加载请求。因此,一旦主服务器发送了分片加载请求,它可以假定该分片已分配,直到分片服务器死亡或分片服务器通知主服务器已卸载该分片。

Bigtable使用Chubby来跟踪分片服务器。当一个分片服务器启动时,它会在特定的Chubby目录中创建并获取一个唯一命名文件的独占锁。主服务器监视这个目录(servers目录)以发现分片服务器。如果一个分片服务器失去了它的独占锁,例如,网络分区可能导致服务器失去了Chubby会话,那么它将停止为其分片提供服务。(Chubby提供了一种有效的机制,允许分片服务器检查它是否仍然拥有它的锁,而不会产生网络流量。)只要该文件仍然存在,分片服务器就会尝试重新获取其文件的独占锁。如果它的文件不再存在,那么该分片服务器将永远无法再次提供服务,因此它会自我终止。每当一个分片服务器终止(例如,因为集群管理系统正在将分片服务器的计算机从集群中移除)时,它会尝试释放它的锁,以便主服务器可以更快地重新分配它的分片。

2.3.2 Tablet更新机制

用类似于LSM-Tree的机制进行append-only方式的更新。并且存在minor compaction(将内存中的immutable定期写入磁盘,这会生成一个SSTable)与major compaction(定期合并盘中的SSTable)两种必要的合并机制。同时当客户端通过某个Tablet Server进行内容写入或更新到GFS时,同时GFS也会尝试将目标数据的一个副本放置在该分片服务器上(一般是本地磁盘),下次有客户端读取该数据时,可以直接从分片服务器读取,而不必再读GFS。

Minor Compaction:当写操作执行时,内存表的大小会增加。当内存表的大小达到一个阈值时,内存表被冻结,创建一个新的内存表,并将冻结的内存表转换为 SSTable 并写入 GFS。这个Minor Compaction过程有两个目标:它缩小了 Tablet Server 的内存使用,并且在该服务器死机时减少了在恢复期间从提交日志中读取的数据量。

Major Compaction:将所有 SSTable 重写为一个 SSTable 的合并压缩称为Major Compaction。由非大型压缩产生的 SSTable 可以包含特殊的删除条目,以抑制旧的 SSTable 中的已删除数据。另一方面,大型压缩生成一个不包含删除信息或已删除数据的 SSTable。Bigtable 循环遍历其所有的 Tablet,并定期对它们应用大型压缩。这些大型压缩允许 Bigtable 回收已删除数据使用的资源,并且还允许它确保已删除的数据及时地从系统中消失,这对于存储敏感数据的服务非常重要。

3.Refinement(改进)

在上述的实现的基础上,需要进行一些改进,才能真正的符合用户对性能、可靠性、可用性三个方面的需求。

3.1 Locality Groups(局部性组)

每个列族都被分配到一个由客户端定义的局部性组(locality group)中,这是一种抽象,使客户端能够控制其数据的存储布局。**在压缩期间,为每个Tablet中的每个locality group都生成一个单独的SSTable。**将通常不一起访问的列族分隔到不同的局部性组中,可以实现更高效的读取。例如,Webtable中的页面元数据(如语言和校验和)可以在一个局部性组中,而页面的内容可以在另一个组中;想要读取元数据的应用程序不需要读取所有页面内容。

此外,还可以根据每个局部性组指定一些有用的调整参数。例如,可以声明一个局部性组为内存中(in-memory)的。内存中的局部性组的SSTable会延迟加载到Tablet服务器的内存中。由于SSTable是不可变的,因此不存在一致性问题。一旦加载,属于这种局部性组的列族就可以在不访问磁盘的情况下进行读取。这个功能对于经常访问的小数据很有用;我们在METADATA表中的tablet-location列族中使用了这个功能。

3.2 Compression(压缩)

客户端可以控制局部性组的SSTable是否压缩,以及使用哪种压缩格式。用户指定的压缩格式应用于每个SSTable块(其大小可以通过局部性组特定的调整参数进行控制)。尽管我们通过单独压缩每个块而浪费了一些磁盘空间,但我们受益于可以在不解压整个文件的情况下读取SSTable的小部分。许多Bigtable客户端使用两遍定制压缩方案two-pass custom compression scheme.)。第一遍使用Bentley和McIlroy’s [1999]的方案,该方案压缩了一个大窗口中的长公共字符串。第二遍使用一个快速的压缩算法,该算法在数据的一个小16 KB窗口中查找重复项。两个压缩通道都非常快——它们在现代计算机上进行编码的速度为100-200 MB/s,解码的速度为400-1000 MB/s。尽管在选择压缩算法时我们强调了速度而非空间减少,但这个两遍压缩方案的表现非常出色。

论文中有具体的实验对比结果。说明这个two-pass custom compression scheme的效果很好。

3.2 Caching for Read Performance

为了提高读取性能,Tablet服务器使用了两级缓存。扫描缓存(Scan Cache)是一个更高级别的缓存,它缓存了由SSTable接口返回给Tablet服务器代码的键值对。块缓存(Block Cache)是一个更低级别的缓存,它缓存了从GFS读取的SSTable块。扫描缓存最适用于反复读取相同数据的应用程序。块缓存对于倾向于读取接近(物理位置上的接近)最近读取的数据的应用程序很有用(例如,顺序读取,或者在同一热行中同一局部性组内的不同列的随机读取)。

3.3 Bloom Filters

如第5.3节所述,读操作必须从组成一个Tablet状态的所有SSTable中读取。如果这些SSTable不在内存中,我们可能会进行大量的磁盘访问。为了减少访问次数,我们允许客户端指定在特定locality group中为SSTable创建布隆过滤器[Bloom 1970]。布隆过滤器允许我们询问一个SSTable是否可能包含指定行/列对的任何数据。对于某些应用程序,用于存储布隆过滤器的少量Tablet服务器内存极大地减少了读操作所需的磁盘寻道次数。我们使用布隆过滤器还避免了对不存在的行或列的大多数查找的磁盘访问。

3.4 Commit-Log Implementation

如果我们为每个Tablet保留一个单独的提交日志文件,那么在GFS中会同时写入大量文件。根据每个GFS服务器上基础文件系统实现的不同,这些写入可能需要大量的磁盘寻道才能写入不同的物理日志文件。此外,每个Tablet有单独的日志文件也会降低组提交优化的效果,因为组的规模会变小。为了解决这些问题,我们将每个Tablet服务器的变更追加到一个单独的提交日志中,这意味着将在同一个物理日志文件中混合不同tablet的变更[Gray 1978;Hagmann 1987]。

在分布式数据库的正常运行期间,使用一个日志文件可以显著提高性能,但它会使恢复变得复杂。当一个 tablet server(分片服务器)宕机时,它所服务的分片将被移动到大量其他 tablet server 上;每个服务器通常只会加载原始服务器的一小部分分片。为了恢复一个分片的状态,新的 tablet server 需要从原始 tablet server 写入的提交日志中重新应用该分片的更新。然而,这些分片的更新被混合在同一个物理日志文件中。一种解决方案是让每个新的 tablet server 读取完整的提交日志文件,并仅应用所需的分片条目以进行恢复。但是,在这种方案下,如果有 100 台机器每台分配了一个来自失败的 tablet server 的单个分片,那么日志文件将会被读取 100 次(每个服务器一次)。

下面通过各种措施来避免重复读取无用的提交日志。

我们通过首先按键(〈表、行名、日志序列号〉)对提交日志条目进行排序来避免重复读取日志。在排序后的输出中,特定分片的所有突变都是连续的,因此可以通过一次磁盘查找和顺序读取来高效地读取。为了并行化排序,我们将日志文件分成 64 MB 的段,并在不同的 tablet server 上并行地对每个段进行排序。这个排序过程由主服务器协调,并在一个 tablet server 表示需要从某个提交日志文件中恢复突变时启动。

将提交日志写入 GFS 有时会因各种原因(例如涉及写入的 GFS 服务器机器崩溃、或负载过重、或用于到达特定一组 GFS 服务器的网络路径正在遭受网络拥塞等)导致性能问题。为了保护变异不受 GFS 延迟峰值的影响,每个 tablet server 实际上有两个日志写入线程,每个线程写入自己的日志文件;同一时间只有其中一个线程处于活动状态。如果对活动日志文件的写入表现不佳,则将日志文件写入切换到另一个线程,并且提交日志队列中的变异会被新的活动日志写入线程写入。日志条目包含序列号,以便恢复过程可以省略由于此日志切换过程而产生的重复条目。

3.5 Speeding Up Tablet Recovery

在卸载一个分片之前,分片服务器会先对该分片进行一次小型压缩(minor compaction)操作。这个压缩操作通过减少分片服务器提交日志中未压实状态的数量来缩短恢复时间。在完成这个压实操作后,分片服务器停止为该分片提供服务。在实际卸载分片之前,分片服务器会进行另一次(通常非常快速的)小型压实操作,这是因为在执行第一个小型压实操作的过程中,会有新的日志到来,这部分日志是第一次操作无法检测到的,因此第二次compaciton操作是为了消除新到达日志中的uncompacted state log。完成这第二个小型压实操作后,可以将该分片加载到另一个分片服务器上,而无需恢复日志条目到新的分片服务器上。

3.6 Exploiting Immutability(利用不变性)

除了 SSTable 缓存之外,Bigtable 系统的各个其他部分也因我们生成的所有 SSTable 都是不可变的这一事实而得到简化。例如,当从 SSTable 中读取数据时,我们不需要对文件系统的访问进行同步。因此,行的并发控制可以非常有效地实现。唯一被读写访问的可变数据结构是内存表(memtable)。为了减少对内存表进行读取时的争用,我们使每个内存表行具备写时复制(copy-on-write)功能,并允许读写操作并行进行。

由于 SSTable 是不可变的,因此永久删除已删除数据的问题被转化为垃圾回收过期的 SSTable。每个分片的 SSTable 在 METADATA 表中进行了注册。主服务器可以通过对 SSTable 集合进行标记-清除垃圾回收([McCarthy 1960])来删除过期的 SSTable,其中 METADATA 表包含了根集合。

最后,SSTable 的不可变性使我们能够快速地分割分片。我们不需要为每个子分片生成新的 SSTable 集合,而是让子分片共享父分片的 SSTable。

4. Lessons

Google的工程师们在设计BigTable时也遇到了很多问题,并总结了一些经验,我认为这些很有用,所以记录了下来。

实验部分不看,后续有需要的时候会专门研究实验部分。

我们学到的一个教训是,大型分布式系统容易受到许多类型的故障影响,不仅仅是许多分布式协议中假定的标准网络分区和故障停止故障。例如,由于以下所有原因,我们都遇到了问题:内存和网络损坏、大的时钟偏差、挂起的机器、扩展和非对称的网络分区、我们正在使用的其他系统中的错误(例如 Chubby),GFS 配额溢出以及计划和未计划的硬件维护。随着我们对这些问题的经验越来越多,我们通过更改各种协议来解决它们。例如,我们为我们的 RPC 机制添加了校验和。我们还通过消除系统的一部分对另一部分的假设来处理一些问题。例如,我们停止假定给定的 Chubby 操作只能返回一组固定的错误之一。

我们学到的另一个教训是,在清楚了新功能将如何使用之前,延迟添加新功能非常重要。例如,我们最初计划在我们的 API 中支持通用事务。由于我们没有即时使用它们的需求,因此我们没有实现它们。现在,我们有许多实际运行在 Bigtable 上的应用程序,我们已经能够检查它们的实际需求,并发现大多数应用程序只需要单行事务。在人们要求分布式事务的情况下,最重要的用途是维护二级索引,我们计划添加一个专门的机制来满足这个需求。新机制将比分布式事务更专业化,但将更高效(特别是对于跨越数百行或更多行的更新),并且还将与我们的乐观跨数据中心复制方案更好地交互。

这告诉我们要根据用户需求加入新的功能,功能不需要具有太大的泛化性,只要能解决用户的需求即可,并且这会减少工作量,并且带来更好的兼容性。即Simple Design

我们从支持 Bigtable 中学到的一个实用教训是适当的系统级监控的重要性(即监控Bigtable本身以及使用Bigtable的客户端进程)。例如,我们扩展了我们的 RPC 系统,以对一些 RPC 进行详细跟踪。这个功能使我们能够检测并修复许多问题,如锁竞争、在提交 Bigtable 变更时对 GFS 的写入速度慢,以及在 METADATA 分片不可用时卡住对 METADATA 表的访问等。另一个有用的监控例子是每个 Bigtable 集群都在 Chubby 中注册。这使我们能够跟踪所有集群,发现它们有多大,看看它们正在运行哪个版本的软件,它们正在接收多少流量,以及是否存在任何问题,例如意外的大延迟。

最重要的教训是简单设计的价值。考虑到我们的系统规模(大约有 100,000 行非测试代码),以及代码随时间以意想不到的方式演变,我们发现代码和设计的清晰度对于代码维护和调试非常有帮助。其中一个例子是我们的分片服务器成员协议。我们的第一个协议很简单:主服务器定期向分片服务器发出租约,如果租约过期,则分片服务器自杀。不幸的是,这个协议在网络问题存在的情况下显著降低了可用性,并且还对主服务器恢复时间敏感。我们多次重新设计协议,直到我们有了一个表现良好的协议。然而,最终的协议过于复杂,并且依赖于Chubby功能的行为,而这些功能很少被其他应用程序使用。我们发现我们花费了大量时间来调试晦涩的边角案例,不仅在 Bigtable 代码中,也在 Chubby 代码中。最终,我们放弃了这个协议,并转向一个更简单的协议,仅依赖于广泛使用的 Chubby 特性。

5.Conclusions

C-Store 和 Bigtable 具有许多相似的特点:两个系统都使用share-nothing架构,并具有两种不同的数据结构,一种用于存储最近的写入数据,另一种用于存储长期存在的数据,并具有从一种形式转换到另一种形式的机制。这两个系统在它们的 API 上存在显著的差异:C-Store 表现得像关系数据库,而 Bigtable 提供了一个更低级别的读写接口,并设计支持每秒每台服务器处理数千个此类操作。C-Store 也是一个“读优化型关系型数据库管理系统”,而 Bigtable 对于读密集和写密集的应用程序都提供良好的性能

Bigtable 的负载平衡器需要解决一些与share-nothing数据库面临的负载和内存平衡问题相同的问题(例如,Copeland 等人[1988]和 Stonebraker 等人[1994])。我们的问题略微简单:(1) 我们不考虑可能存在多个相同数据的副本,这些副本可能由于视图或索引的不同而采用不同的形式;(2) 我们让用户告诉我们哪些数据应该存储在内存中,哪些数据应该保留在磁盘上,而不是动态地确定;(3) 我们没有需要执行或优化的复杂查询。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值