hbase使用、运维、改进(不断更新)

刚刚看了google jeff dean 在新的一年里发表的演讲,讲到各种系统配合使用完成海量数据处理任务。深有感触:http://t.cn/zYE89gn 。2013年,依然会专注hbase研究,并以此为基础扩展,对hbase衍生的一些特性和产品进行深入研究,例如replication、phoenix。从传统的离线计算(hadoop、hive),到实时流式计算系统(storm、s4),创新应用性接口(Impala、phoenix),这些hbase的上下游系统、接口扩展等都要进行全面的了解。

       以hbase为基础,让各个面向不同使用场景的系统配合起来共同工作,打造大数据处理体系架构。需要学习的东西很多,2013年,加油!

      

       1、hbase的client端hostname错误导致“Thu Mar 07 13:21:11 CST 2013, org.apache.hadoop.hbase.client.ScannerCallable@79ee2c2c, java.net.UnknownHostException”

 理论上说,hbase的client端会去连接hbase cluster,通过集群返回查询结果,自身的hostname不会影响查询。直到遇到这个异常,通过代码发现client在做scan时会调用一个函数

[java]  view plain copy
  1. /** 
  2.    * compare the local machine hostname with region server's hostname 
  3.    * to decide if hbase client connects to a remote region server 
  4.    * @throws UnknownHostException. 
  5.    */  
  6.   private void checkIfRegionServerIsRemote() throws UnknownHostException {  
  7.     String myAddress = DNS.getDefaultHost("default""default");  
  8.     if (this.location.getHostname().equalsIgnoreCase(myAddress)) {  
  9.       isRegionServerRemote = false;  
  10.     } else {  
  11.       isRegionServerRemote = true;  
  12.     }  
  13.   }  

该函数检查连接的region是否就是本地。所以client端去尝试本机的host时会报UnknownHostException异常


       2、hbase的coprocessor中传递自定义类报不支持错误。在coprocessor中传递的对象,需要传递,所以需要序列化和反序列化

      在ExecResult中,序列化和反序列化都依赖一个类HbaseObjectWritable,而这个类中需要声明的有以下3个参数

      Class<?>declaredClass

      Object instance

      Configuration

       同时,HbaseObjectWritable还规定了能够被识别的对象code,没有注册code的也依然会报错。

[java]  view plain copy
  1. static {  
  2.       
  3.     // WARNING: Please do not insert, remove or swap any line in this static  //  
  4.     // block.  Doing so would change or shift all the codes used to serialize //  
  5.     // objects, which makes backwards compatibility very hard for clients.    //  
  6.     // New codes should always be added at the end. Code removal is           //  
  7.     // discouraged because code is a short now.                               //  
  8.       
  9.   
  10.     int code = NOT_ENCODED + 1;  
  11.     // Primitive types.  
  12.     addToMap(Boolean.TYPE, code++);  
  13.     addToMap(Byte.TYPE, code++);  
  14.     addToMap(Character.TYPE, code++);  
  15.     addToMap(Short.TYPE, code++);  
  16.     addToMap(Integer.TYPE, code++);  
  17.     addToMap(Long.TYPE, code++);  
  18.     addToMap(Float.TYPE, code++);  
  19.     addToMap(Double.TYPE, code++);  
  20.     addToMap(Void.TYPE, code++);  
  21.   
  22.     // Other java types  
  23.     addToMap(String.class, code++);  
  24.     addToMap(byte [].class, code++);  
  25.     addToMap(byte [][].class, code++);  
  26.   
  27.     // Hadoop types  
  28.     addToMap(Text.class, code++);  
  29.     addToMap(Writable.class, code++);  
  30.     addToMap(Writable [].class, code++);  
  31.     addToMap(HbaseMapWritable.class, code++);  
  32.     addToMap(NullInstance.class, code++);  
  33.   
  34.     // Hbase types  
  35.     addToMap(HColumnDescriptor.class, code++);  
  36.     addToMap(HConstants.Modify.class, code++);  
  37.   
  38.     // We used to have a class named HMsg but its been removed.  Rather than  
  39.     // just axe it, use following random Integer class -- we just chose any  
  40.     // class from java.lang -- instead just so codes that follow stay  
  41.     // in same relative place.  
  42.     addToMap(Integer.class, code++);  
  43.     addToMap(Integer[].class, code++);  
  44.   
  45.     addToMap(HRegion.class, code++);  
  46.     addToMap(HRegion[].class, code++);  
  47.     addToMap(HRegionInfo.class, code++);  
  48.     addToMap(HRegionInfo[].class, code++);  
  49.     addToMap(HServerAddress.class, code++);  
  50.     addToMap(HServerInfo.class, code++);  
  51.     addToMap(HTableDescriptor.class, code++);  
  52.     addToMap(MapWritable.class, code++);  
  53.   
  54.     //  
  55.     // HBASE-880  
  56.     //  
  57.     addToMap(ClusterStatus.class, code++);  
  58.     addToMap(Delete.class, code++);  
  59.     addToMap(Get.class, code++);  
  60.     addToMap(KeyValue.class, code++);  
  61.     addToMap(KeyValue[].class, code++);  
  62.     addToMap(Put.class, code++);  
  63.     addToMap(Put[].class, code++);  
  64.     addToMap(Result.class, code++);  
  65.     addToMap(Result[].class, code++);  
  66.     addToMap(Scan.class, code++);  
  67.   
  68.     addToMap(WhileMatchFilter.class, code++);  
  69.     addToMap(PrefixFilter.class, code++);  
  70.     addToMap(PageFilter.class, code++);  
  71.     addToMap(InclusiveStopFilter.class, code++);  
  72.     addToMap(ColumnCountGetFilter.class, code++);  
  73.     addToMap(SingleColumnValueFilter.class, code++);  
  74.     addToMap(SingleColumnValueExcludeFilter.class, code++);  
  75.     addToMap(BinaryComparator.class, code++);  
  76.     addToMap(BitComparator.class, code++);  
  77.     addToMap(CompareFilter.class, code++);  
  78.     addToMap(RowFilter.class, code++);  
  79.     addToMap(ValueFilter.class, code++);  
  80.     addToMap(QualifierFilter.class, code++);  
  81.     addToMap(SkipFilter.class, code++);  
  82.     addToMap(WritableByteArrayComparable.class, code++);  
  83.     addToMap(FirstKeyOnlyFilter.class, code++);  
  84.     addToMap(DependentColumnFilter.class, code++);  
  85.   
  86.     addToMap(Delete [].class, code++);  
  87.   
  88.     addToMap(HLog.Entry.class, code++);  
  89.     addToMap(HLog.Entry[].class, code++);  
  90.     addToMap(HLogKey.class, code++);  
  91.   
  92.     addToMap(List.class, code++);  
  93.   
  94.     addToMap(NavigableSet.class, code++);  
  95.     addToMap(ColumnPrefixFilter.class, code++);  
  96.   
  97.     // Multi  
  98.     addToMap(Row.class, code++);  
  99.     addToMap(Action.class, code++);  
  100.     addToMap(MultiAction.class, code++);  
  101.     addToMap(MultiResponse.class, code++);  
  102.   
  103.     // coprocessor execution  
  104.     addToMap(Exec.class, code++);  
  105.     addToMap(Increment.class, code++);  
  106.   
  107.     addToMap(KeyOnlyFilter.class, code++);  
  108.   
  109.     // serializable  
  110.     addToMap(Serializable.class, code++);  
  111.   
  112.     addToMap(RandomRowFilter.class, code++);  
  113.   
  114.     addToMap(CompareOp.class, code++);  
  115.   
  116.     addToMap(ColumnRangeFilter.class, code++);  
  117.   
  118.     addToMap(HServerLoad.class, code++);  
  119.   
  120.     addToMap(RegionOpeningState.class, code++);  
  121.   
  122.     addToMap(HTableDescriptor[].class, code++);  
  123.   
  124.     addToMap(Append.class, code++);  
  125.   
  126.     addToMap(RowMutations.class, code++);  
  127.   
  128.     addToMap(Message.class, code++);  
  129.   
  130.     //java.lang.reflect.Array is a placeholder for arrays not defined above  
  131.     GENERIC_ARRAY_CODE = code++;  
  132.     addToMap(Array.class, GENERIC_ARRAY_CODE);  
  133.   
  134.     // make sure that this is the last statement in this static block  
  135.     NEXT_CLASS_CODE = code;  
  136.   }  

那么上面代码中涉及的类,默认就能够在coprocessor中传递了,这也是我们在使用coprocessor传递普通类型对象时无需干预的原因。但是一旦需要传递自定义的对象,就需要了解coprocessor的对象传递机制。HbaseObjectWritable对每类对象都进行了编码,code。所以如果自定义对象需要在coprocessor中传递,需要能够属于HbaseObjectWritable已编码类型的对象,或者修改HbaseObjectWritable。这里推荐采用前一种,只需要在自定义的类中implements Serializable接口即可。


      3、hbase常用运维命令      

一,基本命令:

    建表:create 'testtable','coulmn1','coulmn2'

     也可以建表时加coulmn的属性如:create 'testtable',{NAME => 'coulmn1', BLOOMFILTER => 'NONE', REPLICATION_SCOPE => '0', VERSIONS => '10', COMPRESSION => 'LZO', TTL => '30000', IN_MEMORY => 'false', BLOCKCACHE => 'false'}, {NAME => 'coulmn', BLOOMFILTER => 'NONE', REPLICATION_SCOPE => '0', VERSIONS => '30', COMPRESSION => 'LZO', TTL => '30000', IN_MEMORY => 'true'}  (其中的属性有versions:设置历史版本数,TTL:过期时间,COMPRESSION:压缩方式,当配置lzo的情况)

    删除表:drop 'testtable'   (删除表之前先要禁用表,命令disable 'testtable')

    启用和禁用表: enable 'testtable' 和disable 'testtable'

    其它的基本命令:describe 'testtable'(查看表结构),alert 修改表结构,list 列出所有表。

二,日常维护的命令

    1,major_compact 'testtable',通常生产环境会关闭自动major_compact(配置文件中hbase.hregion.majorcompaction设 为0),选择一个晚上用户少的时间窗口手工major_compact,如果hbase更新不是太频繁,可以一个星期对所有表做一次 major_compact,这个可以在做完一次major_compact后,观看所有的storefile数量,如果storefile数量增加到 major_compact后的storefile的近二倍时,可以对所有表做一次major_compact,时间比较长,操作尽量避免高锋期。

    2,flush 'testtable',将所有memstore刷新到hdfs,通常如果发现regionserver的内存使用过大,造成该机的 regionserver很多线程block,可以执行一下flush操作,这个操作会造成hbase的storefile数量剧增,应尽量避免这个操 作,还有一种情况,在hbase进行迁移的时候,如果选择拷贝文件方式,可以先停写入,然后flush所有表,拷贝文件。

    3,balance_switch true或者balance_switch flase,配置master是否执行平衡各个regionserver的region数量,当我们需要维护或者重启一个regionserver时,会 关闭balancer,这样就使得region在regionserver上的分布不均,这个时候需要手工的开启balance。

三,重启一个regionserver

    bin/graceful_stop.sh --restart --reload --debug nodename

    这个操作是平滑的重启regionserver进程,对服务不会有影响,他会先将需要重启的regionserver上面的所有 region迁移到其它的服务器,然后重启,最后又会将之前的region迁移回来,但我们修改一个配置时,可以用这种方式重启每一台机子,这个命令会关 闭balancer,所以最后我们要在hbase shell里面执行一下balance_switch true,对于hbase regionserver重启,不要直接kill进程,这样会造成在zookeeper.session.timeout这个时间长的中断,也不要通过 bin/hbase-daemon.sh stop regionserver去重启,如果运气不太好,-ROOT-或者.META.表在上面的话,所有的请求会全部失败。

四,关闭下线一台regionserver

    bin/graceful_stop.sh  nodename

    和上面一样,系统会在关闭之前迁移所有region,然后stop进程,同样最后我们要手工balance_switch true,开启master的region均衡。

五,检查region是否正常以及修复

    bin/hbase hbck  (检查)

    bin/hbase hbck -fix  (修复)

    会返回所有的region是否正常挂载,如没有正常挂载可以使用下一条命令修复,如果还是不能修复,那需要看日志为什么失败,手工处理。

六,hbase的迁移

    1,copytable方式

    bin/hbase org.apache.hadoop.hbase.mapreduce.CopyTable --peer.adr=zookeeper1,zookeeper2,zookeeper3:/hbase 'testtable'

    目前0.92之前的版本的不支持多版本的复制,0.94已经支持多个版本的复制。当然这个操作需要添加hbase目录里的conf/mapred-site.xml,可以复制hadoop的过来。

    2,Export/Import

    bin/hbase org.apache.hadoop.hbase.mapreduce.Export testtable /user/testtable [versions] [starttime] [stoptime]

    bin/hbase org.apache.hadoop.hbase.mapreduce.Import testtable  /user/testtable

    跨版本的迁移,我觉得是一个不错的选择,而且copytable不支持多版本,而export支持多版本,比copytable更实用一些。

    3,直接拷贝hdfs对应的文件

    首先拷贝hdfs文件,如bin/hadoop distcp hdfs://srcnamenode:9000/hbase/testtable/ hdfs://distnamenode:9000/hbase/testtable/

    然后在目的hbase上执行bin/hbase org.jruby.Main bin/add_table.rb /hbase/testtable

    生成meta信息后,重启hbase

    这个操作是简单的方式,操作之前可以关闭hbase的写入,执行flush所有表(上面有介绍),再distcp拷贝,如果hadoop版本不一致,可以用hftp接口的方式,我推荐使用这种方式,成本低。

    先总结这么多,有空我再详细写一下region坏时怎么修复。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值