。 每个随机读操作都要通过网络从GFS传输64KB的SSTable到Tablet服务器,而我们只使用其中大小是1000 byte的一个value值。Tablet服务器每秒大约执行1200次读操作,也就是每秒大约从GFS读取75MB的数据。这个传输带宽足以占满Tablet服务器的CPU时间,因为其中包括了网络协议栈的消耗、SSTable解析、以及BigTable代码执行;这个带宽也足以占满我们系统中网络的链接带宽。大多数采用这种访问模式BigTable应用程序会减小Block的大小,通常会减到8KB。内存中的随机读操作速度快很多,原因是,所有1000-byte的读操作都是从Tablet服务器的本地内存中读取数据,不需要从GFS读取64KB的Block。随机和序列写操作的性能比随机读要好些,原因是每个Tablet服务器直接把写入操作的内容追加到一个Commit日志文件的尾部,并且采用批量提交的方式,通过把数据以流的方式写入到GFS来提高性能。随机写和序列写在性能上没有太大的差异,这两种方式的写操作实际上都是把操作内容记录到同一个Tablet服务器的Commit日志文件中。序列读的性能好于随机读,因为每取出64KB的SSTable的Block后,这些数据会缓存到Block缓存中,后续的64次读操作直接从缓存读取数据。扫描的性能更高,这是由于客户程序每一次RPC调用都会返回大量的value的数据,所以,RPC调用的消耗基本抵消了。
随着我们将系统中的Tablet服务器从1台增加到500台,系统的整体吞吐量有了梦幻般的增长,增长的倍率超过了100。比如,随着Tablet服务器的数量增加了500倍,内存中的随机读操作的性能增加了300倍。之所以会有这样的性能提升,主要是因为这个基准测试的瓶颈是单台Tablet服务器的CPU。尽管如此,性能的提升还不是线性的。在大多数的基准测试中我们看到,当Tablet服务器的数量从1台增加到50台时,每台服务器的吞吐量会有一个明显的下降。这是由于多台服务器间的负载不均衡造成的,大多数情况下是由于其它的程序抢占了CPU。 我们负载均衡的算法会尽量避免这种不均衡,但是基于两个主要原因,这个算法并不能完美的工作:一个是尽量减少Tablet的移动导致重新负载均衡能力受限(如果Tablet被移动了,那么在短时间内 -- 一般是1秒内 -- 这个Tablet是不可用的),另一个是我们的基准测试程序产生的负载会有波动
(alex注:the load generated by our benchmarks shifts around as the benchmark progresses)。随机读基准测试的测试结果显示,随机读的性能随Tablet服务器数量增加的提升幅度最小(整体吞吐量只提升了100倍,而服务器的数量却增加了500倍)。这是因为每个1000-byte的读操作都会导致一个64KB大的Block在网络上传输。这样的网络传输量消耗了我们网络中各种共享的1GB的链路,结果导致随着我们增加服务器的数量,每台服务器上的吞吐量急剧下降。
8 实际应用
截止到2006年8月,Google内部一共有388个非测试用的Bigtable集群运行在各种各样的服务器集群上,合计大约有24500个Tablet服务器。表1显示了每个集群上Tablet服务器的大致分布情况。这些集群中,许多用于开发目的,因此会有一段时期比较空闲。通过观察一个由14个集群、8069个Tablet服务器组成的集群组,我们看到整体的吞吐量超过了每秒1200000次请求,发送到系统的RPC请求导致的网络负载达到了741MB/s,系统发出的RPC请求网络负载大约是16GB/s。
表2提供了一些目前正在使用的表的相关数据。一些表存储的是用户相关的数据,另外一些存储的则是用于批处理的数据;这些表在总的大小、 每个数据项的平均大小、从内存中读取的数据的比例、表的Schema的复杂程度上都有很大的差别。本节的其余部分,我们将主要描述三个产品研发团队如何使用Bigtable的。
8.1 Google Analytics
Google Analytics是用来帮助Web站点的管理员分析他们网站的流量模式的服务。它提供了整体状况的统计数据,比如每天的独立访问的用户数量、每天每个URL的浏览次数;它还提供了用户使用网站的行为报告,比如根据用户之前访问的某些页面,统计出几成的用户购买了商品。为了使用这个服务,Web站点的管理员只需要在他们的Web页面中嵌入一小段JavaScript脚本就可以了。这个Javascript程序在页面被访问的时候调用。它记录了各种Google Analytics需要使用的信息,比如用户的标识、获取的网页的相关信息。Google Analytics汇总这些数据,之后提供给Web站点的管理员。我们粗略的描述一下Google Analytics使用的两个表。Row Click表(大约有200TB数据)的每一行存放了一个最终用户的会话。行的名字是一个包含Web站点名字以及用户会话创建时间的元组。这种模式保证了对同一个Web站点的访问会话是顺序的,会话按时间顺序存储。这个表可以压缩到原来尺寸的14%。 Summary表(大约有20TB的数据)包含了关于每个Web站点的、各种类型的预定义汇总信息。一个周期性运行的MapReduce任务根据Raw Click表的数据生成Summary表的数据。每个MapReduce工作进程都从Raw Click表中提取最新的会话数据。系统的整体吞吐量受限于GFS的吞吐量。这个表的能够压缩到原有尺寸的29%。
8.2 Google Earth
Google通过一组服务为用户提供了高分辨率的地球表面卫星图像,访问的方式可以使通过基于Web的Google Maps访问接口(maps.google.com),也可以通过Google Earth定制的客户端软件访问。这些软件产品允许用户浏览地球表面的图像:用户可以在不同的分辨率下平移、查看和注释这些卫星图像。这个系统使用一个表存储预处理数据,使用另外一组表存储用户数据。数据预处理流水线使用一个表存储原始图像。在预处理过程中,图像被清除,图像数据合并到最终的服务数据中。这个表包含了大约70TB的数据,所以需要从磁盘读取数据。图像已经被高效压缩过了,因此存储在Bigtable后不需要再压缩了。 Imagery表的每一行都代表了一个单独的地理区域。行都有名称,以确保毗邻的区域存储在了一起。Imagery表中有一个列族用来记录每个区域的数据源。这个列族包含了大量的列:基本上市每个列对应一个原始图片的数据。由于每个地理区域都是由很少的几张图片构成的,因此这个列族是非常稀疏的。数据预处理流水线高度依赖运行在Bigtable上的MapReduce任务传输数据。在运行某些MapReduce任务的时候,整个系统中每台Tablet服务器的数据处理速度是1MB/s。这个服务系统使用一个表来索引GFS中的数据。这个表相对较小(大约是500GB),但是这个表必须在保证较低的响应延时的前提下,针对每个数据中心,每秒处理几万个查询请求。 因此,这个表必须在上百个Tablet服务器上存储数据,并且使用in-memory的列族。
8.3 个性化查询
个性化查询()是一个双向服务;这个服务记录用户的查询和点击,涉及到各种Google的服务,比如Web查询、图像和新闻。用户可以浏览他们查询的历史,重复他们之前的查询和点击;用户也可以定制基于Google历史使用习惯模式的个性化查询结果。个性化查询使用Bigtable存储每个用户的数据。每个用户都有一个唯一的用户id,每个用户id和一个列名绑定。一个单独的列族被用来存储各种类型的行为(比如,有个列族可能是用来存储所有的Web查询的)。每个数据项都被用作Bigtable的时间戳,记录了相应的用户行为发生的时间。个性化查询使用以Bigtable为存储的MapReduce任务生成用户的数据图表。这些用户数据图表用来个性化当前的查询结果。个性化查询的数据会复制到几个Bigtable的集群上,这样就增强了数据可用性,同时减少了由客户端和Bigtable集群间的“距离”造成的延时。个性化查询的开发团队最初建立了一个基于Bigtable的、“客户侧”的复制机制为所有的复制节点提供一致性保障。现在的系统则使用了内建的复制子系统。个性化查询存储系统的设计允许其它的团队在它们自己的列中加入新的用户数据,因此,很多Google服务使用个性化查询存储系统保存用户级的配置参数和设置。在多个团队之间分享数据的结果是产生了大量的列族。为了更好的支持数据共享,我们加入了一个简单的配额机制
(alex注:quota,参考AIX的配额机制)限制用户在共享表中使用的空间;配额也为使用个性化查询系统存储用户级信息的产品团体提供了隔离机制。
9 经验教训
在设计、实现、维护和支持Bigtable的过程中,我们得到了很多有用的经验和一些有趣的教训。一个教训是,我们发现,很多类型的错误都会导致大型分布式系统受损,这些错误不仅仅是通常的网络中断、或者很多分布式协议中设想的fail-stop类型的错误
(alex注:fail-stop failture,指一旦系统fail就stop,不输出任何数据;fail-fast failture,指fail不马上stop,在短时间内return错误信息,然后再stop)。比如,我们遇到过下面这些类型的错误导致的问题:内存数据损坏、网络中断、时钟偏差、机器挂起、扩展的和非对称的网络分区(alex注:extended and asymmetric network partitions,不明白什么意思。partition也有中断的意思,但是我不知道如何用在这里)、我们使用的其它系统的Bug(比如Chubby)、GFS配额溢出、计划内和计划外的硬件维护。我们在解决这些问题的过程中学到了很多经验,我们通过修改协议来解决这些问题。比如,我们在我们的RPC机制中加入了Checksum。我们在设计系统的部分功能时,不对其它部分功能做任何的假设,这样的做法解决了其它的一些问题。比如,我们不再假设一个特定的Chubby操作只返回错误码集合中的一个值。 另外一个教训是,我们明白了在彻底了解一个新特性会被如何使用之后,再决定是否添加这个新特性是非常重要的。比如,我们开始计划在我们的API中支持通常方式的事务处理。但是由于我们还不会马上用到这个功能,因此,我们并没有去实现它。现在,Bigtable上已经有了很多的实际应用,我们可以检查它们真实的需求;我们发现,大多是应用程序都只是需要单个行上的事务功能。有些应用需要分布式的事务功能,分布式事务大多数情况下用于维护二级索引,因此我们增加了一个特殊的机制去满足这个需求。新的机制在通用性上比分布式事务差很多,但是它更有效(特别是在更新操作的涉及上百行数据的时候),而且非常符合我们的“跨数据中心”复制方案的优化策略。还有一个具有实践意义的经验:我们发现系统级的监控对Bigtable非常重要(比如,监控Bigtable自身以及使用Bigtable的客户程序)。比如,我们扩展了我们的RPC系统,因此对于一个RPC调用的例子,它可以详细记录代表了RPC调用的很多重要操作。这个特性允许我们检测和修正很多的问题,比如Tablet数据结构上的锁的内容、在修改操作提交时对GFS的写入非常慢的问题、以及在METADATA表的Tablet不可用时,对METADATA表的访问挂起的问题。关于监控的用途的另外一个例子是,每个Bigtable集群都在Chubby中注册了。这可以帮助我们跟踪所有的集群状态、监控它们的大小、检查集群运行的我们软件的版本、监控集群流入数据的流量,以及检查是否有引发集群高延时的潜在因素。对我们来说,最宝贵的经验是简单设计的价值。考虑到我们系统的代码量(大约100000行生产代码
(alex注:non-test code)),以及随着时间的推移,新的代码以各种难以预料的方式加入系统,我们发现简洁的设计和编码给维护和调试带来的巨大好处。这方面的一个例子是我们的Tablet服务器成员协议。我们第一版的协议很简单:Master服务器周期性的和Tablet服务器签订租约,Tablet服务器在租约过期的时候Kill掉自己的进程。不幸的是,这个协议在遇到网络问题时会大大降低系统的可用性,也会大大增加Master服务器恢复的时间。我们多次重新设计这个协议,直到它能够很好的处理上述问题。但是,更不幸的是,最终的协议过于复杂了,并且依赖一些Chubby很少被用到的特性。我们发现我们浪费了大量的时间在调试一些古怪的问题(alex注:obscure corner cases),有些是Bigtable代码的问题,有些事Chubby代码的问题。最后,我们只好废弃了这个协议,重新制订了一个新的、更简单、只使用Chubby最广泛使用的特性的协议。
10 相关工作
Boxwood【24】项目的有些组件在某些方面和Chubby、GFS以及Bigtable类似,因为它也提供了诸如分布式协议、锁、分布式Chunk存储以及分布式B-tree存储。Boxwood与Google的某些组件尽管功能类似,但是Boxwood的组件提供更底层的服务。Boxwood项目的目的是提供创建类似文件系统、数据库等高级服务的基础构件,而Bigtable的目的是直接为客户程序的数据存储需求提供支持。现在有不少项目已经攻克了很多难题,实现了在广域网上的分布式数据存储或者高级服务,通常是“Internet规模”的。这其中包括了分布式的Hash表,这项工作由一些类似CAN【29】、Chord【32】、Tapestry【37】和Pastry【30】的项目率先发起。这些系统的主要关注点和Bigtable不同,比如应对各种不同的传输带宽、不可信的协作者、频繁的更改配置等;另外,去中心化和Byzantine灾难冗余
(alex注:Byzantine,即拜占庭式的风格,也就是一种复杂诡秘的风格。Byzantine Fault表示:对于处理来说,当发错误时处理器并不停止接收输出,也不停止输出,错就错了,只管算,对于这种错误来说,这样可真是够麻烦了,因为用户根本不知道错误发生了,也就根本谈不上处理错误了。在多处理器的情况下,这种错误可能导致运算正确结果的处理器也产生错误的结果,这样事情就更麻烦了,所以一定要避免处理器产生这种错误。)也不是Bigtable的目的。就提供给应用程序开发者的分布式数据存储模型而言,我们相信,分布式B-Tree或者分布式Hash表提供的Key-value pair方式的模型有很大的局限性。Key-value pair模型是很有用的组件,但是它们不应该是提供给开发者唯一的组件。我们选择的模型提供的组件比简单的Key-value pair丰富的多,它支持稀疏的、半结构化的数据。另外,它也足够简单,能够高效的处理平面文件;它也是透明的(通过局部性群组),允许我们的使用者对系统的重要行为进行调整。有些数据库厂商已经开发出了并行的数据库系统,能够存储海量的数据。Oracle的RAC【27】使用共享磁盘存储数据(Bigtable使用GFS),并且有一个分布式的锁管理系统(Bigtable使用Chubby)。IBM并行版本的DB2【4】基于一种类似于Bigtable的、不共享任何东西的架构(a shared-nothing architecture)【33】。每个DB2的服务器都负责处理存储在一个关系型数据库中的表中的行的一个子集。这些产品都提供了一个带有事务功能的完整的关系模型。 Bigtable的局部性群组提供了类似于基于列的存储方案在压缩和磁盘读取方面具有的性能;这些以列而不是行的方式组织数据的方案包括C-Store【1,34】、商业产品Sybase IQ【15,36】、SenSage【31】、KDB+【22】,以及MonetDB/X100【38】的ColumnDM存储层。另外一种在平面文件中提供垂直和水平数据分区、并且提供很好的数据压缩率的系统是AT&T的Daytona数据库【19】。局部性群组不支持Ailamaki系统中描述的CPU缓存级别的优化【2】。 Bigtable采用memtable和SSTable存储对表的更新的方法与Log-Structured Merge Tree【26】存储索引数据更新的方法类似。这两个系统中,排序的数据在写入到磁盘前都先存放在内存中,读取操作必须从内存和磁盘中合并数据产生最终的结果集。 C-Store和Bigtable有很多相似点:两个系统都采用Shared-nothing架构,都有两种不同的数据结构,一种用于当前的写操作,另外一种存放“长时间使用”的数据,并且提供一种机制在两个存储结构间搬运数据。两个系统在API接口函数上有很大的不同:C-Store操作更像关系型数据库,而Bigtable提供了低层次的读写操作接口,并且设计的目标是能够支持每台服务器每秒数千次操作。C-Store同时也是个“读性能优化的关系型数据库”,而Bigtable对读和写密集型应用都提供了很好的性能。 Bigtable也必须解决所有的Shared-nothing数据库需要面对的、类型相似的一些负载和内存均衡方面的难题(比如,【11,35】)。我们的问题在某种程度上简单一些:(1)我们不需要考虑同一份数据可能有多个拷贝的问题,同一份数据可能由于视图或索引的原因以不同的形式表现出来;(2)我们让用户决定哪些数据应该放在内存里、哪些放在磁盘上,而不是由系统动态的判断;(3)我们的系统中没有复杂的查询执行或优化工作。
11 结论
我们已经讲述完了Bigtable,Google的一个分布式的结构化数据存储系统。Bigtable的集群从2005年4月开始已经投入使用了,在此之前,我们花了大约7人年设计和实现这个系统。截止到2006年4月,已经有超过60个项目使用Bigtable了。我们的用户对Bigtable提供的高性能和高可用性很满意,随着时间的推移,他们可以根据自己的系统对资源的需求增加情况,通过简单的增加机器,扩展系统的承载能力。由于Bigtable提供的编程接口并不常见,一个有趣的问题是:我们的用户适应新的接口有多难?新的使用者有时不太确定使用Bigtable接口的最佳方法,特别是在他们已经习惯于使用支持通用事务的关系型数据库的接口的情况下。但是,Google内部很多产品都成功的使用了Bigtable的事实证明了,我们的设计在实践中行之有效。我们现在正在对Bigtable加入一些新的特性,比如支持二级索引,以及支持多Master节点的、跨数据中心复制的Bigtable的基础构件。我们现在已经开始将Bigtable部署为服务供其它的产品团队使用,这样不同的产品团队就不需要维护他们自己的Bigtable集群了。随着服务集群的扩展,我们需要在Bigtable系统内部处理更多的关于资源共享的问题了【3,5】。最后,我们发现,建设Google自己的存储解决方案带来了很多优势。通过为Bigtable设计我们自己的数据模型,是我们的系统极具灵活性。另外,由于我们全面控制着Bigtable的实现过程,以及Bigtable使用到的其它的Google的基础构件,这就意味着我们在系统出现瓶颈或效率低下的情况时,能够快速的解决这些问题。
Acknowledgements
We thank the anonymous reviewers, David Nagle, and our shepherd Brad Calder, for their feedback on this paper.The Bigtable system has benefited greatly from the feedback of our many users within Google. In addition,we thank the following people for their contributions to Bigtable: Dan Aguayo, Sameer Ajmani, Zhifeng Chen,Bill Coughran, Mike Epstein, Healfdene Goguen, Robert Griesemer, Jeremy Hylton, Josh Hyman, Alex Khesin, Joanna Kulik, Alberto Lerner, Sherry Listgarten, Mike Maloney, Eduardo Pinheiro, Kathy Polizzi, Frank Yellin,and Arthur Zwiegincew.
References
[1] ABADI, D. J., MADDEN, S. R., AND FERREIRA, M. C. Integrating compression and execution in columnoriented database systems. Proc. of SIGMOD (2006). [2] AILAMAKI, A., DEWITT, D. J., HILL, M. D., AND SKOUNAKIS, M. Weaving relations for cache performance.In The VLDB Journal (2001), pp. 169-180. [3] BANGA, G., DRUSCHEL, P., AND MOGUL, J. C. Resource containers: A new facility for resource management in server systems. In Proc. of the 3rd OSDI (Feb. 1999), pp. 45-58. [4] BARU, C. K., FECTEAU, G., GOYAL, A., HSIAO, H., JHINGRAN, A., PADMANABHAN, S., COPELAND,G. P., AND WILSON, W. G. DB2 parallel edition. IBM Systems Journal 34, 2 (1995), 292-322. [5] BAVIER, A., BOWMAN, M., CHUN, B., CULLER, D., KARLIN, S., PETERSON, L., ROSCOE, T., SPALINK, T., AND WAWRZONIAK, M. Operating system support for planetary-scale network services. In Proc. of the 1st NSDI(Mar. 2004), pp. 253-266. [6] BENTLEY, J. L., AND MCILROY, M. D. Data compression using long common strings. In Data Compression Conference (1999), pp. 287-295. [7] BLOOM, B. H. Space/time trade-offs in hash coding with allowable errors. CACM 13, 7 (1970), 422-426. [8] BURROWS, M. The Chubby lock service for looselycoupled distributed systems. In Proc. of the 7th OSDI (Nov. 2006). [9] CHANDRA, T., GRIESEMER, R., AND REDSTONE, J.Paxos made live ? An engineering perspective. In Proc. of PODC (2007). [10] COMER, D. Ubiquitous B-tree. Computing Surveys 11, 2 (June 1979), 121-137. [11] COPELAND, G. P., ALEXANDER, W., BOUGHTER, E. E., AND KELLER, T. W. Data placement in Bubba. In Proc. of SIGMOD (1988), pp. 99-108. [12] DEAN, J., AND GHEMAWAT, S. MapReduce: Simplified data processing on large clusters. In Proc. of the 6th OSDI (Dec. 2004), pp. 137-150. [13] DEWITT, D., KATZ, R., OLKEN, F., SHAPIRO, L., STONEBRAKER, M., AND WOOD, D. Implementation techniques for main memory database systems. In Proc. of SIGMOD (June 1984), pp. 1-8. [14] DEWITT, D. J., AND GRAY, J. Parallel database systems: The future of high performance database systems. CACM 35, 6 (June 1992), 85-98. [15] FRENCH, C. D. One size ts all database architectures do not work for DSS. In Proc. of SIGMOD (May 1995), pp. 449-450. [16] GAWLICK, D., AND KINKADE, D. Varieties of concurrency control in IMS/VS fast path. Database Engineering Bulletin 8, 2 (1985), 3-10. [17] GHEMAWAT, S., GOBIOFF, H., AND LEUNG, S.-T. The Google file system. In Proc. of the 19th ACM SOSP (Dec.2003), pp. 29-43. [18] GRAY, J. Notes on database operating systems. In Operating Systems ? An Advanced Course, vol. 60 of Lecture Notes in Computer Science. Springer-Verlag, 1978. [19] GREER, R. Daytona and the fourth-generation language Cymbal. In Proc. of SIGMOD (1999), pp. 525-526. [20] HAGMANN, R. Reimplementing the Cedar file system using logging and group commit. In Proc. of the 11th SOSP (Dec. 1987), pp. 155-162. [21] HARTMAN, J. H., AND OUSTERHOUT, J. K. The Zebra striped network file system. In Proc. of the 14th SOSP(Asheville, NC, 1993), pp. 29-43. [22] KX.COM. kx.com/products/database.php. Product page. [23] LAMPORT, L. The part-time parliament. ACM TOCS 16,2 (1998), 133-169. [24] MACCORMICK, J., MURPHY, N., NAJORK, M., THEKKATH, C. A., AND ZHOU, L. Boxwood: Abstractions as the foundation for storage infrastructure. In Proc. of the 6th OSDI (Dec. 2004), pp. 105-120. [25] MCCARTHY, J. Recursive functions of symbolic expressions and their computation by machine. CACM 3, 4 (Apr. 1960), 184-195. [26] O'NEIL, P., CHENG, E., GAWLICK, D., AND O'NEIL, E. The log-structured merge-tree (LSM-tree). Acta Inf. 33, 4 (1996), 351-385. [27] ORACLE.COM. . Product page. [28] PIKE, R., DORWARD, S., GRIESEMER, R., AND QUINLAN, S. Interpreting the data: Parallel analysis with Sawzall. Scientific Programming Journal 13, 4 (2005), 227-298. [29] RATNASAMY, S., FRANCIS, P., HANDLEY, M., KARP, R., AND SHENKER, S. A scalable content-addressable network. In Proc. of SIGCOMM (Aug. 2001), pp. 161-172. [30] ROWSTRON, A., AND DRUSCHEL, P. Pastry: Scalable, distributed object location and routing for largescale peer-to-peer systems. In Proc. of Middleware 2001(Nov. 2001), pp. 329-350. [31] SENSAGE.COM. sensage.com/products-sensage.htm. Product page. [32] STOICA, I., MORRIS, R., KARGER, D., KAASHOEK, M. F., AND BALAKRISHNAN, H. Chord: A scalable peer-to-peer lookup service for Internet applications. In Proc. of SIGCOMM (Aug. 2001), pp. 149-160. [33] STONEBRAKER, M. The case for shared nothing. Database Engineering Bulletin 9, 1 (Mar. 1986), 4-9. [34] STONEBRAKER,M., ABADI, D. J., BATKIN, A., CHEN, X., CHERNIACK, M., FERREIRA, M., LAU, E., LIN, A., MADDEN, S., O'NEIL, E., O'NEIL, P., RASIN, A., TRAN, N., AND ZDONIK, S. C-Store: A columnoriented DBMS. In Proc. of VLDB (Aug. 2005), pp. 553-564. [35] STONEBRAKER, M., AOKI, P. M., DEVINE, R., LITWIN, W., AND OLSON, M. A. Mariposa: A new architecture for distributed data. In Proc. of the Tenth ICDE(1994), IEEE Computer Society, pp. 54-65. [36] SYBASE.COM. . Product page. [37] ZHAO, B. Y., KUBIATOWICZ, J., AND JOSEPH, A. D. Tapestry: An infrastructure for fault-tolerant wide-area location and routing. Tech. Rep. UCB/CSD-01-1141, CS Division, UC Berkeley, Apr. 2001. [38] ZUKOWSKI, M., BONCZ, P. A., NES, N., AND HEMAN, S. MonetDB/X100 ?A DBMS in the CPU cache. IEEE Data Eng. Bull. 28, 2 (2005), 17-22.