【HBase协处理器】

一、协处理器简介

1. 起源

        Hbase 作为列族数据库最经常被人诟病的特性包括:无法轻易建立“二级索引”,难以执 行求和、计数、排序等操作。比如,在旧版本的(<0.92)Hbase 中,统计数据表的总行数,需 要使用 Counter 方法,执行一次 MapReduce Job 才能得到。虽然 HBase 在数据存储层中集成 了 MapReduce,能够有效用于数据表的分布式计算。然而在很多情况下,做一些简单的相 加或者聚合计算的时候,如果直接将计算过程放置在 server 端,能够减少通讯开销,从而获 得很好的性能提升于是,HBase 在 0.92 之后引入了协处理器(coprocessors),实现一些激动 人心的新特性:能够轻易建立二次索引、复杂过滤器(谓词下推)以及访问控制等。

2、介绍

协处理器有两种:observer 和 endpoint

Observer 类似于传统数据库中的触发器,当发生某些事件的时候这类协处理器会被 Server 端调用。Observer Coprocessor 就是一些散布在 HBase Server 端代码中的 hook 钩子, 在固定的事件发生时被调用。比如:put 操作之前有钩子函数 prePut,该函数在 put 操作执 行前会被 Region Server 调用;在 put 操作之后则有 postPut 钩子函数

以 HBase0.92 版本为例,它提供了三种观察者接口:

  • RegionObserver:提供客户端的数据操纵事件钩子:Get、Put、Delete、Scan 等。
  • WALObserver:提供 WAL 相关操作钩子。
  • MasterObserver:提供 DDL-类型的操作钩子。如创建、删除、修改数据表等。

到 0.96 版本又新增一个 RegionServerObserver

Endpoint 协处理器类似传统数据库中的存储过程,客户端可以调用这些 Endpoint 协处 理器执行一段 Server 端代码,并将 Server 端代码的结果返回给客户端进一步处理,最常见 的用法就是进行聚集操作。如果没有协处理器,当用户需要找出一张表中的最大数据,即 max 聚合操作,就必须进行全表扫描,在客户端代码内遍历扫描结果,并执行求最大值的 操作。这样的方法无法利用底层集群的并发能力,而将所有计算都集中到 Client 端统一执行, 势必效率低下。利用 Coprocessor,用户可以将求最大值的代码部署到 HBase Server 端,HBase 将利用底层 cluster 的多个节点并发执行求最大值的操作。即在每个 Region 范围内执行求最 大值的代码,将每个 Region 的最大值在 Region Server 端计算出,仅仅将该 max 值返回给客 户端。在客户端进一步将多个 Region 的最大值进一步处理而找到其中的最大值。这样整体 的执行效率就会提高很多

3、总结

  • Observer 允许集群在正常的客户端操作过程中可以有不同的行为表现
  • Endpoint 允许扩展集群的能力,对客户端应用开放新的运算命令
  • Observer 类似于 RDBMS 中的触发器,主要在服务端工作
  • Endpoint 类似于 RDBMS 中的存储过程,主要在服务端工作
  • Observer 可以实现权限管理、优先级设置、监控、ddl 控制、二级索引等功能
  • Endpoint 可以实现 min、max、avg、sum、distinct、group by 等功能

二、协处理加载方式

  协处理器的加载方式有两种,我们称之为静态加载方式(Static Load)和动态加载方式 (Dynamic Load)。静态加载的协处理器称之为 System Coprocessor,动态加载的协处理器称 之为 Table Coprocessor。

1、 静态加载

通过修改 hbase-site.xml 这个文件来实现,启动全局 aggregation,能过操纵所有的表上 的数据。只需要添加如下代码:

<property>
<name>hbase.coprocessor.user.region.classes</name>
<value>org.apache.hadoop.hbase.coprocessor.AggregateImplementation</value>
</property>

为所有 table 加载了一个 cp class,可以用”,”分割加载多个 class

2、 动态加载

启用表 aggregation,只对特定的表生效。通过 HBase Shell 来实现。

(1)停用表  disable 'guanzhu'

(2)添加协处理器  alter 'guanzhu', METHOD => 'table_att', 'coprocessor' => 'hdfs://myha01/hbase/guanzhu.jar|com.study.hbase.cp.HbaseCoprocessorTest|1001|'

(3)启用表  enable 'guanzhu'

3、 协处理器卸载

同样是3步

disable 'mytable'
alter 'mytable',METHOD=>'table_att_unset',NAME=>'coprocessor$1'
enable 'mytable'

三、案例

1. IDEA创建maven项目,一定不要用spring initializr快速创建项目

public class HbaseCoprocessorTest extends BaseRegionObserver{

    static Configuration conf = HBaseConfiguration.create();
    static Connection conn = null;
    static Table table = null;
    
    static {
        conf.set("hbase.zookeeper.quorum", "hadoop1:2181,hadoop2:2181,hadoop3:2181");
        try {
            conn = ConnectionFactory.createConnection(conf);
            table = conn.getTable(TableName.valueOf("fans"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 
    /**
     * 此方法是在真正的put方法调用之前进行调用
     * 参数put为table.put(put)里面的参数put对象,是要进行插入的那条数据
     * 
     * 例如:要向关注表里面插入一条数据    姓名:二狗子    关注的明星:王宝强
     * shell语句:put 'guanzhu','ergouzi', 'cf:star', 'wangbaoqiang'
     *
     * */
    @Override
    public void prePut(ObserverContext<RegionCoprocessorEnvironment> e, Put put, WALEdit edit, Durability durability)
            throws IOException {
        //获取put对象里面的rowkey'ergouzi'
        byte[] row = put.getRow();
        //获取put对象里面的cell
        List<Cell> list = put.get("cf".getBytes(), "star".getBytes());
        Cell cell = list.get(0);
        
        //创建一个新的put对象
        Put new_put = new Put(row);
        new_put.addColumn("cf".getBytes(), "fensi".getBytes(), cell.getValueArray());
        table.put(new_put);
        conn.close();
       //注意这里面把conn关闭了,触发的内容就只能添加一次!
    }
}

【注意】我们可以通过下面的方式实现表名的获取

String currentTableName = e.getEnvironment().getRegionInfo().getRegionNameAsString();

 

2. pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>hbase3</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>


        <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-client</artifactId>
            <version>1.3.1</version>
        </dependency>

        <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-server</artifactId>
            <version>1.3.1</version>
        </dependency>
        
    </dependencies>

</project>

3. 打包

   把maven项目打包,上传到hdfs上 hadoop fs -put guanzhu.jar /hbase

4. 创建两张测试的数据表

#t提前创建两张数据表

create 'fans','cf'

create 'guanzhu','cf'

5. 测试

hbase(main):001:0> disable 'guanzhu'
row(s) in 2.8850 seconds

hbase(main):002:0> alter 'guanzhu', METHOD => 'table_att', 'coprocessor' => 'hdfs://myha01/hbase/guanzhu.jar|com.study.hbase.cp.HbaseCoprocessorTest|1001|'
Updating all regions with the new schema...
1/1 regions updated.
Done.
row(s) in 2.7570 seconds

hbase(main):003:0> enable 'guanzhu'
row(s) in 2.3400 seconds

hbase(main):004:0> desc 'guanzhu'
Table guanzhu is ENABLED                                                                                        
guanzhu, {TABLE_ATTRIBUTES => {coprocessor$1 => 'hdfs://myha01/hbase/guanzhu.jar|com.study.hbase.cp.HbaseCoproce
ssorTest|1001|'}                                                                                                
COLUMN FAMILIES DESCRIPTION                                                                                     
{NAME => 'cf', BLOOMFILTER => 'ROW', VERSIONS => '1', IN_MEMORY => 'false', KEEP_DELETED_CELLS => 'FALSE', DATA_
BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', COMPRESSION => 'NONE', MIN_VERSIONS => '0', BLOCKCACHE => 'true', BL
OCKSIZE => '65536', REPLICATION_SCOPE => '0'}                                                                   
row(s) in 0.0500 seconds

hbase(main):005:0> put 'guanzhu', 'ergouzi', 'cf:star', 'wangbaoqiang'
row(s) in 0.3050 seconds

hbase(main):006:0> scan 'guanzhu'
ROW                           COLUMN+CELL                                                                       
 ergouzi                      column=cf:star, timestamp=1522759023001, value=wangbaoqiang                       
row(s) in 0.0790 seconds

hbase(main):007:0> scan 'fans'
ROW                           COLUMN+CELL                                                                       
 \x00\x00\x00\x19\x00\x00\x00 column=cf:fensi, timestamp=1522759022996, value=ergouzi                           
 \x0C\x00\x07ergouzi\x02cfsta                                                                                   
 r\x7F\xFF\xFF\xFF\xFF\xFF\xF                                                                                   
 F\xFF\x04wangbaoqiang                                                                                          
row(s) in 0.0330 seconds

hbase(main):008:0>

转载:https://segmentfault.com/a/1190000018071516?utm_source=tag-newest

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值