HBase运维和优化
管理工具
HBase Shell
HBase Shell是HBase组件提供的基于JRuby IRB的字符界面的交互式客户端程序,通过HBase Shell可以实现对HBase的绝大部分操作
通过help ["group-name"]命令,可以获取该组包含命令的详细使用说明
hbck工具
hbck工具对HBase中的数据进行扫描,找出错误的数据块,并生产简单的报表。该工具调用方法如下:
$ bin/hbase hbck
输出结果摘录如下:
......
Number of Tables: 1
Number of live region servers: 2
Number of dead region servers: 0
Master: node1,60000,1357616232695
Number of backup masters: 0
......
Summary:
ROOT is okay.
Number of regions: 1
Deployed on: node1,60020,1357613909450
.META. is okay.
Number of regions: 1
Deployed on: node2,60020,1357613870843
t1 is okay.
Number of regions: 1
Deployed on: node1,60020,1357613870843
0 inconsistencies detected.
Status: OK
说明:关于hbck工具的详细信息,可参考HBase文档:http://hbase.apache.org/book/hbck.in.depth.html
hfile工具
hfile工具主要用于分析HBase的数据文件HFile。该工具的使用方法如下:
$ bin/hbase hfile [-a] [-b] [-e] [-f <arg>] [-k] [-m] [-p] [-r <arg>] [-s] [-v]
hfile工具具体的参数如表5-2所示。
表5-2 hfile参数
参数 |
说明 |
a,-checkfamily |
启用列族检查 |
b,-printblocks |
打印块索引元数据 |
e,-printkey |
打印所有rowkey |
f,-file <full/path/to/hfile> |
设置要分析的HFile,应输入完整的路径名,如hdfs://namenode:8020/hbase/.META./12/34 |
k,-checkrow |
查找没有排序的行 |
m,-printmeta |
打印hfile的元数据信息 |
p,-printkv |
打印所有的<Key/Value>键值对 |
r,-region <region-name> |
设置要分析的Region,输入Region名,如".META.,,1" |
s,-stats |
打印统计信息 |
v,-verbose |
打印详细信息,包括元数据和文件分割符 |
hlog工具
hlog工具主要用于分析HBase的WAL日志HLog文件。该工具的使用方法如下:
$ bin/hbase hlog <filename...> [-h] [-j] [-p] [-r <arg>] [-s <arg>] [-w <arg>]
hlog工具具体的参数如表5-3所示。
表5-3 hlog参数
参数 |
说明 |
h,-help |
打印帮助信息 |
-j, --json |
设置分析结果以json格式输出 |
p,-printvals |
打印所有值 |
r,-region <region-name> |
设置要分析的Region |
s,-sequence <sequence-num> |
设置要分析的序列 |
w,-row <row-name> |
设置要分析的行 |
zkcli工具
zkcli工具是hbase包装的ZooKeeper Shell,通过它可以查看HBase集群使用的ZooKeeper集群的信息。该工具的启用方法如下:
$ bin/hbase zkcli
启用后,会进入如下界面:
Welcome to ZooKeeper!
...
JLine support is enabled
...
WATCHER::
WatchedEvent state:SyncConnected type:None path:null
[zk: node5:2181(CONNECTED) 0]
在该提示符下输入任意一个字符,可获取zkcli支持的命令列表
5.2.3 日常维护
Compaction操作
HBase每隔一段时间会对将许多小的HBase数据文件(HFile)合并成大文件,这个过程叫做Compaction。Compaction操作可有效较少HFile的个数,节约磁盘空间,提高HBase的性能。RegionServer在执行Compaction操作期间会占用大量的内存资源,过于频繁的Compaction操作会影响HBase的性能,而Compaction操作周期过长也会导致期间积累的HFile过多,单次Compaction时间很长,同样也会影响性能。如果HBase在运行期间一直保持较高的Compaction频率,应该考虑添加新的节点以提高集群的负载能力。
说明:关于HBase Compaction的详细信息,请参考HBase文档:http://hbase.apache.org/book/regions.arch.html#compaction
Split操作
HBase的Region大小是由上限的,当Region的大小超过了这个限制,RegionServer就会执行一次Split过程,将这个Region一份为二,这个过程叫做Split。Split过程使用标记方式,将实际的数据分割操作放在后台进行,因此,该操作速度较快。Split操作可以将Region分成两份,分配给不同的RegionServer管理。如果HBase中的数据存在局部过热的Region,可以考虑手动对这些Region执行split操作,并将这些Region重新分配给不同节点。下面是这个过程的HBase Shell示例:
hbase(main):010:0> split 'test','test,row150,1357626052663.15bbf20f9ce9b38e0a6dcb0732a90945'
hbase(main):012:0> move '9de82062a65b07cc70b999793ad658dd', 'apache-node3,60020,1357613909450'
数据备份
HBase的数据都记录在HDFS的/hbase目录下,可以将HBase数据作为普通的HDFS文件进行备份,相关内容可参见3.2.3日常维护章节内容。也可以使用HBase提供的Replication机制进行数据备份。Replication机制基于操作日志将HBase数据同步到备用集群。关于Replication的内容,请参见HBase文档:http://hbase.apache.org/replication.html。
数据迁移
HBase数据迁移问题主要包括三个方面,如下所示:
- 从外部数据源(如关系型数据库)导入数据
- 将HBase数据导入外部数据源
- HBase集群间的数据迁移
对于第一、二种情况,可以利用HBase API编写相关的导入程序完成数据导入/导出操作,对于第三种情况,当然也使用可以和一、二两种情况相同的方法,不过针对第三种情况,有更简单的方法。
- 导出数据
HBase提供导出数据的工具用来将HBase表格数据导出本地磁盘或HDFS上,该工具为:org.apache.hadoop.hbase.mapreduce.Export,使用方法如下:
$ bin/hbase org.apache.hadoop.hbase.mapreduce.Export [-D <property=value>]* <tablename> <outputdir> [<versions> [<starttime> [<endtime>]] [^[regex pattern] or [Prefix] to filter]]
设置参数可以限制导出的数据范围。下面的例子将表t1的f1列族导出到HDFS上:
$ bin/hbase –D hbase.mapreduce.scan.column.family=f1 t1 hdfs://node1:8020/tmp/t2_backup
- 导入数据
对应的,HBase也提供了导入工具,可将导出的数据导入到HBase中,该工具为org.apache.hadoop.hbase.mapreduce.Import,使用发方法如下:
$ bin/hbase org.apache.hadoop.hbase.mapreduce.Import <tablename> <inputdir>
*Import工具将数据导入HBase中已存在的表中,如果表不存在,将会发生错误。
- 导入TSV格式的数据
TSV (Tab Separated Values)格式的数据以Tab分隔每个列的数据。HBase提供了ImportTsv工具来导入这种数据:
$ bin/hbase org.apache.hadoop.hbase.mapreduce.ImportTsv -Dimporttsv.columns=a,b,c <tablename> <inputdir>
下面给出一个示例,设HDFS上有一个TSV格式的数据文件/tmp/tsv如下所示:
row1c1c2
row2c1c2
row3c1c2
设第一列数据为rowkey,第二列对应HBase中的列为"f1:c1",第三列对应HBase中的列为"f1:c2",使用ImportTsv工具导入数据:
$ bin/base org.apache.hadoop.hbase.mapreduce.ImportTsv -Dimporttsv.columns=HBASE_ROW_KEY,f1:c1,f1:c2 tsv hdfs://node1:8020/tmp/tsv
ImportTsv工具也需要导入前HBase中已存在目标表格。
说明:Sqoop是一个用来将Hadoop和关系型数据库中的数据相互转换的数据迁移工具。CDHv1.0不包含Sqoop组件,但是兼容Apache Sqoop 1.4.2及以上版本。关于Sqoop的信息,请参见Sqoop官方网站:http://sqoop.apache.org/。
数据压缩
对于存在I/O瓶颈的应用中,启用压缩是一个不错的选择。数据压缩不但节约了磁盘空间,也加快了数据传输效率。HBase支持全局设置压缩算法,也支持按列族压缩数据。全局压缩算法通过" hbase.regionserver.codecs"来设置。HBase支持的压缩算法如表5-5所示。下面的示例为列族"f1"设置GZip压缩算法。
hbase(main):010:0> distable 't1'
0 row(s) in 1.0700 seconds
hbase(main):005:0> alter 't1', {NAME => 'f1', COMPRESSION =>'GZ'}
Updating all regions with the new schema...
1/1 regions updated.
Done.
0 row(s) in 1.2980 seconds
hbase(main):006:0> enable 't1'
0 row(s) in 2.0700 seconds
表5-5 HBase支持的压缩算法及性能比较
压缩算法 |
配置名 |
压缩率 |
编码效率 |
解码效率 |
LZO算法 |
LZO |
20.5% |
135 MB/s |
410 MB/s |
GZIP算法 |
GZ |
13.4% |
21 MB/s |
118 MB/s |
SNAPPY |
SNAPPY |
22.2% |
172 MB/s |
409 MB/s |
添加节点
为HBase添加新的RegionServer非常简单,只需在新的节点启动新的RegionServer即可。具体步骤如下:
- 在新的节点部署和配置HBase
- 在新节点运行下述命令启动新的RegionServer
$ bin/hbase-daemon.sh start regionserver
- 更新集群配置,将新节点加入regionservers文件中
- 刷新Web UI,检查新节点是否已经加入集群
删除节点
从HBase上动态删除RegionServer节点也比较方便,具体步骤如下:
- 在待删除的节点运行下述命令关闭RegionServer,该命令将告知Master重新分配该RegionServer上的Region到其他RegionServer上:
$ bin/hbase-daemon.sh stop regionserver
- 更新集群配置,将待删除节点从regionservers文件中删除
- 刷新Web UI,检查该节点是否已经退出集群
5.3性能调优
5.3.1优化系统配置
优化项 |
优化原理 |
推荐做法 |
Master服务器的数量 |
一个集群只有一台active的Master,其他的都作为backup备份机器。可尽量的多配置几台Master,配置更多数量的Master服务器没有坏处,但是配置太少会降低高可用性。 |
在集群的机器上,内存许可的条件下,尽量都运行Master服务 |
每台机器内存大小 |
RegionServer会在内存中保留很多数据,需要占用较多的内存。200个region配20G内存给RegionServer还好,若超过200个region便会影响读写情况。每台机器除了RS外,大多还运行了Master, ZooKeeper, DataNode等服务,所以单台服务器的整体内存需要一个较高的配置 |
最好有48G的内存,最少24G的内存 |
文件句柄数 |
由于 Linux系统最大可打开文件数一般默认的参数值是1024,通过 ulimit -n 65535 可即时修改,但重启后就无效了 |
在文件/etc/security/limits.conf 有服务可打开文件句柄数的最大值配置,重启后仍有效,添加如下两行:* soft nofile 327680* hard nofile 327680 同时将单个用户可用的最大线程数也配大一些,即再添加如下几行:hdfs soft nproc 131072hdfs hard nproc 131072mapred soft nproc 131072mapred hard nproc 131072hbase soft nproc 131072hbase hard nproc 131072zookeeper soft nproc 131072zookeeper hard nproc 131072hive soft nproc 131072hive hard nproc 131072 |
5.3.2 优化配置项
优化项 |
优化原理 |
推荐做法 |
zookeeper.session.timeout |
RegionServer与Zookeeper间的连接超时时间。当超时时间到后,ReigonServer会被Zookeeper从RS集群清单中移除,HMaster收到移除通知后,会对这台server负责的regions重新balance,让其他存活的RegionServer接管.这个timeout决定了RegionServer是否能够及时的failover。设置成1分钟或更低,可以减少因等待超时而被延长的failover时间。 但是,对于一些Online应用,RegionServer从宕机到恢复时间本身就很短的(网络闪断,crash等故障,运维可快速介入),如果调低timeout时间,反而会得不偿失。因为当ReigonServer被正式从RS集群中移除时,HMaster就开始做balance了(让其他RS根据故障机器记录的WAL日志进行恢复)。当故障的RS在人工介入恢复后,这个balance动作是毫无意义的,反而会使负载不均匀,给RS带来更多负担。特别是那些固定分配regions的场景。 |
修改hbase-site.xml |
hbase.regionserver.handler.count |
RegionServer的请求处理IO线程数。较少的IO线程,适用于处理单次请求内存消耗较高的Big PUT场景(大容量单次PUT或设置了较大cache的scan,均属于Big PUT)或ReigonServer的内存比较紧张的场景。较多的IO线程,适用于单次请求内存消耗低,TPS要求(每秒事务处理量非常高的场景。设置该值的时候,以监控内存为主要参考。但是如果server的region数量很少,大量的请求都落在一个region上,因快速充满memstore触发flush导致的读写锁会影响全局TPS,不是IO线程数越高越好。 |
修改hbase-site.xml 推荐设置为50 |
hbase.hregion.max.filesize |
当前ReigonServer上单个Reigon的最大存储空间,单个Region超过该值时,这个Region会被自动split成更小的region。小region对split和compaction友好,因为拆分region或compact小region里的storefile速度很快,内存占用低。缺点是split和compaction会很频繁,特别是数量较多的小region不停地split, compaction,会导致集群响应时间波动很大,region数量太多不仅给管理上带来麻烦,甚至会引发一些Hbase的bug。一般512M以下的都算小region。大region,则不太适合经常split和compaction,因为做一次compact和split会产生较长时间的停顿,对应用的读写性能冲击非常大。此外,大region意味着较大的storefile,compaction时对内存也是一个挑战。大region适合场景:如果应用场景中某个时间点的访问量较低,那么此时做compact和split,既能顺利完成split和compaction,又能保证绝大多数时间平稳的读写性能。 |
修改hbase-site.xml |
hfile.block.cache.size |
storefile的读缓存占用Heap的大小百分比,默认0.2表示20%。该值直接影响数据读的性能。当然是越大越好,如果读比写多,开到0.4-0.5也没问题。如果读写较均衡,0.3左右。如果写比读多,用默认即可。 |
修改hbase-site.xml |
hbase.hstore.blockingStoreFiles |
阻塞写请求的最大storefile数:即当一个store中有超过此值个storefile待compact,则阻塞写请求。block写请求会影响当前region的性能,将值设为单个region可以支撑的最大store file数量会是个不错的选择,即允许comapction时,memstore继续生成storefile。最大storefile数量可通过region size/memstore size来计算。 |
默认7,若写请求大大多于读请求,修改修改hbase-site.xml,54 (3.5G/64M),但54太大,将其配置为15. |
避免CMS concurrent mode failure |
HBase使用CMS GC。默认触发GC的时机是当年老代内存达到90%的时候,这个百分比由 -XX:CMSInitiatingOccupancyFraction=N 这个参数来设置。concurrent mode failed发生在这样一个场景: 当年老代内存达到90%的时候,CMS开始进行并发垃圾收集,于此同时,新生代还在迅速不断地晋升对象到年老代。当年老代CMS还未完成并发标记时,年老代满了,悲剧就发生了。CMS因为没内存可用不得不暂停mark,并触发一次全jvm的stop the world(挂起所有线程),然后采用单线程拷贝方式清理所有垃圾对象。这个过程会非常漫长。为了避免出现concurrent mode failed,我们应该让GC在未到90%时,就触发。 通过设置 -XX:CMSInitiatingOccupancyFraction=N 这个百分比, 可以简单的这么计算。如果你的 hfile.block.cache.size 和 hbase.regionserver.global.memstore.upperLimit 加起来有60%(默认),那么你可以设置 70-80,一般高10%左右差不多。 |
修改 hbase-env.shexport HBASE_OPTS="$HBASE_OPTS -ea -XX:+HeapDumpOnOutOfMemoryError -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70" |
maxClientCnxns |
增大zookeeper的最大连接数可以提高集群的并发性能。 |
|
5.3.3 客户端优化配置
优化项 |
优化原理 |
优化方法 |
建表时预创建region |
对于rowkey不以时间作为起始不分的表,可以在建表时预创建region,这样便免去了开始写入阶段频繁的split操作。 |
调用HBaseAdmin的 createTable(final HTableDescriptor desc, byte [][] splitKeys)方法来指定region的分隔符 |
客户端AutoFlush |
客户端批量更新开关,设为false则当Put填满客户端flush缓存时,才发送到服务端。默认为true |
使用HTable的setAutoFlush(boolean autoFlush)来配置为false |
Scan Caching |
scanner一次缓存多少数据来scan(从服务端一次抓多少数据回来scan)。 |
修改hbase-site.xml 推荐设置hbase.client.scanner.caching为500 |
用完关闭ResultScanners |
若不关闭ResultScanner, RegionServer可能会出现问题(对应的Server资源无法释放)。 |
通过scan取完数据后,要关闭ResultScanner。 |
选择性关闭WAL写日志 |
当Put一些非重要的数据时,可以关闭WAL,不预写日志,可进一步提高写性能,风险是,若RS宕机,则刚才put的数据会丢失,且无法恢复 |
调用Put的writeToWAL(false) |
批量Put |
在不影响业务要求的前提下,可以进行批量put,提高写性能。 |
调用HTable的put(final List<Put> puts)方法来批量写 |
设置不同备份数 |
在建表时,根据不同表数据的重要性,可以按照列族设置其备份数。 |
调用HColumnDescriptor的setReplication(short replica)来配置 |
TTL设置 |
可以设置列族的TTL(Time To Live, 存活时间),当前时间-录入时间若超过了设置的TTL值,HBase会将其删除,设置此项,方便管理有时效性限制的数据。 |
调用HColumnDescriptor.setTimeToLive(777600),参数单位为秒,如此便设置成3个月;默认是2147483647,68年多一些。 |
常见问题
Invalid maximum heap size: -Xmx0m
Could not create the Java virtual machine.
不正确的内存设置(分配给master的最大内存为0MB)会导致master的.out日志文件输出上述信息,解决方法是修改hbase-env.sh文件,将HBase_MASTER_OPTS中添加-Xmx{size}m项,{size}表示内存大小,以MB为单位,如为master分配2G内存,可使用-Xmx2048m项。
ERROR: Table xxx is enabled. Disable it first.
HBase中应先disable表格,然后删除表格,否则无法删除表格,并出现上述信息。该信息还有可能在没有disable表格之前就进行表格元数据(HTableDescription\HColumnDescription等)的修改操作。
org.apache.zookeeper.ClientCnxn: Session 0x23c17f38b2e0000 for server null, unexpected error, closing socket connection and attempting reconnect
该错误是由于无法连接ZooKeeper集群造成的,出现上述问题时,请检查如下几项是否正常:
- 网络连接是否正常;
- 防火墙是否关闭;
- 检查HBase ZooKeeper节点配置是否正确;
- ZooKeeper集群是否运行。
...too many open files...
操作系统同时打开的文件数是有限的(默认为1024),超过该限制将出现上述错误。可以通过修改系统文件提高该值,具体如下:
在 /etc/security/limits.conf 的末尾加上以下两行:
注意,应把下面的root替换成实际用来执行hbase client的linux用户。
root soft nproc 65536
root hard nproc 65536
...Master rejected startup because clock is out of sync...
HBase内部各部件的RPC服务需要时间同步,当节点之间的时间差超出了配置的阈值(由hbase.master.maxclockskew配置项设定),将出现上述错误,并将导致无法启动RegionServer。解决方法是调整各个节点的时间,使节点时间差小于设定值。为了一劳永逸的解决这个问题,建议在集群中配置NTP服务器。
...connection reset by peer...
网络异常和客户端长时间无操作都有可能导致服务器重置连接,出现上述现象。解决方案:
- 如果是网络异常造成上述现象出现,请检查集群的网络连接;
- 如果是客户端长时间无操作造成连接重置,只需在客户端中加入重连逻辑即可。
... HBase is able to connect to ZooKeeper but the connection closes immediately....
网络异常和连接数过多都可能导致上述问题的发生,解决方案:
- 如果是网络异常造成上述现象出现,请检查集群的网络连接;
- 如果是连接数过多的情况,需修改配置项hbase.zookeeper.property.maxClientCnxns,增加连接数。
... ScannerTimeoutException...
HBase执行Scan操作时长时间没有响应将导致上述异常,解决方案:
- 修改hbase-site.xml,hbase.regionserver.lease.period改为180000,默认60000(ms)
- 修改客户端的配置:
conf.setLong(HConstants.HBASE_REGIONSERVER_LEASE_PERIOD_KEY, 180000)
... Cluster key invalid, the format should be:...
不正确的系统升级或维护过程不恰当的操作使得一些旧的Zookeeper信息被保留下来,与新的Zookeeper集群发生冲突。解决方案:
- 停止HBase集群(如果使用的是独立ZooKeeper集群,还需停止Zookeeper集群);
- 删除每个ZooKeeper节点下的ZooKeeper数据(由hbase.zookeeper.property.dataDir配置)
- 重启ZooKeeper集群和HBase集群。