HBase实战

978-7-115-32446-7
作者: 【美】Nick Dimiduk Amandeep Khurana
译者: 谢磊
编辑: 杨海玲
分类: HBase

图书目录:

详情

本书囊括了使用HBase设计、构建和运行应用程序所需的所有知识和实用技术。全书共分为4个部分。前两个部分介绍首先介绍分布式系统和大规模数据处理的基础知识,讲解如何使用HBase;第三部分通过真正的应用程序和代码示例,结合足够的理论,探索HBase的一些实用技术;第四部分讲解如何把原型开发系统升级为羽翼丰满的生产系统。书中囊括了使用HBase设计、构建和运行应用程序所需的所有知识。

图书摘要

MANNING

HBase实战

HBase IN ACTION

[美]Nick Dimiduk Amandeep Khurana 著

谢磊 译

人民邮电出版社

北京

图书在版编目(CIP)数据

HBase实战/(美)迪米达克(Dimiduk,N.),(美)卡拉纳(Khurana,A.)著;谢磊译.--北京:人民邮电出版社,2013.9(2018.5重印)

书名原文:HBase in Action

ISBN 978-7-115-32446-7

Ⅰ.①H… Ⅱ.①迪…②卡…③谢… Ⅲ.①计算机—网络—信息存贮 Ⅳ.①TP393

中国版本图书馆CIP数据核字(2013)第144722号

◆著 [美]Nick Dimiduk Amandeep Khurana

译 谢磊

责任编辑 杨海玲

责任印制 程彦红 杨林杰

◆人民邮电出版社出版发行  北京市丰台区成寿寺路11号

邮编 100164  电子邮件 315@ptpress.com.cn

网址 http://www.ptpress.com.cn

北京九州迅驰传媒文化有限公司印刷

◆开本:800×1000 1/16

印张:21.25

字数:458千字  2013年9月第1版

印数:10401-10700册  2018年5月北京第14次印刷

著作权合同登记号 图字:01-2013-0774号

定价:69.00元

读者服务热线:(010)81055410 印装质量热线:(010)81055316

反盗版热线:(010)81055315

广告经营许可证:京东工商广登字20170147号

版权声明

Original English language edition, entitled HBase in Action by Nick Dimiduk and Amandeep Khurana, published by Manning Publications Co., 209 Bruce Park Avenue, Greenwich, CT 06830.

Copyright ©2013 by Manning Publications Co.

Simplified Chinese-language edition copyright ©2013 by Posts & Telecom Press. All rights reserved.

本书中文简体字版由Manning Publications Co.授权人民邮电出版社独家出版。未经出版者书面许可,不得以任何方式复制或抄袭本书内容。

版权所有,侵权必究。

内容提要

HBase是一种NoSQL存储系统,专门设计用来快速随机读写大规模数据。HBase运行在普通商用服务器上,可以平滑扩展,以支持从中等规模到数十亿行、数百万列的数据集。

本书是一本基于经验提炼而成的指南,它教给读者如何运用HBase设计、搭建及运行大数据应用系统。全书共分为4个部分。前两个部分分别介绍了分布式系统和大规模数据处理的发展历史,讲解HBase的基本原理模式设计以及如何使用HBase的高级特性;第三部分通过真实的应用和代码示例以及支持这些实践技巧的理论知识,进一步探索HBase的一些实用技术;第四部分讲解如何把原型开发系统升级为羽翼丰满的生产系统。

本书适合所有对云计算、大数据处理技术和NoSQL数据库感兴趣的技术人员阅读,尤其适合对Hadoop及HBase感兴趣的技术人员参考。阅读本书不要求之前具备HBase、Hadoop或者MapReduce方面的知识。

译者序

互联网技术已飞速发展十几年,移动互联网的崛起更是如火如荼,基于iOS和Android平台的智能手机在中国已是遍地开花,使得用户接入互联网的方式和用户行为正在发生翻天覆地的变化;由量变引发质变,各行各业无论愿意与否,也在不知不觉中经历着深刻变革。这种变化映射到后台,一个决定性的基础环节就是——大数据。是的,不是“数据”,而是“大数据”!现在,无论在数据规模、数据类型、数据来源上,与几年前已经截然不同。这是摆在很多企业和个人面前的一个机会,同时也是一个挑战!数据不必然等于信息,也不必然等于价值,只有经过性能优异的大数据技术平台的缜密管理,才可以发挥“大数据”的威力,才能真正挖掘出商业价值。

近年来,各种管理数据的技术在不断创新,其中Hadoop开源产品系列在商业实践中取得了广泛认可,几近成为事实上的大数据管理行业标准平台。而HBase正是Hadoop产品系列里的分布式数据库平台,主要应用于在线应用系统。当访问淘宝、FaceBook,或者访问搜索引擎、电商门户、视频网站时,你或多或少已经使用了某些基于HBase的应用服务。在互联网公司里,HBase和Hadoop的应用已经有些年头了。现在的情况是,越来越多的传统企业也对它们表现出了浓厚的兴趣。在电信、金融、生物制药、智能交通、医疗、智能电网等行业,越来越多的企业用户和解决方案提供商正在尝试使用HBase和Hadoop等技术,如果有一天你发现你的话费清单数据实际上来自于HBase系统而不是Oracle系统,请不要感到奇怪。

大数据的概念已经被宣传得有些泛滥,但是如何搭建一个性能优异的、高性价比的大数据解决方案却谈得很不够。《HBase实战》正是谈论这个话题的经典书籍,我希望本书在国内翻译出版,有助于宣传和推广HBase和Hadoop技术,把大数据解决方案成功地应用于更多的行业。

本书始终沿着一条主线由浅入深地逐步展开,那就是如何基于HBase搭建符合生产要求的应用系统。此外,本书还剖析了两个实际使用中的应用系统,一方面验证前面介绍的设计技巧和系统特性;另一方面也为你自己的应用系统设计提供一些思路和启发。最后,本书还简要总结了HBase运维方面的重要内容。总体来看,HBase和传统关系型数据库的设计初衷有很大不同,所以设计基于HBase的应用系统也大有不同。简单来说,针对高吞吐量、高可扩展能力的场合,HBase的表现相当令人惊讶。HBase的使用场景还在不断扩展,如果你对此感兴趣,可以通过网络搜索找到更多信息。

HBase和Hadoop现在都是Apache软件基金会的顶级项目,是开源软件世界的杰作,它们的思想源自Google的三大论文。一个成功的开源项目背后往往有一个兴旺的开源社区,HBase和Hadoop也是如此。但是,由于语言的障碍,以及国内和国外沟通偏好的差别,国内的朋友参与国外的开源社区时,可能会有一些不便利之处。基于这个考虑,我发起建立了ChinaHadoop社区(http://ChinaHadoop.net),这里汇集了许多国内一线互联网公司数据平台的技术专家,希望能够成为国内大数据领域最有活力的互动和分享平台,将Hadoop的开源及分享精神发扬光大。借此机会诚邀你参与进来!

在本书的翻译过程中,我得到了来自ChinaHadoop社区技术专家的大力支持。其中,卢亿雷审校了序言、第1、7、8章,搜狗的冼茂源审校了第4、5章,神州数码的何德芳审校了第9、10章,新浪的袁康审校了第2、3、6章,在此表示衷心感谢!

感谢华崧、杨智樟、杜航等朋友,作为本书早期的读者,他们给出了很多有建设性的反馈意见。

此外,本书的责任编辑杨海玲女士及其团队在整个翻译过程中不断给予反馈和建议,在此表示衷心的感谢。

感谢我的家人,他们总是默默地给予我最大的支持和包容,让我能够集中全部精力投入到翻译中;本书的翻译占用了大量的业余时间,即使是4岁的天予宝宝也知道不要打扰爸爸。

于我而言,翻译本书的过程也是一个学习的过程;译文中若有错误或者不足之处,敬请读者给予指正,以便能够不断改进。来信请联系邮箱ChinaHadoop@sina.com,或者联系新浪微博@ChinaHadoop。本书勘误也会及时公布于网站:http://ChinaHadoop.net。

谢磊

2013年6月25日于照澜院

总体而言,HBase就像原子弹一样,正反两面特点鲜明。一方面,它的基本操作如此简单,似乎在酒杯边的一两张餐巾纸的背面就可以解释清楚,另一方面,它的部署却是另一回事儿,相当复杂。

HBase由多个灵活的部件构成,分布式的HBase应用系统包括许多客户端和服务器进程。例如,HBase在Hadoop分布式文件系统(Hadoop Distributed File System)上存储;此外,HBase使用了另一个分布式系统Apache ZooKeeper来管理整个集群状态;还有,大多数的部署都用到MapReduce,用来批量加载数据或者运行分布式的全表扫描等任务。显然,近乎完美地把各个部分组合在一起是相当不容易的。

构建合适的环境和做出适当的配置对于HBase来说是至关重要的。HBase作为一种通用的数据存储,可以广泛用在各种各样的应用系统中。它的默认设置选择了保守的做法,主要面对通用的使用场景和常见的硬件规格。它的适应能力或者说自我调整能力还有很大空间,所以你可以根据实际的硬件和负载情况来调整HBase,但往往需要经过多次尝试后才可以得到正确的配置。

仅仅做出适当的配置还不够,对HBase的数据模式模型也必须给予足够重视。如果数据模式和数据存储的检索方式不匹配,再合适的配置方案也于事无补。相反,如果模式和数据检索方式琴瑟和谐,性能就会得到巨大的提升。习惯了关系型数据库思维的人们往往不习惯HBase模式建模。使用HBase这样的列式数据库和使用MySQL这样的关系型数据库相比,尽管有些相似之处,但还是有许多不同的技巧。

如果你需要上述帮助,这本书就是为你量身定制的;这本书还可以在其他方面提供帮助,如如何往HBase核心里增加自定义功能,什么是良好的HBase应用系统设计,等等。Amandeep和Nick使用了适当的、饱含实践经验的文字,浅显易懂地告诉你怎样使用HBase。这本书可以帮助那些基于HBase部署应用系统的人们。

Nick和Amandeep是有真材实料的老师,他们都是长期的HBase实践者。回忆往昔,多年前 Amandeep 来到旧金山加入我们早期的周末黑客马拉松的时候,我们挤在他的ThinkPad旧笔记本电脑旁边,在HBase项目早期版本上努力调试数据的场景。

他在项目邮件列表上帮助了很多人,对于HBase社区贡献良多。不久之后,Nick也出现了,不时地在HBase项目中崭露头角,添砖加瓦。他们拿出时间研究和编纂自己的经验,把这本书贡献给了HBase社区。

你可能打算阅读这本书,也可能打算下载使用HBase,但是请不要错过HBase最宝贵的东西——开发者社区。围绕HBase项目,一个多功能的、热情的开发者社区已经成长起来了,并且正在推动项目全力发展。像Amandeep、Nick和我自己这样的成员,最让我们自豪的就是我们的社区。尽管Facebook、华为、Cloudera和Salesforce等大公司对于HBase的发展贡献也很大,但是社区的形成不是因为公司,而是因为我们这些参与的个体。请考虑加入进来吧,我们欢迎你。

Michael Stack

Apache HBase项目管理委员会主席

致HBase社区的一封信

在讨论现状之前,请允许我把时间倒退几年,看看HBase是怎么开始的。

2007年,我需要一个大规模的、可扩展的数据存储方案,但是几乎没有预算,所以也就没有多少选择。要么使用免费开源数据库,如MySQL或者PostgreSQL;要么使用像Berkeley DB这样的纯键值数据库;要么选择自己开发,这可是一个新领域,至少在当时你需要足够勇敢才会这么尝试。

当时已有的解决方案或许也可以用,但是对它们最大的顾虑是可扩展性。在这一点上当时的系统做得并不好,往往需要事后补救。我需要存储数十亿个文档,维护一个关于它们的搜索索引,要求支持数据随机更新并且同时快速更新索引。这些需求让我选择了第三种方式:Hadoop和HBase。

这两个产品有着强大的血统,它们都源自Google公司,这是一个每当提到可扩展系统就能想到的群英汇集的殿堂。我相信,如果这些系统可以服务于世界上最大的用户,它们一定是牢固可靠的。因此,我选择使用HBase(还有Lucene)构建我的系统。

在2007年,这种选择不多,很容易决定。但是再往后几年,这个新兴领域逐渐成长壮大,我们看到了许多有竞争力的和补充的解决方案。于是大家使用专用术语NoSQL来把这些分布式数据库归为一类。这个专用术语一直伴随着长期的、有时也显得没有意义的争论;对我来说,有意义的是可用的选择越来越多了。

定位各种新生数据库系统的基础是比较它们的功能特性:强一致性和最终一致性(两者用来满足不同的特定需求)。人们再一次以这种方式衡量HBase和它的同类产品,例如,使用Eric Brewer的CAP定理来衡量。随之而来的是一场激烈的讨论,什么是最重要的:是强一致性?还是即使在灾难情况下部分系统硬件故障时还可以保证数据服务?

和前面一样,对我而言,这是个选择的问题。我学会的是,你打算使用一个系统就要先全面了解它。今天我们选择余地很大,解决方案也有重叠和相似之处;我的选择并不意味着其他解决方案等而下之。你应该成为一个能够区分它们的专家,然后根据你手边的问题做出最佳选择。

我们就是这样选择了HBase,一直使用到今天。毫无疑问,大名鼎鼎的大型网络公司用户提升了HBase的声誉,证实了HBase可以胜任特定的使用场景。这些公司都有一个重要的优势:它们雇用了非常有经验的工程师。但是,许多小型公司使用HBase和基于它的应用系统并不顺利。我们需要有人用一种简单易懂的方式指导大家如何在HBase上轻松搭建验证过的、成熟的使用场景。

应该怎样设计模式(schema)来存储复杂的数据以保证读写性能的均衡?应该怎样规划数据的访问方式来保证最大限度地发挥HBase集群的威力?如果你订阅了公共邮件列表,类似问题还有很多。Amandeep和Nick会在这些地方帮助大家。他们在各种用户场景下使用HBase的丰富的实战经验可以帮你了解使用正确的数据模式和访问方式的复杂性,帮你成功构建下一个项目。

HBase会有什么样的未来呢?我相信前程远大!同样的技术仍然在Google公司承载着数量众多的产品和系统,反对的观点被证实是错误的,HBase社区也成长为我参加过的最健康的社区之一。我要表达我的感谢,给那些推举我为Fellow Member的人,给那些每天提交代码和补丁使HBase变得更好的人,给那些主动在HBase上投入全职工程师的公司,也要给HBase项目管理委员会。这绝对是一个我所知道的最真诚的群体。

最后,非常感谢Nick和Amandeep写了这本书。这本书有助于实现HBase的价值,有助于传播开源理念。在他们开始写这本书之前我们就认识了,他们有些顾虑。当时我支持说:这是你们能够为HBase和社区所做的最棒的事情。作为个人,能够成为社区的一分子我感到谦卑和自豪。

Lars George

HBase Committer

前言

2008年秋季我开始和HBase结缘,当时它还是一个新生项目,一年前刚刚发布。早期版本出来时,HBase表现很不错,但是也不是没有令人尴尬的缺陷。HBase项目当时有近10个软件Committer,作为一个Apache子项目还算不错。接下来是NoSQL宣传的高潮。当时专有名词NoSQL还没有出现,但是随后的一年这个术语变成了通俗用语。没有人能够说清楚为什么NoSQL重要,只知道它就是重要,反正数据领域开源社区的每个人都对这个概念很着迷。社区中有两种声音,有人批评关系型数据库,批评它愚不可及的严谨;有人嘲笑新技术,嘲笑它不够成熟。

大部分探索新技术的人来自于互联网公司,当时我就在一家致力于社交媒体内容分析的创业公司工作。那时候Facebook仍在强调隐私政策,而Twitter还不够大,其著名的报错页面“失败的鲸鱼”(Fail Whale)还没有问世。当时我们的兴趣点主要在博客上。在此前一家公司我花了3年好时光专注于层次型数据库引擎。我们广泛使用了Berkeley DB,所以我熟悉不使用SQL引擎的数据技术。在这家公司我加入了一个小团队,任务是构建一个新型数据管理平台。我们有一个MS SQL数据库,已经塞满了博客帖子和评论。当我们的日常分析作业耗时达到18小时时,我们都知道这个系统时日不多了。

在收集了基本需求后,我们着手寻找新型数据技术。我们的团队不大,一边维护现有系统,一边花了数月时间评估不同的选择。我们试验了不同的方法,并亲身感受了对数据手工分区的痛苦。我们研究了CAP定理和最终一致性,最后的结论是妥协。尽管HBase有缺点,我们还是决定选择它,我们认为开源技术的潜在好处超过了它的风险,并且说服了经理。

我在家里玩过Hadoop,但是从没有写过真正的MapReduce作业。我听说过HBase,但在这份新工作之前也没有特别关注过。随着时间推移,我们已经开始行动。我们申请了一些空闲机器和几个机架,然后就开工了。这家公司是.NET的地盘,我们得不到运维支持,所以我们学着使用bash和rsync,自己管理整个集群。

我加入了邮件列表和IRC频道,开始提问题。就在那个时候,我认识了Amandeep。他在忙于硕士论文,尝试把HBase运行到Hadoop以外的系统上。不久他完成学业,加入Amazon,搬到西雅图。在这个充满微软痕迹的城市中,我们两个是少有的HBase粉丝。随后两年很快过去了……

2010年秋季,第一次提出让我们写《HBase实战》。在我们看来,这很搞笑。为什么是我们这两个社区会员来写这本书?内部来看,这是一块难啃的骨头。《HBase权威指南》正在进展中,我们认识它的作者,我们深知在他面前的挑战。外部来看,我认为HBase只是一个“简单的键值数据库”。API只有5个基本概念,都不复杂。我们不想再写一本类似于《HBase权威指南》那样介绍内部机制的书,我也不相信应用开发人员从这类书中可以得到足够有价值的东西。

我们开始做头脑风暴,事情很快清楚了,我是错的。不仅可以找到足够的资料帮助用户,而且社区会员的角色使得我们成为写这本书的最佳人选。我们开始分门别类整理多年来我们使用这门技术累积下来的知识。这本书是我们8年来使用HBase实践经验的升华。它面向HBase的全新用户,可以指导大家跃过我们自己当年遇到过的障碍。我们尽可能多地收集和编纂了散布在社区里的内部知识。对于模糊的建议我们尽可能给出清晰的指导。我们希望你能发现这本书是一个完整的手册,可以帮助你顺利开始使用HBase,而不只是一个简单的问答列表。

HBase现在逐渐稳定了。我们开始时遇到过的大部分缺陷已经被解决、打上补丁,或者完全修改了架构。HBase正在接近1.0版本,在这个里程碑时刻我们很自豪自己是社区的一部分。我们很自豪把这份书稿提交给社区,希望它可以鼓舞和帮助下一代HBase用户。HBase最强大之处就是兴旺的社区,我们希望你加入到社区来,帮助社区在数据系统新时代继续创新。

Nick Dimiduk

当你看到这里的时候,你大概很想知道我是怎样进入HBase世界的。首先我要感谢你选择这本书来学习HBase,学习怎样使用HBase作为存储系统来搭建应用系统。希望你能找到有用的东西和实用技巧,以便更好地搭建应用系统,祝你成功。

我曾经在加州大学圣克鲁兹分校进行本科学习,当时我在思科公司找了一份兼职研究员的工作,专注于分布式系统。我所工作的团队当时在搭建一个数据集成框架,这个框架可以对数百种数据存储(包括但不限于大型关系型数据库管理系统)上的数据进行集成、索引和研究。我们开始寻找可以解决问题的系统和解决方案。我们评估了许多系统,从对象数据库到图形数据库,最后我们考虑基于Berkeley DB构建一个定制的分布式数据存储。显而易见的一个关键需求是可扩展性,但是我们并不想从头开始构建一个分布式系统。想想看,如果你为某个机构工作,打算构建一个定制的分布式数据库或者文件系统,最好先看看有没有现成的解决方案可以解决你的一部分问题。

基于这个原则,我们认为从头开始搭建新系统是不明智的,我们希望使用已有的技术。随后我们开始使用Hadoop系列产品,尝试了很多组件,在HBase上为数据集成系统搭建了概念验证原型系统。系统工作良好,扩展性也不错。HBase很适合解决这类问题,但是当时它们都是新生项目,能够保证我们成功的一个重要因素是它们的社区。HBase有着一个最热情的、最有活力的开源社区;当时社区规模要小得多,但是迄今为止其核心理念一直没有变化。

后来数据集成项目成了我的研究生论文。这个项目用HBase作为核心,因此我也越来越深入地参与到社区中。在邮件列表里和IRC频道里,开始我是问别人问题,后来我也回答别人的问题。在这段时间里我认识了Nick并了解了他在做什么。在为这个项目工作的过程中,我对这个技术和开源社区的兴趣和热爱与日俱增,我希望一直参与下去。

完成研究生学习后,我加入了位于西雅图的Amazon,开始做后端分布式系统项目的工作。我的大部分时间花在Elastic MapReduce团队那里,我们搭建了HBase托管服务的第一个版本。Nick也生活在西雅图,我们经常见面,讨论工作中的项目情况。2010年底,Manning出版社提出写《HBase实战》这本书。开始的时候我们觉得这个想法很搞笑,我记得对Nick说过:“不就是上传、下载和扫描吗?HBase的客户端只做这几件事情。你想写一本介绍3个API 调用的书吗?”

但是深入思考之后,我们意识到构建HBase应用系统很有挑战,而市面上缺乏足够的资料可供启蒙。这种情况限制了HBase的发展。我们决定收集更多如何有效使用HBase的资料,来帮助大家构建满足需要的系统。我们花了一些时间整理资料,2011年秋季,我们开始了这本书的写作。

那段时间,我搬家到了旧金山,加入了Cloudera公司,接触到很多搭建在Hadoop和HBase上的应用系统。我尽力结合我所知道的以及过去多年在HBase相关工作中和研究生学习中得到的,提取精华写到你现在读的这本书中。多年来HBase走了很长的路,许多大公司使用它作为核心系统。它比以往更加稳定、快速和易于维护,1.0版本也接近发布了。

我们写这本书的目的就是希望学习HBase可以更加有章可循,更加容易,更加有趣。等你进一步了解HBase以后,我们鼓励你参与到社区中来,你可以学到更多在这本书中没有讲到的。你可以发表博客,贡献代码,分享经验,让我们一起推动这个伟大的项目向各种可能的方向走得更远。打开书,开始阅读,欢迎来到HBase世界!

Amandeep Khurana

致谢

编写这本书时,我们一直谦逊地提醒自己:我们站在了巨人的肩上。如果没有10年前Google发表的那些论文,就不会有HBase和Hadoop。如果没有那些受这些论文启发并想办法解决自己挑战的人,就不会有HBase。无论是过去还是现在,我们要对每一个HBase和Hadoop的贡献者说:谢谢你。我们尤其要感谢HBase的代码提交者。你们往这个世界上最先进的数据技术项目里不断地投入时间和精力。更令人惊讶的是,你们把努力的结果贡献给了广大的社区。谢谢你们。

没有整个HBase社区就不可能有这本书。HBase拥有着NoSQL领域最大的、最活跃的、最热情的用户社区之一。我们还要感谢邮件列表中每个提问题的人和耐心回答问题的人。你们的热情和回答问题的意愿从一开始就鼓励大家参与进来。你们所提的问题和所需要的帮助许多是我们在书中提炼和澄清的内容的基础。我们希望能够扩大HBase的影响力并且帮助HBase的拥护者。

我们要特别感谢在这个过程中帮助我们的许多HBase代码提交者和社区会员。特别感谢Michael Stack、Lars George、Josh Patterson和Andrew Purtell,感谢你们的鼓励,也感谢你们提示我们这本书给社区带来的价值。感谢Ian Varley、Jonathan Hsieh和Omer Trajman,感谢你们贡献思路和反馈建议。Benoît Sigoure审核了OpenTSDB那一章(第7章)和asynchbase那一节(6.5节),谢谢你贡献的代码和评论。感谢Michael为本书作序,感谢Lars撰写了“致HBase社区的一封信”。

我们还要感谢我们各自的公司Cloudera, Inc.和The Climate Corporation,你们不仅支持我们,而且鼓励我们,没有你们不可能完成这本书。

我们要感谢Manning出版社的编辑Renae Gregoire和Susanna Kline。你们目睹了这本书从毫无头绪地开始到成功地完成的整个过程。我们认为你们其他的项目不会像我们这个如此令人兴奋!感谢我们的技术编辑Mark Henry Ryan以及技术校对Jerry Kuch和Kristine Kuch。

下面的人在编写本书的各个阶段阅读和审核了书稿,感谢你们提供了富有洞察力的反馈意见:Aaron Colcord、Adam Kawa、Andy Kirsch、Bobby Abraham、Bruno Dumon、Charles Pyle、Cristofer Weber、Daniel Bretoi、Gianluca Righetto、Ian Varley、John Griffin、Jonathan Miller、Keith Kim、Kenneth De Long、Lars Francke、Lars Hofhansl、Paul Stusiak、Philipp K. Janert、Robert J. Berger、Ryan Cox、Steve Loughran、Suraj Varma、Trey Spiva和Vinod Panicker。

最后也是最重要的——没有家人和朋友的认可我们什么也做不了,没有爱我们的人的支持我们完成不了这本书。谢谢你们在整个过程中的支持和耐心。

关于本书

HBase建立在Apache Hadoop和Apache ZooKeeper这些复杂的分布式系统之上。虽说你不必成为所有这些技术的专家才可以有效使用HBase,但是理解这些基础层面的知识有助于充分利用HBase。这些技术受了Google发表的论文启发。这些技术是Google的这些出版物中所描述的技术的开源实现。阅读这些专业论文对于使用HBase或其他这些技术虽说不是必要条件,但是当你学习一种技术,了解启发它们发明的源头总是有用的。尽管本书不要求你熟悉这些技术,也不要求你读过相关论文。

《HBase实战》定位是HBase的用户指南。它不会涉足HBase内部工作机制,也不会涉足理解Hadoop生态系统所必需的广泛话题。《HBase实战》专注于一点:使用HBase。它会指导你在HBase上搭建应用系统,并且在生产环境中使用这个应用系统。同时,你会学到一些HBase实施细节。你也会熟悉Hadoop的其他产品。你会学习足够的知识来理解HBase的工作方式,并问一些聪明的问题。本书不会把你培养成HBase的Committer(代码提交者),但会教你HBase的实战技巧。

路线图

《HBase实战》分为4个部分。前两个部分介绍如何使用HBase。在6章的篇幅里,你会从一个新手成长为可以在HBase上熟练编程的人。在这个过程中,你会学到HBase的基本原理、模式设计以及如何使用HBase的高级特性。最重要的是,你将学会用HBase的方式思考。第三部分有两章,介绍一些应用示例,让你体会一下实际应用是什么样子。第四部分指导你如何把原型开发系统升级为羽翼丰满的生产系统。

第1章总体介绍Hadoop、HBase和NoSQL的起源。我们将介绍HBase是什么和不是什么,把HBase和其他NoSQL数据库进行对比,介绍一些通用的使用场景。我们会帮你判断对于你的项目和公司来说HBase是否是正确的技术选择。第1章包括简单安装HBase和开始存储一点儿数据。

第2章开始运行一个示例应用。通过这个例子,我们探讨使用HBase的基础知识。包括创建表、存取数据以及HBase的数据模型。我们也会深入探讨HBase的内部工作机制,理解HBase如何组织数据,以及在你的应用中如何利用这些知识。

第3章作为一个分布式系统重新介绍HBase。本章探讨HBase、Hadoop和ZooKeeper之间的关系。你会学到HBase的分布式架构以及如何转换成一个强大的分布式数据系统。动手练习示例中会探讨在HBase上使用Hadoop MapReduce的使用场景。

第4章专门针对HBase模式设计。我们用示例应用来探讨这个复杂的主题。你会看到表设计决策是如何影响应用的,以及如何避免常见错误。我们会把一些关系型数据库知识映射到HBase世界里。你还会看到如何使用服务器端过滤器(server-side filter)来进一步完善模式设计。这一章也涵盖HBase的高级物理配置选项。

第5章介绍协处理器(coprocessor),这是一种把计算推向HBase集群的计算机制。你会用两种不同的方式扩展示例应用,在集群上构建应用的新特性。

第6章全面、快速地介绍可选的HBase客户端。HBase是用Java编写的,但这并不意味着你的应用必须是用Java编写的。你可以用各种编程语言和不同的网络协议来访问示例应用。

第三部分从第7章开始,将开始构建一个真实的、可以投入生产环境的应用系统。你会了解这个应用系统打算解决的问题和特别的挑战。然后我们深入到实现过程中,在技术细节上做全面考虑。也就是说,从前端到后端全面探讨如何在HBase上搭建应用系统。

第8章介绍如何在一个新领域里使用HBase。我们将带你快速进入这个新领域——GIS,然后教你如何基于HBase使用一种可扩展的方式来面对这个领域里特别的挑战。这一章的焦点在于针对特定领域的模式设计以及最大化利用扫描(scan)和过滤器(filter)特性。之前可以没有GIS经验,但是要准备好充分运用前面章节学习的知识。

在第四部分,第9章将部署你的HBase集群。从头开始,我们教你如何着手进行HBase部署。这一章将探讨硬件的种类、数量和如何分配硬件。考虑云服务吗?我们也会谈到。硬件确定以后,我们为你介绍如何为一个基本部署配置集群,如何让集群正常启动运行。

第10章将把你的部署升级到生产水平。我们教你通过参数和监控工具来监控集群。你会了解到如何根据你的应用负载来进一步优化集群的性能。我们教你如何管理集群,如何保持集群健康运行,有问题时如何诊断和处理,有需要时如何升级,等等。你将学习使用附带的工具来管理数据的备份和恢复,以及如何配置多集群间的复制工作。

目标读者

本书是一本数据库的用户实践手册。因此,它的主要受众群体是希望快速掌握HBase的应用开发人员和技术架构师。本书实践多于理论,使用技巧多于原理研究。本书的用途是开发人员指南,而不是学生教科书。本书也会介绍部署和运维的基本知识,所以对于运维工程师来说也能起到一定的帮助。(坦白说,面向运维人员的HBase方面的书还没有编写。)

HBase是用Java编写的,运行在JVM上面。我们希望你熟悉类似于类文件和JAR这样的Java编程语言和JVM概念。我们也假定你基本掌握一些JVM工具,特别是Maven,因为书中的源代码使用这个软件管理。Hadoop和 HBase运行在Linux和UNIX系统上,因此需要你掌握UNIX的基本知识。HBase不支持Windows操作系统,本书也不支持。Hadoop方面的经验会有帮助,尽管不是必需的。在这个领域,关系型数据库无处不在,所以我们假定你理解相关技术的概念。

HBase是一种分布式系统,使用了分布式、并行计算技术。希望你理解并行编程的基本概念,如多线程和并发进程等。我们不要求你知道如何编写并行计算程序,但是你应该熟悉并发执行线程的思路。本书重心不在算法理论,但是任何操作TB或PB级数据的人都应该对渐进计算的时间复杂度有概念。在模式设计的那一章中大O标记[1]会频频出现。

代码约定

和我们编写一本实战书籍的目标相一致,你会发现我们自由混合文字和代码。有时段落间只有两行代码。我们的指导思路是只在有必要时才展示给你如何使用API,然后提供额外的细节。这些代码片段将随着章节内容发展和演变。我们总是在小结一章时,给出代码的完整列表,提供充分的上下文背景。我们偶尔使用类Python风格的伪代码来帮助解释。这主要是在Java代码中使用了太多样板代码或者其他语言噪声以至于干扰了预期关键点的场合。真正的Java实现一般紧跟在伪代码后面提供。

因为这是一本动手的书,我们还使用了许多命令来演示系统的一些方面。这些命令包括你在终端输入的东西和你期望从系统得到的输出。软件系统会随着时间而改变,所以完全有可能在我们打印命令输出的时候,输出的内容有些变化。不过,这应该足以引导你判断系统预期的表现。

在命令和源代码部分,我们广泛使用了说明文字和注释来引起你对重要内容的注意。一些命令输出可能比较密集,尤其是使用HBase Shell时;使用说明文字和注释做引导比较清楚。文本中的代码使用等宽字体。

代码下载

我们所有的源代码,无论是小的脚本还是整个应用程序,都可以下载并且开源。我们已经把它们在Apache License Version 2.0下发布,与HBase一样的授权方式。你可以在GitHub专门为本书建立的网站www.github.com/HBaseinaction上找到源代码。在那里每个项目都是完整的应用程序。你也可以从出版商的网站www.manning.com/HBaseinaction上下载代码。

遵循开源的精神,我们希望我们的示例代码在你的应用中有用。我们鼓励你使用、修改、发展并与别人分享它们。如果你发现错误,请让我们知道,或者是提交问题,或者更好是修正问题。开源社区常说:欢迎补丁。

[1].表示算法的时间复杂度。——译者注

第一部分 HBase基础

书前三章介绍HBase的基本原理。第1章大体上回顾一下数据库技术的演变,并介绍HBase出现的特定背景。

第2章通过建立一个应用示例——TwitBase来讲授HBase的基础知识。通过这个示例,你可以学习如何访问HBase以及如何设计HBase的模式(schema),你会简单地了解到在应用系统中如何有效使用HBase。

HBase是一种分布式系统,我们在第3章会探讨分布式架构。你将学习到HBase如何在集群中管理你的数据以及如何使用MapReduce访问HBase。到第一部分结束,你就能掌握搭建HBase应用系统所需的基本知识了。

第1章 HBase介绍

本章涵盖的内容

Hadoop、HBase和NoSQL的起源

HBase的常见使用场景

HBase的基本安装

使用HBase存储和查询数据

HBase 是一种数据库:Hadoop数据库。它经常被描述为一种稀疏的、分布式的、持久化的、多维有序映射,它基于行键(rowkey)、列键(column key)和时间戳(timestamp)建立索引。人们会说它是一种键值(key value)存储、面向列族的数据库,有时也是一种存储多时间戳版本映射的数据库。所有这些描述都是正确的。但是从根本上讲,它是一个可以随机访问的存储和检索数据的平台,也就是说,你可以按照需要写入数据,然后再按照需要读取数据。HBase可以自如地存储结构化和半结构化的数据,所以你可以录入微博、解析好的日志文件或者全部产品目录及其用户评价。它也可以存储非结构化数据,只要不是特别大。它不介意数据类型,允许动态的、灵活的数据模型,并不限制存储的数据的种类。

HBase不同于你可能已经习惯的关系型数据库。它不用SQL语言,也不强调数据之间的关系。HBase不允许跨行的事务,你可以在一行的某一列存储一个整数而在另一行的同一列存储字符串。

HBase被设计成在一个服务器集群上运行,而不是单台服务器。集群可以由普通硬件构建;当把更多机器加入集群时,HBase可以相应地横向扩展。集群中的每个节点提供一部分存储空间、一部分缓存和一部分计算能力,因此HBase难以想象地灵活和宽容。因为没有独一无二的节点,所以某一台机器坏了,只需简单地用另一台机器替换即可。这意味着一种强大的、可扩展的使用数据的方式,到现在为止,一直没有官方数据说明它的扩展上限。

加入社区

遗憾的是,在生产环境中使用的最大的HBase集群没有官方的公开数据。这种信息容易被认为是商业机密而受到限制,经常不能分享。眼下,你只能在用户群组、聚会和会议上通过出版物的脚注、幻灯片内容或者是友好的非正式的八卦里满足一下好奇心了。

那么加入社区吧!这是正确的选择,我们也是这样参与进来的。HBase是一个非常专业领域里的开源项目。尽管HBase面对世界上最大几家软件公司的竞争,但是该项目的财务状况良好。是社区创造了HBase,也是社区使它保持竞争能力和创新能力。另外,这是一个智慧的、友好的群体。最好的开始方式是加入邮件列表[1]。你可以从JIRA网站[2]得到进展中的产品特性、增强和Bug等情况的信息。这是个开源的、协作的项目,正是像你这样的用户决定着项目的方向和发展。

走上前去,告诉他们,你来了!

HBase是设计和目标都与传统关系型数据库不同的系统,使用HBase构建应用也需要不同的方法。本书就是专门教你怎样使用HBase提供的特性来构建处理海量数据的应用的。在开始学习使用HBase之前,我们先从历史的角度来看看HBase是怎么出现的,以及其背后的驱动力。然后我们再看看人们使用HBase解决问题的成功案例。可能你和我们一样,在深入研究之前想试用一下HBase。最后我们会指导你在自己的笔记本电脑上安装HBase,存些数据进去,跑跑看看。学习HBase,了解大背景很重要,让我们先从数据库的演变历史开始。

1.1 数据管理系统:速成

关系型数据库系统已经存在几十年了,多年来在解决数据存储、服务和处理问题方面取得了巨大的成功。一些大型公司使用关系型数据库建立了自己的系统,比如联机事务处理系统和后端分析应用系统。

联机事务处理(OLTP)系统用来实时记录交易信息。对这类系统的期望是能够快速返回响应信息,一般是在毫秒级。例如,零售商店的收银机在客户购买和付款时需要实时记录相应信息。银行拥有大型OLTP系统,用来记录客户之间转账之类的交易信息,但OLTP不仅仅用于资金交易,像Linked In这样的互联网公司也需要这样的系统,例如,当用户连接其他用户时也会用到。OLTP中的transaction指的是数据库语境中的事务,而不是金融交易。

联机分析处理(OLAP)系统用来分析查询所存储数据。在零售商那里,这种系统意味着按天、按周、按月生成销售报表,按产品和按地域从不同角度分析信息。OLAP属于商业智能的范畴,数据需要研究、处理和分析,以便收集信息,进一步驱动商业决策。对于Linked In这样的公司,连接关系的建立可以看做事务,分析用户关系图的连通性以及生成每用户平均联系数量这种信息的报表就属于商业智能,这种处理很可能需要使用OLAP系统。

无论是开源的还是商业版权的关系型数据库,都已经成功地用于这样的使用场景。这一点通过Oracle、Vertica、Teradata等公司的财务报表可以清楚地看到。微软公司和IBM公司也占有一定份额。所有这些系统提供全面的ACID[3]保证。一些系统扩展性要优于其他系统;一些系统是开源的,还有一些需要支付夸张的许可费用。

关系型数据库的内部设计由关系算法决定,这些系统需要预先定义一个模式(schema)和数据要遵守的类型。随着时间的推移,SQL成了与这些系统交互的标准方式,被广泛使用了许多年。与使用编程语言编写定制访问代码相比,SQL语句更容易写,花费时间也要少得多。但并不是所有情况下SQL都是表达访问模式的最好方式,比如对象-关系不匹配问题出现的场合。

计算机科学中的问题都可以通过改变使用方式来解决。解决对象-关系不匹配问题也没有什么不同,最终可以通过重建框架来解决。

1.1.1 你好,大数据

让我们认真看看大数据这个术语。说实话,这是一个过分吹捧的术语,很多商业化的企业都会使用它来进行市场营销。我们这里尽量让讨论接点儿地气。

什么是大数据?关于大数据的定义有好几种,我们认为没有哪一种定义清晰地解释了这个术语。比如,一些定义说大数据意味着数据足够大,为了从这些数据中获得一些真知灼见,你不得不研究它;另一些说大数据就是不再适用于单台机器的数据。这些定义从他们各自的角度来看是准确的,但并不完整。我们的观点是,我们需要用一种根本上不同的方式来考虑数据,从如何驱动商业价值的角度来考虑数据,这种数据就是大数据。传统上,有联机事务处理系统(OLTP)和联机分析处理系统(OLAP)。但是,事务处理背后的原因是什么?是什么因素促成业务发生?又是什么直接影响了用户行为?我们缺乏这样的洞察力。以早期的Linked In为例,这种使用数据的方式可以理解为:基于用户属性、用户之间的二度关系、浏览行为等寻找可能认识的人,然后主动推荐并引导用户联系他们。有效地寻求这种主动推荐行为显然需要大量的各种各样数据。

这种新型数据使用方式首先为Google和Amazon等互联网公司采用,随后是Yahoo!和Facebook跟进。这些公司需要使用不同种类的数据,经常是非结构化的或者半结构化的数据(如用户访问网站的日志)。这需要系统处理比传统数据分析高了几个数量级的数据。传统关系型数据库能够纵向扩展到一定程度来面对一些使用场景,但这样做经常意味着昂贵的许可费用和复杂的应用逻辑。

但是受制于关系型数据库提供的数据模型,对于逐渐出现的、未预先定义模式(schema)的数据集,关系型数据库不能很好地工作。系统需要能够适应不同种类的数据格式和数据源,不需要预先严格定义模式,并且能够处理大规模数据。系统需求发生了巨大变化,互联网先驱不得不走回画图板,重新设计数据库,他们这样做了。大数据系统和NoSQL的曙光出现了。(有人可能会说曙光出现的时间点还要再晚一些,这并不重要,这的确标志着大家开始以不同方式思考数据了。)

作为数据管理系统创新的一部分,出现了几种新技术。每种新技术都适用于不同的使用场景,有着不同的设计前提和功能要求,也有着不同的数据模型。

什么时候会谈到HBase呢?是什么促使了这个系统的创立呢?请看下一节介绍。

1.1.2 数据创新

我们知道,许多杰出的互联网公司,如最突出的Google、Amazon、Yahoo!、Facebook等,都处于这场数据大爆炸的最前沿。一些公司自己生成数据,还有一些公司收集免费可获得的数据;但是管理这些海量的不同种类的数据成为他们推进业务发展的关键。开始阶段他们都采用了当时可用的关系型数据库技术,但是这些技术的局限性随后成了他们继续发展和业务成功的障碍。尽管数据管理技术不是他们业务的核心,但却是推进业务的基础。因此,他们大量投资于新技术研究领域,带来了许多新数据技术的突破。

很多公司都对自己的研究成果严格保密,但是Google选择公开讲述他的伟大技术。Google发表了震撼性的Google文件系统(Google File System)[4]和MapReduce[5]的论文。两者结合展示了一种全新的存储和处理数据的方法。此后不久,Google发表了BigTable[6]的论文,对基于Google文件系统的存储范型提供了补充。其他公司也参与进来,公布了各自的成功技术的想法和做法。Google的论文提供了对于如何建立互联网索引的深刻理解,Amazon公布了Dynamo[7],解密了网上购物车的基本组件。

不久,所有这些新想法都被浓缩到开源实践中。接下来的几年,数据管理领域出现了形形色色的项目。一些项目关注快速键值(key-value)存储,而另外一些关注内置数据结构或者基于文档的抽象化。同样多种多样的是这些技术可以支持的预期访问模式和数据量。一些项目甚至放弃写数据到硬盘,为了性能而牺牲当前的数据持久化。大多数技术不能保证支持受推崇的ACID。尽管有一些是商业版权产品,但是绝大多数这类技术都是开源项目。因此,这些技术作为整体被称为NoSQL。

HBase适于什么场合呢?HBase的确被称为NoSQL数据库。它提供了键值API,尽管有些变化,与其他键值数据库有些不同。它承诺强一致性,所以客户端能够在写入后马上看到数据。HBase运行在多个节点组成的集群上,而不是单台机器。它对客户端隐藏了这些细节。你的应用代码不需要知道它在访问1个还是100个节点,对每个人来说事情变得简单了。HBase被设计用来处理TB到PB级数据,它为这种场景做了优化。它是Hadoop生态系统的一部分,依靠Hadoop其他组件提供的重要功能,例如数据冗余和批处理。

了解了大背景后,我们再专门看看HBase的崛起。

1.1.3 HBase的崛起

假设你正忙于一个开源项目,通过爬网站和建立索引来搜索互联网。你有一个实现方案,这个实现方案工作在一个小集群上,但是需要许多手工环节。再假设你正忙于这个项目的时候,Google发表了数据存储和数据处理框架的论文。显然,你会研究这些论文,模仿它们启动一个开源实现。好吧,你不打算这么做,我们当然也不会,但是Doug Cutting和Mike Cafarella就是这么做的。

Nutch是他们的互联网搜索开源项目,脱胎于Apache Lucene,Hadoop就是在Nutch项目里诞生的[8]。从那时起,Yahoo!开始关注Hadoop,最后Yahoo!招募了Cutting和其他人为Yahoo!全职工作。随后,Hadoop从Nutch中剥离出来,最后成为Apache的顶级项目。随着Hadoop的良好发展和BigTable论文的发表,在Hadoop上面实现一个BigTable开源版本的基础工作开始了。2007年,Cafarella发布了实验性代码,开源的BigTable。他称其谓HBase。创业公司Powerset决定贡献出Jim Kellerman和Michael Stack两位专家专职做这个BigTable的模仿产品,回馈它所依赖的开源社区。

HBase被证实是一个强大的工具,尤其是在已经使用Hadoop的场合。在其“婴儿期”的时候,它就快速部署到了其他公司的生产环境并得到开发人员的支持。今天,HBase已经是Apache顶级项目,有着众多的开发人员和兴旺的用户社区。它成为一个核心的基础架构部件,运行在世界上许多公司(如StumbleUpon、Trend Micro、Facebook、Twitter、Salesforce和Adobe)的大规模生产环境中。

HBase不是数据管理问题的;“万能药”,针对不同的使用场景你可能需要考虑其他的技术。让我们看看现在HBase是如何使用的,人们用它构建了什么类型的应用系统。通过这个讨论,你会知道哪种数据问题适合使用HBase。

1.2 HBase使用场景和成功案例

有时候了解软件产品的最好方法是看看它是怎么用的。它可以解决什么问题和这些解决方案如何适用于大型应用架构,这些能够告诉你很多。因为HBase有许多公开的产品部署案例,我们正好可以这么做。本节将详细介绍一些成功使用HBase的使用场景。

注意 不要自我限制,认为HBase只能在这些使用场景下使用。它是一个很新的技术,根据使用场景进行的创新正推动着该系统的发展。如果你有新想法,认为HBase提供的功能会让你受益,那就试试吧。社区很乐于帮助你,也会从你的经验中学习。这正是开源软件精神。

HBase模仿了Google的BigTable,让我们先从典型的BigTable问题开始:存储互联网。

1.2.1 典型的互联网搜索问题:BigTable发明的原因

搜索是一种定位你所关心信息的行为。例如,搜索一本书的页码,其中含有你想读的主题,或者搜索网页,其中含有你想找的信息。搜索含有特定词语的文档,需要查找索引,该索引提供了特定词语和包含该词语的所有文档的映射。为了能够搜索,首先必须建立索引。Google和其他搜索引擎正是这么做的。它们的文档库是整个互联网,搜索的特定词语就是你在搜索框里敲入的任何东西。

BigTable和模仿出来的HBase,为这种文档库提供存储,BigTable提供行级访问,所以爬虫可以插入和更新单个文档。搜索索引可以基于BigTable通过MapReduce计算高效生成。如果结果是单个文档,可以直接从BigTable取出。支持各种访问模式是影响BigTable设计的关键因素。图1-1显示了互联网搜索应用中BigTable的关键角色。

注意 为简洁起见,这里不做BigTable原作者判定。我们强烈推荐关于Google File System、MapReduce和BigTable三大论文,如果你对这些技术感到好奇,这是必读读物。你不会失望的。

讲完典型HBase使用场景以后,我们来看看其他使用HBase的地方。愿意使用HBase的用户数量在过去几年里迅猛增长。部分原因在于HBase产品变得更加可靠且性能变得更好,更多原因在于越来越多的公司开始投入大量资源来支持和使用它。随着越来越多的商业服务供应商提供支持,用户越发自信地把HBase应用于关键应用系统。一个设计初衷是用来存储互联网持续更新网页副本的技术,用在互联网相关的其他方面也是很合适的。例如,HBase在社交网络公司内部和周围各种各样的需求中找到了用武之地。从存储个人之间的通信信息,到通信信息分析,HBase 成为 Facebook、Twitter 和StumbleUpon等公司的关键基础设施。

在这个领域,HBase有3种主要使用场景,但不限于这3种。为了保持本节简单明了,本节我们只介绍主要的使用场景。

1.2.2 抓取增量数据

数据通常是细水长流的,累加到已有数据库以备将来使用,如分析、处理和服务。许多HBase使用场景属于这一类——使用HBase作为数据存储,抓取来自各种数据源的增量数据。例如,这种数据源可能是网页爬虫(我们讨论过的BigTable典型问题),可能是记录用户看了什么广告和看了多长时间的广告效果数据,也可能是记录各种参数的时间序列数据。我们讨论几个成功的使用场景,以及这些项目涉及的公司。

1.抓取监控指标:OpenTSDB

服务数百万用户的基于Web的产品的后台基础设施一般都有数百或数千台服务器。这些服务器承担了各种功能——服务流量,抓取日志,存储数据,处理数据,等等。为了保证产品正常运行,监控服务器和上面运行的软件的健康状态是至关重要的(从OS到用户交互应用)。大规模监控整个环境需要能够采集和存储来自不同数据源各种监控指标的监控系统。每个公司都有自己的办法。一些公司使用商业工具来收集和展示监控指标,而另外一些公司采用开源框架。

StumbleUpon创建了一个开源框架,用来收集服务器的各种监控指标。按照时间收集监控指标一般被称为时间序列数据,也就是说,按照时间顺序收集和记录的数据。StumbleUpon的开源框架叫做OpenTSDB,它是Open Time Series Database(开放时间序列数据库)的缩写。这个框架使用HBase作为核心平台来存储和检索所收集的监控指标。创建这个框架的目的是为了拥有一个可扩展的监控数据收集系统,一方面能够存储和检索监控指标数据并保存很长时间,另一方面如果需要增加功能也可以添加各种新监控指标。StumbleUpon使用OpenTSDB监控所有基础设施和软件,包括HBase集群自身。OpenTSDB作为搭建在HBase之上的一种示例应用,我们将在第7章详细介绍。

2.抓取用户交互数据:Facebook和StumbleUpon

抓取监控指标是一种使用方式。还有一种是抓取用户交互数据。如何跟踪数百万用户在网站上的活动?怎么知道哪一个网站功能最受欢迎?怎样使得这一次网页浏览直接影响到下一次?例如,谁看了什么?某个按钮被点击了多少次?还记得Facebook和Stumble里的Like按钮和StumbleUpon里的+1按钮吗?是不是听起来像是一个计数问题?每次用户喜欢一个特定主题,计数器增加一次。

StumbleUpon在开始阶段采用的是MySQL,但是随着网站服务越来越流行,这种技术选择遇到了问题。急剧增长的用户在线负载需求远远超过了MySQL集群的能力,最终StumbleUpon选择使用HBase来替换这些集群。当时,HBase产品不能直接提供必需的功能。StumbleUpon在HBase上做了一些小的开发改动,后来将这些开发工作贡献回了项目社区。

FaceBook使用HBase的计数器来计量人们喜欢特定网页的次数。内容原创人和网页主人可以得到近乎实时的、多少用户喜欢他们网页的数据信息。他们可以因此更敏捷地判断应该提供什么内容。Facebook为此创建了一个叫Facebook Insights的系统,该系统需要一个可扩展的存储系统。公司考虑了很多种可能的选择,包括关系型数据库管理系统、内存数据库和Cassandra数据库,最后决定使用HBase。基于HBase,Facebook可以很方便地横向扩展服务规模,给数百万用户提供服务,还可以继续沿用他们已有的运行大规模HBase集群的经验。该系统每天处理数百亿条事件,记录数百个监控指标。

3.遥测技术:Mozilia和Trend Micro

软件运行数据和软件质量数据,不像监控指标数据那么简单。例如,软件崩溃报告是有用的软件运行数据,经常用来探究软件质量和规划软件开发路线图。HBase可以成功地用来捕获和存储用户计算机上生成的软件崩溃报告。

Mozilla基金会负责FireFox网络浏览器和Thunderbird电子邮件客户端两个产品。这些工具安装在全世界数百万台计算机上,支持各种操作系统。当这些工具崩溃时,会以Bug报告的形式返回一个软件崩溃报告给Mozilla。Mozilla如何收集这些数据?收集后又是怎么使用的呢?实际情况是这样的,一个叫做Socorro的系统收集了这些报告,用来指导研发部门研制更稳定的产品。Socorro系统的数据存储和分析建构在HBase上。

使用HBase,基本分析可以用到比以前多得多的数据。这种分析用来指导Mozilla的开发人员,使其更为专注,研制出Bug最少的版本。

Trend Micro为企业客户提供互联网安全和入侵管理服务。安全的重要环节是感知,日志收集和分析对于提供这种感知能力是至关重要的。Trend Micro使用HBase来管理网络信誉数据库,该数据库需要行级更新和支持MapReduce批处理。有点像Mozilla的Socorro系统,HBase也用来收集和分析日志活动,每天收集数十亿条记录。HBase中灵活的数据模式允许数据结构出现变化,当分析流程重新调整时,Trend Micro可以增加新属性。

4.广告效果和点击流

过去十来年,在线广告成为互联网产品的一个主要收入来源。先提供免费服务给用户,在用户使用服务的时侯投放广告给目标用户。这种精准投放需要针对用户交互数据做详细的捕获和分析,以便理解用户的特征。基于这种特征,选择并投放广告。精细的用户交互数据会带来更好的模型,进而导致更好的广告投放效果,并获得更多的收入。但这类数据有两个特点:它以连续流的形式出现,它很容易按用户划分。理想情况下,这种数据一旦产生就能够马上使用,用户特征模型可以没有延迟地持续优化,也就是说,以在线方式使用。

在线系统与离线系统

在线和离线的术语多次出现。对于初学者来说,这些术语描述了软件系统执行的条件。在线系统需要低延迟。某些情况下,系统哪怕给出没有答案的响应,也要比花了很长时间给出正确答案的响应好。你可以把在线系统想象为一个跳着脚的没有耐心的用户。离线系统不需要低延迟,用户可以等待答案,不期待马上给出响应。当实现应用系统时,在线或者离线的目标影响着许多技术决策。HBase是一个在线系统。和Hadoop MapReduce的紧密结合又赋予它离线访问的能力。

HBase非常适合收集这种用户交互数据,HBase已经成功地应用在这种场合,它可以存储第一手点击流和用户交互数据,然后用不同的处理方式(MapReduce是其中一种)来处理数据(清理、丰富和使用数据)。在这类公司,你会发现很多HBase案例。

1.2.3 内容服务

传统数据库最主要的使用场合之一是为用户提供内容服务。各种各样的数据库支撑着提供各种内容服务的应用系统。多年来,这些应用一直在发展,因此它们所依赖的数据库也在发展。用户希望使用和交互的内容种类越来越多。此外,由于互联网迅猛的增长以及终端设备更加迅猛的增长,对这些应用的接入方式提出了更高的要求。各种各样的终端设备带来了另一个挑战:不同的设备需要以不同的格式使用同样的内容。

上面说的是用户消费内容(user consuming content),另外一个完全不同的使用场景是用户生成内容(user generate content)。Twitter帖子、Facebook帖子、Instagram图片和微博等都是这样的例子。

它们的相同之处是使用和生成了许多内容。大量用户通过应用系统来使用和生成内容,而这些应用系统需要HBase作为基础。

内容管理系统(Content Management System,CMS)可以集中管理一切,可以用来存储内容和提供内容服务。但是当用户越来越多,生成的内容越来越多的时候,就需要一个更具可扩展性的CMS解决方案。可扩展的Lily CMS使用HBase作为基础,加上其他开源框架,如Solr,构成了一个完整的功能组合。

Salesforce提供托管CRM产品,这个产品通过网络浏览器界面提交给用户使用,显示出丰富的关系型数据库功能。在Google发表NoSQL原型概念论文之前很长一段时间,在生产环境中使用的大型关键数据库最合理的选择就是商用关系型数据库管理系统。多年来,Salesforce通过数据库分库和尖端性能优化手段的结合扩展了系统处理能力,达到每天处理数亿事务的能力。

当Salesforce把分布式数据库系统列入选择范围后,他们评测了所有NoSQL技术产品,最后决定部署HBase[9]。一致性的需求是这个决定的主要原因。BigTable类型的系统是唯一的架构方式,结合了无缝水平扩展能力和行级强一致性能力。此外,Salesforce已经在使用Hadoop完成大型离线批处理任务,他们可以继续沿用Hadoop上面积累的宝贵经验。

1.URL短链接

最近一段时间URL短链接非常流行,许多类似产品破土而出。StumbleUpon使用名字为su.pr.的短链接产品,这个产品以HBase为基础。这个产品用来缩短URL,存储大量的短链接以及和原始长链接的映射关系,HBase帮助这个产品实现扩展能力。

2.用户模型服务

经HBase处理过的内容往往并不直接提交给用户使用,而是用来决定应该提交给用户什么内容。这种中间处理数据用来丰富用户的交互。

还记得前面提到的广告服务场景里的用户特征吗?用户特征(或者说模型)就是来自HBase。这种模型多种多样,可以用于多种不同场景。例如,针对特定用户投放什么广告的决定,用户在电商网站购物时实时报价的决定,用户在搜索引擎检索时增加背景信息和关联内容,等等。很多这种使用案例可能不便于公开讨论,说多了我们就有麻烦了。

当用户在电商网站上发生交易时,Runa用户模型服务可以用来实时报价。这种模型需要基于不断产生的新用户数据持续调优。

1.2.4 信息交换

各种社交网络破土而出[10],世界变得越来越小。社交网站的一个重要作用就是帮助人们进行互动。有时互动在群组内发生(小规模和大规模),有时互动在两个个人之间发生。想想看,数亿人通过社交网络进行对话的场面。单单和远处的人对话还不足以让人满意,人们还想看看和其他人对话的历史记录。让社交网络公司感到幸运的是,保存这些历史记录很廉价,大数据领域的创新可以帮助他们充分利用廉价的存储。[11]

在这方面,Facebook短信系统经常被公开讨论,它也可能极大地推动了HBase的发展。当你使用Facebook时,某个时候你可能会收到或者发送短信给你的朋友。Facebook的这个特性完全依赖于HBase。用户读写的所有短信都存储在HBase里。Facebook短信系统要求:高的写吞吐量,极大的表,数据中心内的强一致性。除了短信系统之外,其他应用系统要求:高的读吞吐量,计数器吞吐量,自动分库。工程师们发现HBase是一个理想的解决方案,因为它支持所有这些特性,它拥有一个活跃的用户社区,Facebook运营团队在Hadoop部署上有丰富经验,等等。在“Hadoop goes realtime at Facebook[12]”这篇文章里,Facebook工程师解释了这个决定背后的逻辑并展示了他们使用Hadoop和HBase构建在线系统的经验。

Facebook工程师在HBaseCon 2012大会上分享了一些有趣的数据。在这个平台上每天交换数十亿条短信,每天带来大约750亿次操作。尖峰时刻,Facebook的HBase集群每秒发生150万次操作。从数据规模角度看,Facebook的集群每月增加250TB的新数据[13],这可能是已知的最大的HBase部署,无论是服务器的数量还是服务器所承载的用户量。

上述一些示例,解释了HBase如何解决一些有趣的老问题和新问题。你可能注意到一个共同点:HBase可以用来对相同数据进行在线服务和离线处理。这正是HBase的独到之处。了解到可以如何使用HBase之后,现在来试用一下。

1.3 你好HBase

HBase搭建在Apache Hadoop和Apache ZooKeeper上面。就像Hadoop家族其他产品一样,它是用Java编写的。HBase可以以3种模式运行:单机伪分布式全分布式。下面我们将使用的是单机模式。这意味着在一个Java进程里运行HBase的全部内容。这种访问模式用于研究HBase和做本地开发。

伪分布式模式需要在一台机器上运行多个Java进程。最后的全分布模式需要一个服务器集群。这两种模式需要安装相关联的软件包以及合理地配置HBase。这些内容将在第9章讨论。

HBase设计运行在*nix系统上,代码和书中的命令都是为*nix系统设计的。如果你使用Windows系统,最好的选择是安装一个Linux虚拟机。

关于Java的解释

HBase基本上用Java编写,只有几个部件不是,最优先支持的语言自然是Java。如果你不是Java开发员,在学习HBase时需要学习一些Java技能。本书的目标是指导你如何有效地使用HBase,很大篇幅内容关于如何使用API,它们都是Java的。所以,辛苦一点儿吧。

1.3.1 快速安装

以单机模式运行HBase,过程很简单。你可以选择Apache HBase 0.92.1版本,使用tar文件包进行安装。第9章会讨论其他各种发行版。如果你选择不同于Apache HBase 0.92.1的其他版本,也是可以使用的。本书的例子基于HBase 0.92.1版本(和Cloudera CDH4),其他API兼容的版本应该都可以正常工作。

HBase需要系统安装Java运行环境(JRE)。生产系统环境我们推荐Oracle的Java软件包。Hadoop和HBase社区测试了一些JRE版本,写作本书时HBase 0.92.1或CDH4的推荐版本是 Java 1.6.0_31。Java 7至今没有测试,因此并不推荐。安装HBase之前先在系统上安装Java。

到Apache HBase网站的下载区下载tar文件包(http:// hbase.apache.org/):

上述步骤从Apache镜像站点下载和解压了HBase的tar文件包。方便起见,创建一个环境变量指向这个目录,后面会比较省事。把它写入环境变量文件,以便每次打开Shell时不用重复设置。书中后面都会用到HBASE_HOME:

完成后,使用系统提供的脚本启动HBase:

如果可以,把$HBASE_HOME/bin放进PATH变量,以便下次你可以直接执行hbase而不是$HBASE_HOME/bin/hbase。

全部做完后,单机模式的HBase就安装成功了。HBase的配置信息主要在两个文件里:hbase-env.sh 和 hbase-site.xml。这两个文件存放在/etc/hbase/conf/目录下。单机模式的默认设置里,HBase写数据到目录/tmp 下,但是该目录不是长期保存数据的地方。你可以编辑hbase-site.xml文件,添加下面配置信息来将目录改到你指定的地方:

HBase安装成功后有一个简单管理界面,运行在端口http://localhost:60010,如图1-2所示。

安装完成,HBase已经启动,现在开始使用HBase。

1.3.2 HBase Shell命令行交互

你可以使用HBase Shell,通过命令行方式和HBase进行交互。本地安装和集群安装都采用同样的Shell方式。HBase Shell是一个封装了Java客户端API的JRuby应用软件,有两种运行方式:交互模式批处理模式。交互模式用于对HBase进行随时访问交互,批处理模式主要通过Shell脚本进行程序化交互或者用于加载小文件。在本章节我们使用交互模式。

JRuby和JVM语言

不熟悉Java的人可能被JRuby的概念搞迷糊了。JRuby是在Java运行时上面的Ruby编程语言的实现。除了正常的Ruby语法,JRuby支持访问Java对象和函数库。JVM上不仅仅只是Java和JRuby。Jython是JVM上Python的实现,还有一些完全不同的语言,如Clojure和Scala。所有这些语言都可以通过Java客户端API来访问HBase。

让我们开始使用交互模式。在终端中执行hbase shell命令启动Shell。Shell可以支持命令自动补全和命令文档内联访问:

走到这一步,可以确认Java和HBase函数库已经安装成功。为了最终验证,可以试试列出HBase中所有表的命令。这个动作执行了一个全程请求,从客户端应用到HBase服务器,然后返回。在Shell提示符下,输入list然后按下回车键。你应该看到输出0个结果,以及接下来的提示符:

完成安装和验证后,现在创建表并存储一些数据。

1.3.3 存储数据

HBase使用表作为顶级结构来存储数据。写数据到HBase,就是写数据到表。现在开始,创建一个有一个列族的表,名字是 mytable。是的,列族(别着急,后面会解释这个术语)。现在创建表:

1.写数据

表创建后,现在写入一些数据。我们往表里写入字符串hello HBase。按HBase的说法,我们这么说,“在'mytable'表的'first'行中的'cf:message'列对应的数据单元中插入字节数组'hello HBase'”能听懂吗?下一章我们会解释所有这些术语。现在,执行写入命令:

简单吧。HBase存储数字的方式和存储字符串一样。继续多增加几个值,如下:

现在表里有3行和3个数据单元。注意,在使用列的时候你并没有提前定义这些列,你也没有定义往每个列里存储的数据的类型。这就是NoSQL粉丝们所说的,HBase是一种无模式(schema-less)的数据库。如果写入数据后不能读取出来也是没有用的,现在读回数据看看。

2.读数据

HBase有两种方式读取数据:get和scan。你肯定敏锐地注意到了,HBase存储数据的命令是put。和put相对应,读取一行的命令是get。还记得我们说过,HBase除了键值API还有一些特别之处吗?scan就是这个特别所在。第2章会介绍scan是如何工作的以及为什么它很重要,同时会重点关注如何使用它。

现在执行get:

如上所示,你得到了第一行。Shell输出了该行所有数据单元,按列组织,输出值还附带时间戳。HBase可以存储每个数据单元的多个时间版本。存储的版本数量默认值是3个,但可以重新设置。读取的时候,除非特别指定,否则默认返回最新时间版本。如果你不希望存储多个时间版本,可以设置HBase只存储一个版本,但是绝不要禁用这个特性。

使用scan命令,你会得到多行数据。但是要小心,我们必须提醒你,除非特别指定,否则该命令会返回表里的所有行。现在执行scan:

返回了所有数据。注意观察HBase返回行的顺序,是按行的名字排序的。HBase称之为行键(rowkey)。HBase还有很多技巧,但是所有其他东西都建立在你刚才使用的基本概念上。好好体会一下。

1.4 小结

我们在开始的介绍性章节里介绍了相当多的数据管理技术的历史资料。当你学习一门技术时,了解它的来龙去脉总是有帮助的。现在,你大概知道了HBase的起源以及NoSQL现象的大背景。你也了解了设计HBase是为了解决什么样的问题,以及它已经解决了哪些问题。不仅如此,你还安装并运行了HBase,并且用其存储了一些可爱的“hello world”数据。

当然,我们会向你提出更多的问题。强一致性为什么重要?客户端读取数据时如何找到正确的节点?scan有趣在什么地方?HBase还有什么其他的技巧呢?下一章我们会回答这些乃至更多的问题。如果你打算搭建一个使用HBase作为后端数据存储的应用系统,第2章会告诉你怎么开始。

第2章 入门

本章涵盖的内容

连接到HBase和定义表

与HBase交互的基本命令

HBase的物理数据模型和逻辑数据模型

基于复合行键的查询

下面几章的一个目标是教你如何使用HBase。作为一名应用开发人员,首先你要适应HBase的特性。你将学习HBase的逻辑数据模型(logical data model),访问HBase的各种方式,以及如何使用这些API的细节。另外一个目标是教你进行HBase模式(schema)设计。HBase有着和以往关系型数据库不同的物理数据模型(physical data model)。我们将介绍一些HBase物理模型的基本原理,以便设计数据模型时你能够利用它对自已的应用系统进行优化。

为了完成这些目标,你将从头开始搭建一个应用系统。请允许我们给你介绍一下完全建立在HBase上的TwitBase,它是社交网络Twitter的简化克隆版。我们不会实现Twitter的所有功能,而且这也不是一个准备投入使用的系统。我们只是把TwitBase看做Twitter的初级原型产品。TwitBase和Twitter早期版本的主要区别是,TwitBase设计中考虑了可扩展性,因此需要依赖数据存储来实现这一点。

本章从基本原理开始讲起。你会看到如何创建HBase表,如何导入数据和读取数据。我们将介绍HBase处理数据的基本操作,以及数据模型的基本组件。同时,你会学到一些HBase的内部工作机制。这些知识可以帮助你在模式设计时作出正确决定。本章是学习HBase和其余章节的起点。

要获取本章及全书的代码,请访问 https://github.com/hbaseinaction/twitbase。

2.1 从头开始

TwitBase存储3种简单的核心数据元素,即用户(user)、推帖(twit)和关系(relationship)。用户是TwitBase的中心。用户登录进入应用系统,维护用户信息,通过发帖与其他用户互动。推帖是TwitBase中用户公开发表的短文。推帖是用户间互动的主要模式。用户通过互相转发产生对话。所有互动的“黏合剂”就是关系。关系连接用户,使用户很容易读到其他用户的推帖。本章关注点是用户和推帖,下一章将讨论关系。

关于Java

本书绝大部分代码都是用Java编写的。有时我们使用伪代码来帮助理解概念,但是工作代码是Java。使用HBase,Java是现实的选择。整个Hadoop系列,包括HBase,都使用Java。HBase客户端函数库是Java,MapReduce函数库也是Java。HBase的部署需要优化JVM性能。但是可以使用非Java和非JVM的语言来访问HBase,第6章会讨论这些内容。

2.1.1 创建表

现在开始搭建TwitBase,为存储用户奠定一个基础。HBase是一个在表里存储数据的数据库,所以我们从创建users表开始。首先进入HBase Shell:

Shell打开一个到HBase的连接,给出提示符。在Shell提示符上,创建你的第一张表:

可以想到'users'是表的名字,但是'info'是什么呢?像关系型数据库里的表一样,HBase的表也是按照行(row)和列(column)来组织的。HBase中的列和关系型数据库中的有些不同。HBase中的列组成列族(column family)。info就是users表的一个列族。HBase中的表必须至少有一个列族。它们之中,列族直接影响HBase数据存储的物理特性。因此,创建表时必须至少指定一个列族。表创建后列族还可以更改,但是这么做很麻烦。后面我们会详细讨论列族,现在只需要知道users表足够简单,只有一个列族,就可以了。

2.1.2 检查表模式

如果你熟悉关系型数据库,会马上注意到,HBase创建表时没提到任何列或者数据类型。除了列族名字,HBase什么也不需要。这就是HBase经常被称作无模式数据库的原因。

你可以要求HBase列出所有已创建的表来验证users表已经创建成功:

list 命令可以显示存在的表,HBase也可以提供表的更多细节。使用describe命令可以看到这个表的所有的默认参数:

Shell显示表有两类属性信息:表的名字和列族的列表。每个列族有许多相应的配置信息细节,这些就是我们前面提到的物理特性。现在先不管这些细节,我们随后研究它们。

HBase Shell

虽然HBase Shell主要用于管理任务,但它拥有丰富的特性。它用JRuby实现,可以使用整个Java客户端API。你可以使用help命令进一步发掘Shell的功能。

2.1.3 建立连接

尽管Shell很好用,但是谁会愿意用Shell命令实现TwitBase呢?聪明的HBase开发人员知道这一点,他们为HBase提供了一个全面的Java客户端库。也有面向其他语言的类似的API,第6章会讨论。现在我们使用Java。打开users表连接的Java代码如下所示:

类似于Shell的做法,构造函数HTable读取默认配置信息来定位HBase。然后定位之前你创建的users表,返回一个句柄。

你也可以传递一个定制的配置对象给HTable对象:

这等同于让HTable对象自己创建配置信息对象。你可以像下面这样设定参数来定制配置信息:

HBase客户端配置信息

HBase客户端应用需要有一份HBase配置信息来访问HBase——ZooKeeper quorum地址。你可以手工设定这个配置如下:

My Conf.set("hbase.zookeeper.quorum","serverip");

ZooKeeper以及客户端与HBase集群之间的交互会在下一章深入研究分布式HBase存储时讨论到。现在你只需要知道HBase配置信息可以通过两种方式获取,一种是Java客户端从类路径里的hbase-site.xml文件里获取配置信息,另一种是通过在连接中显式设定配置信息来获取。如果你没有指定配置信息,就像示例代码里那样,客户端就会使用默认配置信息,把localhost作为ZooKeeper quorum 地址。单机模式中,指的就是你用来验证本书内容的机器,这正是你需要的配置信息。

2.1.4 连接管理

创建一张表实例是个开销很大的操作,需要占用一些网络资源。与直接创建表句柄相比,使用连接池更好一些。连接从连接池里分配,然后再返回到连接池。实践中,使用HTablePool比直接使用HTable更为常见:

当你完成工作关闭表时,连接资源会返回到连接池里。

没有数据的表是没有用的,现在我们存储一些数据。

2.2 数据操作

HBase表的行有唯一标识符,叫做行键(rowkey)。其他部分用来存储HBase表里的数据,但是行键是第一重要的。就像关系型数据库的主键,HBase表中每行的行键值都是不同的。每次访问表中的数据都从行键开始。TwitBase中每个用户是唯一的,所以users表使用用户名字作为行键很方便,一会儿就这么用。

和数据操作有关的HBase API称为命令(command)。有5个基本命令用来访问HBase,Get(读)、Put(写)、Delete(删除)、Scan(扫描)和Increment(递增)。用来存储数据的命令是Put。为了往表里存储数据,你需要创建一个Put实例。根据行键创建Put实例,如下所示:

为什么不能直接存储用户名字呢?HBase中所有数据都是作为原始数据(raw data)使用字节数组的形式存储的,行键也是如此。Java客户端函数库提供了一个公用类Bytes,用来转换各种Java数据类型,所以你不必担心。注意,这个Put实例还没有插入到表中。现在只是创建了对象。

2.2.1 存储数据

既然我们准备好了一个命令往HBase里添加数据,你还需要提供要存储的数据。先存储一个叫Mark的用户的基本信息,如他的邮件地址和密码。如果还有另外一个用户也叫Mark Twain会发生什么呢?它们的名字会冲突,数据不能存储到TwitBase里。所以我们必须使用一个独一无二的用户名作为行键,用户的真实名字不做行键而是存储在一个列里面。把前面的Put命令放在一起编写代码如下:

记住,HBase使用坐标来定位表中的数据。行键是第一个坐标,下一个是列族。列族用做数据坐标时,表示一组列。再下一个坐标是列限定符(column qualifier),如果你熟悉HBase术语,它经常简称为(column)或标志(qual)。本例子中列限定符是name、email和password。因为HBase是无模式的,你不需要事先定义列限定符或者设定数据类型。它们是动态的,你所需要做的只是在写入数据时给出列的名字。3个坐标确定了单元(cell)的位置。HBase中数据作为值(value)存储在单元里。表中确定一个单元的坐标是[rowkey, column family, column qualifier]。上面的代码在一行中存储3个单元的3个值。其中存储Mark名字的单元坐标是[TheRealMT, info, name]。

写数据到HBase的最后一步是提交命令给表。这一步很简单:

2.2.2 修改数据

HBase中修改数据使用的方式与存储新数据一样:创建Put对象,在正确的坐标上给出数据,提交到表。我们来给Mark修改一个更安全的密码。

2.2.3 工作机制:HBase写路径

在HBase中无论是增加新行还是修改已有的行,其内部流程都是相同的。HBase接到命令后存下变化信息,或者写入失败抛出异常。默认情况下,执行写入时会写到两个地方:预写式日志(write-ahead log,也称HLog)和MemStore(见图2-1)。HBase的默认方式是把写入动作记录在这两个地方,以保证数据持久化。只有当这两个地方的变化信息都写入并确认后,才认为写动作完成。

MemStore是内存里的写入缓冲区,HBase中数据在永久写入硬盘之前在这里累积。当MemStore填满后,其中的数据会刷写到硬盘,生成一个HFile。HFile是HBase使用的底层存储格式。HFile对应于列族,一个列族可以有多个HFile,但一个HFile不能存储多个列族的数据。在集群的每个节点上,每个列族有一个MemStore。[14]

大型分布式系统中硬件故障很常见,HBase也不例外。设想一下,如果MemStore还没有刷写,服务器就崩溃了,内存中没有写入硬盘的数据就会丢失。HBase的应对办法是在写动作完成之前先写入WAL。HBase集群中每台服务器维护一个WAL来记录发生的变化。WAL是底层文件系统上的一个文件。直到WAL新记录成功写入后,写动作才被认为成功完成。这可以保证HBase和支撑它的文件系统满足持久性。大多数情况下, HBase使用Hadoop分布式文件系统(HDFS)来作为底层文件系统。

如果HBase服务器宕机,没有从MemStore里刷写到HFile的数据将可以通过回放WAL 来恢复。你不需要手工执行。HBase 的内部机制中有恢复流程部分来处理。每台HBase服务器有一个WAL,这台服务器上的所有表(和它们的列族)共享这个WAL。

你可能想到,写入时跳过WAL应该会提升写性能。但我们不建议禁用WAL,除非你愿意在出问题时丢失数据。如果你想测试一下,如下代码可以禁用WAL:

注意:不写入WAL会在RegionServer故障时增加丢失数据的风险。关闭WAL,出现故障时HBase可能无法恢复数据,没有刷写到硬盘的所有写入数据都会丢失。

2.2.4 读数据

从HBase读取数据和写入数据一样简单。创建一个Get命令实例,告诉它你感兴趣的单元,提交到表:

该表会返回一个包含数据的Result实例。实例中包含行中所有列族的所有列。这可能大大超过你所需要的。你可以在Get实例中放置限制条件来减少返回的数据量。为了返回列 password,可以执行命令 add Column()。对于列族同样可以执行命令add Family(),下面的例子可以返回指定列族的所有列:

检索特定值,从字节转换回字符串,如下所示:

2.2.5 工作机制:HBase读路径

如果你想快速访问数据,通用的原则是数据保持有序并尽可能保存在内存里。HBase实现了这两个目标,大多情况下读操作可以做到毫秒级。HBase读动作必须重新衔接持久化到硬盘上的HFile和内存中MemStore里的数据。HBase在读操作上使用了LRU(最近最少使用算法)缓存技术。这种缓存也叫做BlockCache,和MemStore在一个JVM堆里。BlockCache设计用来保存从HFile里读入内存的频繁访问的数据,避免硬盘读。每个列族都有自己的BlockCache。

掌握BlockCache是优化HBase性能的一个重要部分。BlockCache中的Block是HBase从硬盘完成一次读取的数据单位。HFile物理存放形式是一个Block的序列外加这些Block的索引。这意味着,从HBase里读取一个Block需要先在索引上查找一次该Block然后从硬盘读出。Block是建立索引的最小数据单位,也是从硬盘读取的最小数据单位。Block大小按照列族设定,默认值是64KB。根据使用场景你可能会调大或者调小该值。如果主要用于随机查询,你可能需要细粒度的Block索引,小一点儿的Block更好一些。Block变小会导致索引变大,进而消耗更多内存。如果你经常执行顺序扫描,一次读取多个Block,大一点儿的Block更好一些。Block变大意味着索引项变少,索引变小,因此节省内存。

从HBase中读出一行,首先会检查MemStore等待修改的队列,然后检查BlockCache看包含该行的Block是否最近被访问过,最后访问硬盘上的对应HFile。HBase内部做了很多事情,这里只是简单概括。读路径如图2-2所示。

注意,HFile存放某个时刻MemStore刷写时的快照。一个完整行的数据可能存放在多个HFile里。为了读出完整行,HBase可能需要读取包含该行信息的所有HFile。

2.2.6 删除数据

从HBase中删除数据和存储数据工作方式类似。基于一个行键创建一个Delete命令实例:

也可以指定更多坐标删除行的一部分:

deleteColumns()方法从行中删除一个单元。这和deleteColumn()方法不同(注意方法名字尾部少了s)。deleteColumn()方法删除单元的内容。

2.2.7 合并:HBase的后台工作

Delete命令并不立即删除内容。实际上,它只是给记录打上删除的标记。就是说,针对那个内容的一条新“墓碑”(tombstone)记录写入进来,作为删除的标记。墓碑记录用来标志删除的内容不能在Get和Scan命令中返回结果。因为HFile文件是不能改变的,直到执行一次大合并(major compaction),这些墓碑记录才会被处理,被删除记录占用的空间才会释放。

合并分为两种:大合并(major compaction)和小合并(minor compaction)。两者将会重整存储在HFile里的数据。小合并把多个小HFile合并生成一个大HFile,如图2-3所示。因为读出一条完整的行可能引用很多文件,限制HFile的数量对于读性能很重要。执行合并时,HBase读出已有的多个HFile的内容,把记录写入一个新文件。然后,把新文件设置为激活状态,删除构成这个新文件的所有老文件[15]。HBase根据文件的号码和大小决定合并哪些文件。小合并设计出发点是轻微影响HBase的性能,所以涉及的HFile的数量有上限。这些都可以设置。

大合并将处理给定region的一个列族的所有HFile。大合并完成后,这个列族的所有HFile合并成一个文件。可以从Shell中手工触发整个表(或者特定region)的大合并。这个动作相当耗费资源,不要经常使用。另一方面,小合并是轻量级的,可以频繁发生。大合并是HBase清理被删除记录的唯一机会。因为我们不能保证被删除的记录和墓碑标记记录在一个HFile里面。大合并是唯一的机会,HBase可以确保同时访问到两种记录。

在NGDATA博客的帖子里更加详细地介绍了合并过程,以及增量图解。[16]

2.2.8 有时间版本的数据

HBase除了是无模式数据库以外,还是有时间版本概念(versioned)的数据库。例如,你可以按照时间回溯最初的密码:

每次你在单元上执行操作,HBase都隐式地存储一个新时间版本。单元的新建、修改和删除都会同样处理,它们都会留下新时间版本。Get请求根据提供的参数调出相应的版本。时间版本是访问特定单元时的最后一个坐标。当没有设定时间版本时,HBase以毫秒为单位使用当前时间[17],所以版本数字用长整型long表示。HBase默认只存储3个版本,这可以基于列族来设置。单元里数据的每个版本提交一个KeyValue实例给Result。你可以使用方法getTimestamp()来获取KeyValue实例的版本信息:

如果一个单元的版本超过了最大数量,多出的记录在下一次大合并时会扔掉。

除了删除整个单元,你也可以删除一个或几个特定的版本。之前提到的方法deleteColumns()(带s)处理小于指定时间版本的所有KeyValue。不指定时间版本时,默认使用当前时间now。方法deleteColumn()只删除一个指定版本。小心你调用的方法,它们的调用方式相似,含义略有不同。

2.2.9 数据模型概括

本节讨论了很多基础知识,包括数据模型和实现细节。现在暂停,复习一下到目前为止我们讨论了哪些东西。HBase模式里的逻辑实体如下。

表(table)——HBase用表来组织数据。表名是字符串(String),由可以在文件系统路径里使用的字符组成。

行(row)——在表里,数据按行存储。行由行键(rowkey)唯一标识。行键没有数据类型,总是视为字节数组byte[]。

列族(column family)——行里的数据按照列族分组,列族也影响到HBase数据的物理存放。因此,它们必须事前定义并且不轻易修改。表中每行拥有相同列族,尽管行不需要在每个列族里存储数据。列族名字是字符串(String),由可以在文件系统路径里使用的字符组成。

列限定符(column qualifier)——列族里的数据通过列限定符或列来定位。列限定符不必事前定义。列限定符不必在不同行之间保持一致。就像行键一样,列限定符没有数据类型,总是视为字节数组byte[]。

单元(cell)——行键、列族和列限定符一起确定一个单元。存储在单元里的数据称为单元值(value)。值也没有数据类型,总是视为字节数组byte[]。

时间版本(version)——单元值有时间版本。时间版本用时间戳标识,是一个long。没有指定时间版本时,当前时间戳作为操作的基础。HBase保留单元值时间版本的数量基于列族进行配置。默认数量是3个。

上述6个概念构成HBase的基础。用户最终看到的是通过API展现的上述6个基本概念的逻辑视图,它们是对HBase物理存放在硬盘上数据进行管理的基石。在学习HBase的过程中请牢牢记住这6个概念。

HBase的每个数据值使用坐标来访问。一个值的完整坐标包括行键、列族、列限定符和时间版本。下一节将详细介绍这些坐标。

2.3 数据坐标

在逻辑数据模型里,时间版本的数字也是数据的坐标之一。你可以想象,在关系型数据库里存储数据使用的是二维坐标系统,先是行后是列。照此类推,HBase在表里存储数据使用的是四维坐标系统。

HBase使用的坐标依次是行键、列族、列限定符和时间版本。users表的坐标如图2-4所示。

把所有坐标视为一个整体,HBase 可以看做是一个键值(keyvalue)数据库。抽象看逻辑数据模型,你可以把这组坐标看做键,把单元数据看做值(见图2-5)。

当使用HBase API检索数据时,你不需要提供全部坐标。如果你在Get命令中省略了时间版本,HBase返回数据值多个时间版本的映射集合。HBase允许你在一次操作中得到多个数据,它们按照坐标的降序排列。那么你可以把HBase看做是这样一种键值数据库,它的数据值是映射集合或者映射集合的集合。该思想如图2-6所示。

等本章后面我们介绍了HBase数据模型再详细讨论这个概念。

2.4 小结

现在知道了如何访问HBase,让我们在一个实际例子中练习已经学到的东西。首先为User实例定义一个简单模型对象,如代码清单2-1所示。

代码清单2-1 User的数据模型

然后在一个类中封装所有HBase访问操作。先声明普遍使用的字节数组byte[]常量,然后定义封装操作命令的方法,接下来是User模型的公有接口和私有实现,如代码清单2-2所示。

代码清单2-2 在UsersDAO.java里的CRUD操作

最后一部分是main()方法。让我们新建UsersTool来简化HBase里users表的访问,如代码清单2-3所示。

代码清单2-3 访问users表的命令行接口,UsersTool

完成所有代码后,你可以试一试。在本书源代码的根目录中编译jar应用:

这会在目标目录下生成文件 twitbase-1.0.0.jar。

用Users Tool往users表中增加用户Mark的信息很容易:

也可以列出表的内容:

初步掌握了如何访问HBase之后,让我们进一步理解HBase中使用的逻辑数据模型和物理数据模型。

2.5 数据模型

正如你看到的那样,HBase进行数据建模的方式和你熟悉的关系型数据库有些不同。关系型数据库围绕表、列和数据类型——数据的形态使用严格的规则。遵守这些严格规则的数据称为结构化数据。HBase设计上没有严格形态的数据。数据记录可能包含不一致的列、不确定大小等。这种数据称为半结构化数据(semistructured data)。

在逻辑模型里针对结构化或半结构化数据的导向影响了数据系统物理模型的设计。关系型数据库假定表中的记录都是结构化的和高度有规律的。因此,在物理实现时,利用这一点相应优化硬盘上的存放格式和内存里的结构。同样,HBase也会利用所存储数据是半结构化的特点。随着系统发展,物理模型上的不同也会影响逻辑模型。因为这种双向紧密的联系,优化数据系统必须深入理解逻辑模型和物理模型。

除了面向半结构化数据的特点外,HBase还有另外一个重要考虑因素——可扩展性。在半结构化逻辑模型里数据构成是松耦合的,这一点有利于物理分散存放。HBase的物理模型设计上适合于物理分散存放,这一点也影响了逻辑模型。此外,这种物理模型设计迫使HBase放弃了一些关系型数据库具有的特性。特别是,HBase不能实施关系约束(constraint)并且不支持多行事务(multirow transaction)[18]。这种关系影响了下面几个主题。

2.5.1 逻辑模型:有序映射的映射集合

HBase中使用的逻辑数据模型有许多有效的描述。图2-6把这个模型解释为键值数据库。我们考虑的一种描述是有序映射的映射(sorted map of maps)。你大概熟悉编程语言里的映射集合或者字典结构。可以把HBase看做这种结构的无限的、实体化的、嵌套的版本。

我们先来思考映射的映射这个概念。HBase使用坐标系统来识别单元里的数据:[行键,列族,列限定符,时间版本]。例如,从users表里取出Mark的记录(见图2-7)。

理解映射的映射的概念时,把这些坐标从里往外看。你可以想象,开始以时间版本为键、数据为值建立单元映射,往上一层以列限定符为键、单元映射为值建立列族映射,最后以行键为键列族映射为值建立表映射。这个庞然大物用Java描述是这样的:Map<RowKey, Map<ColumnFamily, Map<ColumnQualifier, Map<Version, Data>>>>。不算漂亮,但是简单易懂。

注意我们说映射的映射是有序的。上述例子只显示了一条记录,即使如此也可以看到顺序。注意password单元有两个时间版本。最新时间版本排在稍晚时间版本之前。HBase按照时间戳降序排列各时间版本,所以最新数据总是在最前面。这种物理设计明显导致可以快速访问最新时间版本。其他的映射键按照升序排列。现在的例子看不到这一点,让我们插入几行记录看看是什么样子:

现在再次列出Users表的内容,可以看到:

实践中,设计HBase表模式时这种排序设计是一个关键考虑因素。这是另外一个物理数据模型影响逻辑模型的地方。掌握这些细节可以帮助你在设计模式时利用这个特性。

2.5.2 物理模型:面向列族

就像关系型数据库一样,HBase中的表由行和列组成。HBase中列按照列族分组。这种分组表现在映射的映射逻辑模型中是其中一个层次。列族也表现在物理模型中。每个列族在硬盘上有自己的HFile集合。这种物理上的隔离允许在列族底层HFile层面上分别进行管理。进一步考虑到合并,每个列族的HFile都是独立管理的。

HBase的记录按照键值对存储在HFile里。HFile自身是二进制文件,不是直接可读的。存储在硬盘上HFile里的Mark用户数据如图2-8所示。注意,在HFile里Mark这一行使用了多条记录。每个列限定符和时间版本有自己的记录。另外,文件里没有空记录(null)。如果没有数据,HBase不会存储任何东西。因此列族的存储是面向列的,就像其他列式数据库一样。一行中一个列族的数据不一定存放在同一个HFile里。Mark的info数据可能分散在多个HFile里。唯一的要求是,一行中列族的数据需要物理存放在一起。

如果users表有了另一个列族,并且Mark在那些列里有数据。Mark的行也会在那些HFile里有数据。每个列族使用自己的HFile意味着,当执行读操作时HBase不需要读出一行中所有的数据,只需要读取用到列族的数据。面向列意味着当检索指定单元时,HBase不需要读占位符(placeholder)记录。这两个物理细节有利于稀疏数据集合的高效存储和快速读取。

让我们增加另外一个列族到users表,以存储TwitBase网站上的活动,这会生成多个HFile。让HBase管理整行的一整套工具如图2-9所示。HBase称这种机制为region,我们下一章会讨论。

在图2-9中可以看到,访问不同列族的数据涉及完全不同的MemStore和HFile。列族activity数据的增长并不影响列族info的性能。

2.6 表扫描

你可能发现,没有查询(query)命令。到目前为止,你都找不到这样的命令。查找包含某个特定值的记录的唯一办法是,使用扫描(Scan)命令读出表的某些部分,然后再使用过滤器(filter)来得到有关记录。可以想到,扫描返回的记录是排好序的。HBase设计上支持这种方式,因此速度很快。

要扫描得到整个表的内容,单独使用Scan构造函数即可:

但是,你经常只对整张表的一个子集感兴趣。比如,你想得到所有以字母T开头的ID的用户。给Scan构造函数增加起始行和结束行的信息即可:

这个例子也许有些牵强,但可以帮助你理解。一个实战的例子是什么样呢?假设你存储了推帖,你一定想进一步了解某个特定用户的最新推帖。让我们开始实现这一点。

2.6.1 设计用于扫描的表

就像设计关系模式一样,为HBase表设计模式(Schema)也需要考虑数据形态和访问模式。推帖数据的访问模型不同于用户,因此我们为它们新建自己的表。为了练手,这里使用Java API 而不是Shell来新建表。

可以使用HBase Admin对象的一个实例来执行表的操作:

创建HBase Admin实例显然需要一个Configuration实例,默认的HTable和HTablePool构造函数帮你隐藏细节。这一步很简单。现在你可以定义一个新表并且创建它:

HTableDescriptor对象建立新表的描述信息,其名字是twits。同样,使用HColumnDescriptor建立列族,名字也是twits。和users表一样,这里只需要一个列族。你不需要推帖的多个时间版本,所以限定保留的版本数为一个。

现在可以开始存储推帖到这个有趣的新twits表。推帖包含内容和发布的日期和时间等。你需要一个唯一值作为行键,所以我们选择用户名加上时间戳来做行键。很简单,我们存储一些推帖,如下所示:

好了,基本如此。首先请注意,用户ID是个变长字符串。当你使用复合行键时这会带来一些麻烦,因为你需要某种分隔符来切分出用户ID。一种变通的办法是对行键的变长类型部分做散列(hash)处理。选择一种散列算法生成固定长度的值。因为你想基于用户分组存储不同用户的推帖,MD5算法是一种好选择。这些组按序存储。在组内,推帖是基于发布日期时间先后顺序存储的。MD5是一种单向散列算法,所以不要忘了把未经编码处理的用户ID另外存储在一个列里,以防后面用到。如下所示,向twits表中写入数据。

一般来说,你会先用到最新推帖。HBase在物理数据模型里按照行键顺序存储行。你可以利用这个特性。在行键里包括推帖的时间戳,并且乘以−1,就可以先得到最新的推帖。

在HBase模式中行键设计至关重要

这一点如何强调都不为过:HBase的行键在设计表时是第一重要的考量因素。我们会在第4章进一步讨论。我们现在提到它是为了让你在学习例子时脑子里有个概念。当你看到HBase模式时第一个应该问自己的问题是:“行键是什么?”下一个问题是:“我可以怎样让行键更有效率?”

2.6.2 执行扫描

使用用户ID作为twits表行键的第一部分证明是好办法。它可以基于用户以自然行的顺序有效地生成数据桶(bucket)。来自同一用户的数据以连续行的形式存储在一起。现在Scan命令如何使用呢?或多或少和之前介绍的类似,只是计算停止键时复杂一点:

本例中,你可以通过对行键中用户ID部分的最后字符加1来生成停止键。扫描器返回包括起始键但是不包括停止键的记录,因此你只得到了匹配用户的推帖。

再通过一个简单的循环从ResultScanner中读出推帖:

循环中唯一需要处理的是分离出时间戳,并且把字节数组byte[]转换成合适的数据类型。你会得到如下数据:

2.6.3 扫描器缓存

在HBase的设置里扫描每次RPC调用得到一批行数据。这可以在扫描对象上使用setCaching(int)在每个扫描器(scanner)层次上设置,也可以在hbasesite.xml 配置文件里使用HBase.client.scanner.caching属性来设置。如果缓存值设置为n,每次RPC调用扫描器返回n行,然后这些数据缓存在客户端。这个设置的默认值是1,这意味着客户端对HBase的每次RPC调用在扫描整张表后仅仅返回一行。这个数字很保守,你可以调整它以获得更好的性能。但是该值设置过高意味着客户端和HBase的交互会出现较长暂停,这会导致HBase端的超时。

ResultScanner接口也有一个next(int)调用,你可以用来要求返回扫描的下面n行。这是在API层面提供的便利,与为了获得那n行数据客户端对HBase的RPC调用次数无关。

在内部机制中,ResultScanner使用了多次RPC调用来满足这个请求,每次RPC调用返回的行数只取决于你为扫描器设置的缓存值。

2.6.4 使用过滤器

并不总能设计一个行键来完美地匹配你的访问模式。有时你的使用场景需要扫描HBase的一组数据但是只返回它的子集给客户端。这时需要使用过滤器(filter)。为你的Scan对象增加过滤器,如下所示:

过滤器是在HBase服务器端上而不是在客户端执行判断动作。当你在Scan里设定Filter时,HBase使用它来决定一个记录是否返回。这样避免了许多不必要的数据传输。这个特性在服务器上执行过滤动作而不是把负担放在客户端。

使用过滤器需要实现 org.apache.hadoop.hbase.filter.filter 接口。HBase提供了许多种过滤器,但实现你自己的过滤器也很容易。

为了过滤所有提到TwitBase的推帖,你可以结合RegexStringComparator使用ValueFilter:

HBase也提供了一个过滤器构造类。ParseFilter对象实现了一种查询语言,可以用来构造Filter实例。可以用一个表达式构造同样的TwitBase 过滤器:

这两个例子中,数据在到达客户端之前在region中编译和使用了正则表达式。

上面是一个在应用中使用过滤器的简单例子。HBase中过滤器可以应用到行键、列限定符或者数据值。你也可以使用FilterList和WhileMatchFilter对象组合多个过滤器。过滤器允许对数据分页处理,限制扫描器返回的行数。我们将在第4章深入讨论组合型过滤器(bundled filter)。

2.7 原子操作

HBase操作库里的最后一个命令是列值递增(Increment Column Value)。它有两种使用方式,像其他命令那样使用Increment命令对象,或者作为HTableInterface的一个方法来使用。我们使用HTableInterface的方式,因为语义更直观。我们使用它来保存每个用户发布推帖的总数,如下所示:

该命令不用先读出HBase单元就可以改变存储其中的值。数据操作发生在HBase服务器上,而不是在你的客户端,所以速度快。当其他客户端也在访问同一个单元时,这样避免了出现紊乱状态。你可以把ICV(Increment Column Value)等同于Java的AtomicLong.addAndGet()方法。递增值可以是任何Java Long类型值,无论正负。我们将在下一节深入讨论原子性操作。

也请注意这个数据不是存储在twits表而是users表中。存在users表的原因是不希望这个信息成为扫描的一部分。存在twits表里会让常用的访问模式很不方便。

就像Java的原子类族,HTableInterface也提供checkAndPut()和checkAndDelete()方法。它们可以在维持原子语义的同时提供更精细地控制。你可以用checkAndPut()来实现incrementColumnValue()方法:

该实现有点长,但可以试试。使用checkAndDelete()的方式与此类似。

按照和前面相同的方式,你可以轻松地新建TwitsTool表。模型、DAO和命令行实现和前面users表的情况类似。本书附带的源代码提供了一个实现。

2.8 ACID语义

如果使用过数据库系统,你会听说过各种数据库系统提供的ACID语义。ACID是当你搭建使用数据库系统做存储的应用系统时需要掌握的一组要素。当应用系统访问承载它的数据库时,遵循这些要素可以使应用系统的行为更加合理。为简单起见,让我们再次定义ACID。记住,ACID不同于之前我们简要介绍过的CAP。

Atomicity(原子性)——原子性是指原子不可分的操作属性,换句话说,要么全部完成,要么全部不完成。如果操作成功,整个操作成功。如果操作失败,整个操作失败,系统会回滚到操作开始前的状态,就像这个操作从来没有执行过一样。

Consistency(一致性)—一致性是指把系统从一个有效状态带入另一个有效状态的操作属性。如果操作使系统出现不一致,操作不会被执行或者被回退。

Isolation(隔离性)——隔离性意味着两个操作的执行是互不干扰的。例如,同时在一个对象上不会出现两个写动作。写动作会一个接一个发生,而不会同时发生。

Durability(持久性)——持久性是我们早前谈论过的。它意味着数据一旦写入,确保可以读回并且不会在系统正常操作一段时间后丢失。

2.9 小结

为了避免漏掉学习内容,这里快速概括一下本章讲过的内容。

HBase是一种专门为半结构化数据(semistructured data)和水平可扩展性(horizontal scalability)设计的数据库。它把数据存储在表里。在表里,数据按照一个四维坐标系统来组织:行键列族列限定符时间版本。HBase是无模式数据库,只需要提前定义列族。它也是无类型数据库,把所有数据不加解释地按照字节数组存储。有5个基本命令用来访问HBase中的数据,即Get、Put、Delete、Scan和Increment。基于非行键值查询HBase的唯一办法是通过带过滤器的扫描

HBase不是一个ACID兼容数据库[19]

HBase不是一个ACID兼容数据库。但是HBase提供一些保证,当你的应用系统访问HBase系统时,你可以用其来使你的应用系统的行为更加合理。这些保证具体如下。

1.操作是低级原子不可分的。换句话说,给定行上的Put()要么整体成功要么整体失败回到操作开始前的状态,永远不会部分行写入而另一部分没有。这个要素和操作执行的列族的数量无关。

2.行间操作不是原子性的。不能保证所有操作整体成功或者失败。所有单行操作如上一点所述是原子性的。

3.check And*和increment*操作是原子不可分的。

4.对于给定行的多个写操作,总是以每个写操作为整体彼此独立的。这是第一点的延伸。

5.对于给定行的任何Get()操作,返回系统当时所保存的完整行。

6.全表扫描不是对某个时间点表的快照的扫描。如果扫描已经开始,但是在行R被扫描器对象读出之前,行R被改变了,那么扫描器读出行R更新后的版本。但是扫描器读出的数据是一致的,得到行R更新后的完整行。

当你搭建使用HBase的应用系统时,这些背景信息是你需要注意的要点。

数据模型从逻辑上可以分类为键值存储或者是有序映射的映射。物理数据模型是基于列族的列式数据库,单个记录以键值形式存储。HBase把数据记录保存在HFile里,这是一种不能更改的文件格式。因为记录一旦写入就不能修改,新值将保存在新HFile里。在读取数据和数据合并时,数据视图需要在内存中重新衔接。

HBase Java API通过HTableInterface来使用表。表连接可以直接通过构造HTable实例来建立。使用HTable实例系统开销大,优选方式是使用HTablePool,因为它可以重复使用连接。表通过 HbaseAdmin、HTableDescriptor 和HColumnDescriptor类的实例来新建和操作。5个命令通过相应的命令对象来使用:Get、Put、Delete、Scan和Increment。命令送到HtableInterface实例来执行。递增 Increment有另外一种用法,使用 HTableInterface.increment ColumnValue()方法。执行Get、Scan和Increment命令的结果返回到Result和ResultScanner对象的实例。一个KeyValue实例代表一条返回记录。所有这些操作也可以通过HBase Shell以命令行方式执行。

预期的数据访问模式对HBase的模式设计有很大的影响。理想情况下,HBase中的表根据预期的模式来组织。行键是HBase中唯一的全局索引坐标,因此查询经常通过行键扫描实现。复合行键是支持这种扫描的常见做法。行键值经常希望是均衡分布的。诸如MD5或SHA1等散列算法通常用来实现这种均衡分布。

相关图书

HBase入门与实践(第2版)
HBase入门与实践(第2版)
HBase入门与实践
HBase入门与实践
HBase权威指南
HBase权威指南
HBase管理指南
HBase管理指南

相关文章

相关课程