HBase 协处理器个别简单案例

协处理器,我个人的理解就是相当于数据库的触发器一样,可以在改变(增删改)数据的前后,做一些紧跟的动作

直接举例子

1.

//重写prePut方法,监听到向table1表插入数据时,执行向table2表插入数据的代码
public class MyProcessor extends BaseRegionObserver {
    @Override
    public void prePut(ObserverContext<RegionCoprocessorEnvironment> e, Put put, WALEdit edit, Durability durability) throws IOException {
       //把自己需要执行的逻辑定义在此处,向table2表插入数据,数据具体是什么内容与Put一样
        //获取table2表table对象
        final HTableInterface table2 =  e.getEnvironment().getTable(TableName.valueOf("table2"));
        //解析table1表的插入对象put,列族是family,对应列是column1
        final Cell cell = put.get(Bytes.toBytes("family"), Bytes.toBytes("column1")).get(0);
        //table对象.put
        final Put put1 = new Put(put.getRow());
        put1.add(cell);
        table2.put(put1); //执行向table2表插入数据
        table2.close();
    }
}

这是一个在put前执行其他方法的例子,案例的作用是监听到向table1表插入数据时,执行向table2表插入数据的代码

2.这是另一个例子,就是有一个关系表relative,a有b的好友,同样b有a的好友,需要a删除b的好友的同时,b好友中的a也应该删除 

 //删除好友关系表,a删除b的同时,b要删除a  
    @Override
    public void preDelete(ObserverContext<RegionCoprocessorEnvironment> e, Delete delete, WALEdit edit, Durability durability) throws IOException {
        //把自己需要执行的逻辑定义在此处,向t2表插入数据,数据具体是什么内容与Put一样
        //获取relative表table对象
        final HTableInterface relative =  e.getEnvironment().getTable(TableName.valueOf("relative"));

        List<Delete> deletes=new ArrayList<>();
        //取得被删除人的keyid
        List<Cell> cells = delete.getFamilyCellMap().get(Bytes.toBytes("friends"));
        for (Cell cell : cells) {
            Delete appendDelete = new Delete(CellUtil.cloneRow(cell));
            appendDelete.addColumn(CellUtil.cloneFamily(cell), CellUtil.cloneRow(cell));
            deletes.add(appendDelete);
        }
        //执行批量删除
        relative.delete(deletes);
        //关闭table对象
        relative.close();
    }

上面的代码思路是a删除b之前,写了一个协处理器,删除前处理事件,a删除b之前,先删除b中a的记录。

但是,上面的代码会造成死循环。协处理器对每一次删除都要触发。a要删除b,触发,需要b先删除a,触发,又需要a先删除b,死循环,hbase直接卡死。

后来,查看源码,确实应该有一个方法是delete之后触发的,postDelete,就报上面的方法名换了一下

 //删除好友关系表,a删除b的同时,b要删除a  
    @Override
    public void postDelete(ObserverContext<RegionCoprocessorEnvironment> e, Delete delete, WALEdit edit, Durability durability) throws IOException {
        //把自己需要执行的逻辑定义在此处,向t2表插入数据,数据具体是什么内容与Put一样
        //获取relative表table对象
        final HTableInterface relative =  e.getEnvironment().getTable(TableName.valueOf("relative"));

        List<Delete> deletes=new ArrayList<>();
        //取得被删除人的keyid
        List<Cell> cells = delete.getFamilyCellMap().get(Bytes.toBytes("friends"));
        for (Cell cell : cells) {
            Delete appendDelete = new Delete(CellUtil.cloneRow(cell));
            appendDelete.addColumn(CellUtil.cloneFamily(cell), CellUtil.cloneRow(cell));
            deletes.add(appendDelete);
        }
        //执行批量删除
        relative.delete(deletes);
        //关闭table对象
        relative.close();
    }

当然,这还是不行,最好在删除前判断一下,是否有这条记录,如下

 @Override
    public void postDelete(ObserverContext<RegionCoprocessorEnvironment> e, Delete delete, WALEdit edit, Durability durability) throws IOException {
        //获取relative表table对象
        final HTableInterface relative =  e.getEnvironment().getTable(TableName.valueOf("relative"));

        List deletes=new ArrayList<Delete>();
        Scan scan = new Scan();
        //取得被删除的所有cell
        List<Cell> cells = delete.getFamilyCellMap().get(Bytes.toBytes("friends"));
        for (Cell cell : cells) {
            //取得被删除的列
            byte[] deletedColumn = CellUtil.cloneQualifier(cell);
            //取得当前的人
            byte[] thisColumn = CellUtil.cloneRow(cell);
            //查询被删除者的名单中是否有当前人
            scan.setStartRow(deletedColumn);
            ResultScanner resultScanner = relative.getScanner(scan);
            Result next = resultScanner.next();
            //有的话,被删除者也删除当前人
            if(next!=null&&!next.isEmpty()){
                Cell[] cells2 = next.rawCells();
                for (Cell cell2 : cells2) {
                   if(new String(thisColumn).equals(new String(CellUtil.cloneQualifier(cell2)))){
                       Delete appendDelete = new Delete(deletedColumn);
                       appendDelete.addColumn(CellUtil.cloneFamily(cell2), thisColumn);
                       deletes.add(appendDelete);
                   }
                }
            }

        }
        //执行批量删除
        relative.delete(deletes);
        //关闭table对象
        relative.close();
    }

这样就可以了,实现删除relative中好友关系,a删除b,b也会自动删除a的好友记录。

 

记住,你得上传jar包到hadoop挂载到habase中relative表

代码打包成jar包   postdelete.jar

上传到hadoop

hdfs dfs -mkdir -p /processor
hdfs dfs -put processor.jar /processor

在hbase中执行

alter 'relative',METHOD => 'table_att','Coprocessor'=>'hdfs://linux121:9000/processor/postdelete.jar|com.test.hbase.processor.PostDelete|1001|' 

         表名                           列属性名,可自定义                                    hadoop中jar包对应得位置信息    对应类的路径名包名+类名                 优先级,多个触发器,优先级大的先触发

 

posted @ 2020-09-08 10:45  若冲  阅读(416)  评论(0编辑  收藏  举报