Praxis
在这一小节,我们将讨论在应用中运行HBase集群时用户常碰到的一些问题。
版本
一直到HBase 0.20, HBase的版本都对应于Hadoop的版本。某个版本的HBase能 够和任何“小版本”(minor version)相同的Hadoop共同运行。小版本就是两个小 数点之间的数字(如,HBase 0.20.5的小版本是20)。HBase 0.20.5可以和Hadoop 0.20.2 一起运行,但 HBase 0.19.5 不能和 Hadoop 0.20.0 一起运行。
但从HBase 0.90开始,两者之间的联系不复存在。Hadoop的开发周期也变长,和HBase的开发周期不再匹配,此外,改变版本号联系还有一个原因是想让一个HBase版本可以运行在多版本的Hadoop上。例如,HBase 0.90.x在Hadoop 0.20.x 和0.21x上都能运行。
这意味着必须保证运行的Hadoop和HBase纪版本是兼容的。请检査下载版本的“要 求”(requirement)一节。如果运行不兼容的版本,幸运的话,系统会抛出异常,报 告版本不兼容。如果两者相互之间根本不能交换版本信息,你会发现HBase集群 在启动后很快就挂在那里,停止运行。以上两种情况还会在系统升级时碰到。升级 后,由于清除得不干净,仍然可以在类路径上找到老版本HBase或Hadoop。
HDFS
HBase使用HDFS的方式与MapReduce使用HDFS的方式截然不同。在 MapReduce中,首先打开HDFS文件,然后map任务流式处理文件的内容,最后 关闭文件。在HBase中,数据文件在启动时就被打开,并在处理过程中始终保持 打开状态,这是为了节省每次访问操作需要打开文件的代价。所以,HBase更容易 碰到MapReduce客户端不常碰到的问题:
文件描述符用完:由于我们在连接的集群上保持文件的打开状态,所以用不了太长时间就可能达 到系统和Hadoop设定的限制。例如,我们有一个由三个节点构成的集群,毎 个节点上运行一个datanode实例和一个Regionserver。如果我们正在运行一个 加载任务,表中有100个区域和10个列族。我们允许每个列族平均有两个 “刷入文件”(flush file)。通过计算,我们知道同时打开了 100xl0x2,即 2000个文件。此外,还有各种外部扫描器和Java库文件占用了文件描述符。 每个打开的文件在远程datanode上至少占用一个文件描述符。一个进程默认 的文件描述符限制是1024。当我们使用的描述符个数超过文件系统的uiimit 值,我们会在日志中看到“Foo many openfdes” (打开了太多文件)的错误信 息。但在这之前,往往就已经能看出HBase的行为不正常。发生哪种错误行 为是不一定的。要修正这个问题需要增加文件描述符的ulimit参数值。可以 通过査看Regionserver日志的前几行来确定运行中的HBase是否设置了足够 多的文件描述符。日志中列出系统的重要组件(如使用的JVM)以及环境设置 (如描述符的ulimit值)。
datanode线程用完:和前面的情况类似,Hadoop的datanode上同时运行的线程数不能超过256这 一限制值。给定前面所描述的表的情况,我们很容易看到很快就会达到这一限 制值,因为每个datanode在写操作时,到文件块的每个打开.的连接都会使用 一个线程。如果查看 datanode 日志,会看到 “xceiverCount 258 exceeds the limit of concurrent xcievers 256” (xceiverCount258 超过了并发 xcievers 的 256 限制)这样的出错信息。同样,很可能在你看到日志中的出错信息之前,HBase 的行为就已经出错了。这时需要在HDFS中把dfs.datanode.max.xcievers 的值调髙,并重启集群。
Sync:必须在有可用sync的HDFS上使用HBase。否则会丢失数据。这意味着需要 在Hadoop 0.21.x版本上或在branch-0.20-append分支上编译的版本上运 行 HBase。branch-0.20-append 在 Hadoop 0.20 版本里添加了可用的sync/append(同步/追加)。
用户界面
HBase在主控机上运行了一个Web服务器,它能提供运行中集群的状态视图。默 认情况下,它监听60010端口。主界面显示了基本的属性(包括软件版本、集群负 载、请求频率、集群表的列表)和加入的Regionserver等。在主界面上单击选中 Regionserver会把你带到那个Regionserver上运行的Web服务器。它列出了这个服 务器上所有区域的列表及其他基本的属性值(如使用的资源和请求频率)。
度量
Hadoop 有一个度量(metric)系统。可以用它每过一段时间获取系统重要组件的信 息,并输出到上下文(context)。启用Hadoop度 量系统,并把它捆绑入Ganglia或导出到JMX,从而得到集群上正在做和刚才做的 事情的视图。HBase也有它自己的度量一请求频率、组件计数、资源使用情况 等——可以通过Hadoop上下文获得它们。相关信息可参见HBase conf目录下的 hadoop-metrics-properties 文件。
模式的设计
单元格是有版本的,数据行是有序的,只要列族存在,列便可以由客户端随时添 加;除了这三个特性以外,HBase的表和RDBMS中的表是类似的。但是,在为HBase设计模式时,需要考虑这些不同点。但最重要的是考虑数据的访问方式。所 有的数据都是通过主键进行访问的。所以在设计时,最主要的问题是知道如何査询 这些数据。在对1183^这样的面向列(族)的存储设计模式时,另一件需要记住的事 情是它可以以极小的开销管理较宽的稀疏表。
连接
HBase并没有内置对数据库连接的支持。但是“宽表”(wide table)使我们并不需要 让一个表和第二个表或第三个表进行数据库连接。一个宽行有时可以容下一个主键 相关的所有数据。
行键
应该把较多的精力用于设计行的键。在本章的气象数据示例,复合的行键利用观测 站作为前缀,对同一个观测站的气温数据进行分组。反向时间戳后缀使我们可以按 时间序读到从最近到最远的气温数据。一个精心设计的复合键可以用来对数据进行 聚类,以配合数据的访问方式。
设计复合键时,可能需要用0来填充数据,使行键可以正确排序。否则,会碰到由 于只考虑字节序而导致10排在2之前的情况。
如果键是整数,则应该使用二进制形式,而不是把数据持久化成字符串类型,这样 可以节省存储空间。
计数器
在StumbleUpon,第一个在HBase上部署的产品特性是为stumbleupon.com前端 维护计数器。计数器以前存储在MySQL中,但计数器的更新太频繁,计数器所导 致的写操作太多,所以Web设计者必须对计数值进行限定。使用 org.apache.hadoop.hbase.HTable 的 incrementColumnValue()方法以后,计数器每秒可以实现数千次更新。
批量加载
HBase有一个高效的“批量加载”(bulk loading)工具。它从MapReduce把以内部 格式表示的数据直接写人文件系统,从而实现批量加载。顺着这条路,我们加载 HBase实例的速度比用HBase客户端API写人数据的方式至少快一个数量级。这 个工具的相关介绍可访问 http:〃hbase.apache.org/docs/current/bulk-loads.html。它还 能向使用中的表批量加载数据。