Hbase0.98.4中部署用户自定义的Observer Coprocessor

Hbase自0.92之后开始支持Coprocessor(协处理器),旨在使用户可以将自己的代码放在regionserver上来运行,即将计算程序移动到数据所在的位置进行运算。这一点与MapReduce的思想一致。Hbase的Coprocess分为observer和endpoint两大类。简单说,observer相当于关系型数据库中的触发器,而endpoint则相当于关系型数据库中的存储过程。关于HBase Coprocessor的介绍网上有很多的文档,由于我也是刚刚学习,从很多好人贡献的文档上了解了很多。

这里记录一下自己在一个完全分布式系统上部署自定义的Coprocessor的过程,本文会介绍两种部署的方法:一种是在hbase-site.xml中配置;第二种是使用表描述符来配置(alter);前者会被所有的表的所有的region加载,而后者只会对指定的表的所有region加载。本文会结合自己的实验过程指出哪些地方为易错点。

首先,还是先来看下环境:

hadoop1.updb.com    192.168.0.101    Role:master

hadoop2.updb.com    192.168.0.102    Role:regionserver

hadoop3.updb.com    192.168.0.103    Role:regionserver

hadoop4.updb.com    192.168.0.104    Role:regionserver

hadoop5.updb.com    192.168.0.105    Role:regionserver

首先编码自定义的Coprocessor,该段代码摘自《Hbase权威指南》,只是修改了package的名字:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/**

* coprocessor

* 当用户在使用get命令从表中取特定的row时,就会触发这个自定义的observer coprocessor

* 触发条件是用户使用get指定的rowkey与程序中指定的FIXED_ROW一致为@@@GETTIME@@@时

* 触发后的操作是程序会在服务端生成一个keyvalue实例,并将这个实例返回给客户端。这个kv实例是以

* @@@GETTIME@@@为rowkey,列族和列标识符均为@@@GETTIME@@@,列值为服务器端的时间

*/

package org.apache.hbase.kora.coprocessor;  import java.io.IOException;  import java.util.List;  import org.apache.commons.logging.Log;  import org.apache.commons.logging.LogFactory;  import org.apache.hadoop.hbase.KeyValue;  import org.apache.hadoop.hbase.client.Get;  import org.apache.hadoop.hbase.coprocessor.BaseRegionObserver;  import org.apache.hadoop.hbase.coprocessor.ObserverContext;  import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;  import org.apache.hadoop.hbase.regionserver.HRegion;  import org.apache.hadoop.hbase.util.Bytes;

public class RegionObserverExample extendsBaseRegionObserver {

public static final Log LOG = LogFactory.getLog(HRegion.class );

public static final byte[] FIXED_ROW = Bytes.toBytes("@@@GETTIME@@@" );

@Override

public void preGet(ObserverContext<RegionCoprocessorEnvironment> c,

Get get, List<KeyValue> result) throws IOException {

LOG.debug( "Got preGet for row: " + Bytes.toStringBinary(get.getRow()));

if (Bytes.equals(get.getRow(), FIXED_ROW)) {

KeyValue kv = new KeyValue(get.getRow(), FIXED_ROW, FIXED_ROW,

Bytes.toBytes(System.currentTimeMillis()));

LOG.debug( "Had a match, adding fake kv: " + kv);

result.add(kv);

}

}

}

编码完成后需要将该类编译并打成jar包,类名上右击--Export,弹出如下窗口

wKiom1RuwbOxV68dAAf7rJQRL_k329.jpg

选择JAR file,然后Next,出现如下窗口

wKioL1Ruwi2iESOaAAJnt1YRiMA058.jpg

指定jar文件的保存路径,然后finish,就完成了RegionObserverExample类的编译和打包,接下来就需要将打好的jar文件使用ftp的方式上传到hbase集群的master服务器上,这里为hadoop1。

1
2
3
4
5
6
7
8
9
## 已经上传到hadoop1上

[grid@hadoop1 ~]$ ls / var/ftp/pub/RegionObserverExample.jar

/ var /ftp/pub/RegionObserverExample.jar

## 由于是完全分布式系统,为了方便管理,我们将jar包存放到hadoop hdfs的根目录下的jars目录下

[grid@hadoop1 ~]$ hdfs dfs -put / var/ftp/pub/RegionObserverExample.jar /jars

## OK,验证已经上传成功  [grid@hadoop1 ~]$ hdfs dfs -ls /jars Found 1 items  -rw-r--r-- 4 grid supergroup 3884 2014-11-15 04:46 /jars/RegionObserverExample.jar

然后需要修改hbase的hbase-env.sh、hbase-site.xml两个配置文件

1
2
3
4
5
6
7
8
9
## 首先修改hbase-env.sh中的这行,将存放Coprocessor jar文件的目录添加到Hbase的classpath中

export HBASE_CLASSPATH=hdfs: //hadoop1:8020/jars

## 然后修改hbase-site.xml文件,添加一个选项

<!-- 这里要注意value中一定要写完整的类名(即把包名写全),否则报ClassNotFound错 -->

<property>

<name>hbase.coprocessor.region.classes</name>

<value>org.apache.hbase.kora.coprocessor.RegionObserverExample</value>

</property>

在master上修改配置文件完成之后,将修改后的文件scp到其他个regionserver上,然后重启hbase使配置生效。重启之后来看是否能够正确的触发

1
2
3
4
5
6
7
8
9
10
## 使用get命令从kora表中取rowkey为@@@GETTIME@@@的行

hbase(main):014:0> get 'kora' '@@@GETTIME@@@'

COLUMN CELL

@@@GETTIME@@@:@@@GETTIM timestamp=9223372036854775807, value=\x00\x00\x01I\xB0@\xA0\xE0

E@@@

1 row(s) in 0.0420 seconds  ## 将列值转化为uninx 时间

hbase(main):015:0> Time.at(Bytes.toLong("\x00\x00\x01I\xB0\x0BZ\x0B" .to_java_bytes)/ 1000)

=> Sat Nov 15 04:42:54 +0800 2014  ## 从上面的测试中看出,我们自定义的Coprocessor已经成功的部署到分布式系统中了。

需要留意的是在hbase-site.xml配置的Coprocessor默认是会被每张表的每个region加载。如果只想要某个表使用这个observer coprocessor,就需要使用表描述符的加载方式,这种方式同样的需要修改hbase-env.sh将jar包路径添加到hbase的classpath中去,与上面不同的是不用在hbase-site.xml中设置Coprocessor,如下

1
2
3
4
5
6
7
8
9
10
11
12
13
## 看hbase-env.sh的配置

[grid@hadoop1 ~]$ grep "jars" /opt/hbase-0.98.4-hadoop2/conf/hbase-env.sh

export HBASE_CLASSPATH=hdfs: //hadoop1:8020/jars

## 注释掉hbase-site.xml中的Coprocessor的配置  [grid@hadoop1 ~]$ tail -7 /opt/hbase-0.98.4-hadoop2/conf/hbase-site.xml  <!--

<property>

<name>hbase.coprocessor.region.classes</name>

<value>org.apache.hbase.kora.coprocessor.RegionObserverExample</value>

</property>

-->

</configuration>

在hbase shell中使用alter命令来为kora表来设定Coprocessor

1
2
3
4
5
6
7
8
9
10
11

## 格式:[coprocessor jar file location] | class name | [priority] | [arguments]

## 列子:hbase> alter 't1' ,

## 'coprocessor' =>'hdfs:///foo.jar|com.foo.FooRegionObserver|1001|arg1=1,arg2=2'

## 由于一定设置了classpath,所以可以忽略jar file location,如下:

hbase(main):101:0> alter 'kora' ,

hbase(main):102:0* 'coprocessor' =>'|org.apache.hbase.kora.coprocessor.RegionObserverExample|'

Updating all regions with the new schema...

0/1 regions updated.  1/1 regions updated.  Done.  0 row(s) in 2.5670 seconds

设置成功,decribe下表

1
2
3
4
5
6
7

hbase(main):103:0> describe 'kora'

DESCRIPTION ENABLED

'kora' , {TABLE_ATTRIBUTES => {coprocessor $1 => '|org.apache.hbase.kora.coprocessor.RegionObserverExa true

mple| '}, {NAME => ' project ', DATA_BLOCK_ENCODING => 'NONE ', BLOOMFILTER => ' ROW', REPLICATION_SCOPE

=> '0' , VERSIONS => '1' , COMPRESSION => 'NONE' , MIN_VERSIONS => '0' , TTL => 'FOREVER' , KEEP_DELETED_

CELLS => 'false' , BLOCKSIZE => '65536' , IN_MEMORY =>'false' , BLOCKCACHE => 'true' }

1 row(s) in 0.0580 seconds

ok,已经设置成功,下面来测试一下

1
2
3
4
5
6
7
8
9
## kora表,指定了Coprocessor

hbase(main):104:0> get 'kora' '@@@GETTIME@@@'

COLUMN CELL

@@@GETTIME@@@:@@@GETTIME@@@ timestamp=9223372036854775807, value=\x00\x00\x01I\xB0\x985W

1 row(s) in 0.0360 seconds  ## testtable,没有指定Coprocessor

hbase(main):105:0> get 'testtable' '@@@GETTIME@@@'

COLUMN CELL  0 row(s) in 0.0180 seconds

需要注意的是,Coprocessor的优先级有SYSTEM和USER两种,SYSTEM优先于USER加载。使用表描述符设置Coprocessor时,不要设置优先级这一项,否则无法成功触发,如

1

'coprocessor' =>'|org.apache.hbase.kora.coprocessor.RegionObserverExample|USER|'

虽然也能成功设置Coprocessor,但是测试时是无法触发的,在上述环境中亲自测试过的,而且hbase帮助文档中优先级这个项用户不是必输项,只有类名是必输项。我们可以根据自己的需求来选择使用哪种方式来配置自己的Coprocessor。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
TableMapReduceUtil是HBase API的一个工具类,用于简化MapReduce程序与HBase表之间的交互。要自定义TableMapReduceUtil,可以按照以下步骤操作: 1.创建一个新的MapReduce程序,并添加需要的依赖库,包括Hadoop和HBase的相关库。 2.在程序创建一个TableMapReduceUtil对象,并配置HBase表的相关信息。 3.自定义Mapper和Reducer的实现,以处理HBase的数据。 4.将Mapper和Reducer实现类注入到TableMapReduceUtil对象,以便TableMapReduceUtil对象能够调用Mapper和Reducer实现类。 5.配置MapReduce作业的其他参数,如输入路径、输出路径、作业名称等。 6.运行MapReduce作业,等待其完成。 下面是一个简单的示例程序,演示如何自定义TableMapReduceUtil: ```java import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.client.Scan; import org.apache.hadoop.hbase.mapreduce.TableMapReduceUtil; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Job; import org.apache.hadoop.mapreduce.Mapper; import org.apache.hadoop.mapreduce.Reducer; import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; import java.io.IOException; public class CustomTableMapReduceUtil { public static void main(String[] args) throws Exception { Configuration conf = new Configuration(); Job job = Job.getInstance(conf, "Custom TableMapReduceUtil"); job.setJarByClass(CustomTableMapReduceUtil.class); Scan scan = new Scan(); scan.setCaching(500); scan.setCacheBlocks(false); TableMapReduceUtil.initTableMapperJob( Bytes.toBytes("mytable"), scan, MyMapper.class, Text.class, IntWritable.class, job); job.setReducerClass(MyReducer.class); job.setOutputKeyClass(Text.class); job.setOutputValueClass(IntWritable.class); FileOutputFormat.setOutputPath(job, new Path(args[0])); System.exit(job.waitForCompletion(true) ? 0 : 1); } public static class MyMapper extends Mapper<ImmutableBytesWritable, Result, Text, IntWritable> { @Override protected void map(ImmutableBytesWritable key, Result value, Context context) throws IOException, InterruptedException { // TODO: implement mapper logic here } } public static class MyReducer extends Reducer<Text, IntWritable, Text, IntWritable> { @Override protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException { // TODO: implement reducer logic here } } } ``` 在这个示例程序,我们创建了一个名为“Custom TableMapReduceUtil”的MapReduce作业,它从名为“mytable”的HBase读取数据,并在Mapper和Reducer定义处理逻辑。我们通过调用TableMapReduceUtil.initTableMapperJob()方法来配置输入数据的来源和Mapper实现类,然后将Reducer实现类设置为作业的Reducer,并指定输出键和值的类型。最后,我们将输出路径设置为命令行参数的第一个参数,并执行MapReduce作业。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值