协处理器使用介绍:
在本项目中,如果向HBASE中插入一条主叫的通话日志,比如张三在2018年3月份跟李四通话了50秒,那么李四在2018年3月份同样也跟张三通话了50秒,在HBASE中同样也应该保存一条李四的通话记录,这里张三是主叫,李四是被叫。我们可以在consumer中插入主叫用户信息后紧接着再插入一条被叫用户的信息,但是这样插入的效率就会降低。所以我们这里使用到了协处理器。协处理器工作在hbase中,当consumer向HBASE中插入一条主叫数据后,自动由协处理器向HBASE中插入一条被叫数据。
思路:
- 编写协处理器类,用于协助处理 HBase 的相关操作(增删改查)
- 在协处理器中,一条主叫日志成功插入后,将该日志切换为被叫视角再次插入一次,放入到与主叫日志不同的列族中。
- 重新创建 hbase 表,并设置为该表设置协处理器。
- 编译项目,发布协处理器的 jar 包到 hbase 的 lib 目录下,并群发该 jar 包
- 修改 hbase-site.xml 文件,设置协处理器,并群发该 hbase-site.xml 文件。
注意:修改了hbase-site.xml文件后,默认对HBASE中全部的表都使用协处理器。可以不用配置,那么就只对该表有效。
协处理器使用步骤:
1.创建类
2.让表知道协处理类(和表有关联),在建表的时候进行
3.将项目打成的jar包发布到hbase中(关联的jar包也需要发布),并且需要分发到集群中
本项目中的协处理器代码:
package com.wp.ct.consumer.coprocessor;
import com.wp.ct.common.bean.BaseDao;
import com.wp.ct.common.constant.Names;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Durability;
import org.apache.hadoop.hbase.client.HTableInterface;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Table;
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.wal.WALEdit;
import org.apache.hadoop.hbase.util.Bytes;
import org.junit.Test;
import java.io.IOException;
public class InsertCalleeCoprocessor extends BaseRegionObserver {
@Override
public void postPut(ObserverContext<RegionCoprocessorEnvironment> e, Put put,
WALEdit edit, Durability durability) throws IOException {
//从hbase中获取表
Table table = e.getEnvironment().getTable(TableName.valueOf(Names.TABLE.getValue()));//获取hbase环境和表
//主叫用户的rowkey。通过主叫用户的put得到
String rowkey = Bytes.toString(put.getRow());
//主叫用户的rowkey格式:1_133_201805_144_0102_1
String[] values = rowkey.split("_");
CoprocessorDao dao = new CoprocessorDao();
String call1 = values[1];
String call2 = values[3];
String calltime = values[2];
String duration = values[4];
String flg = values[5];
//只有主叫用户保存后才需要出发被叫用户的保存,被叫用户put后,不再执行下面代码
if("1".equals(flg)){
//生成被叫用户的rowkey
String calleeRowkey = dao.getRegionNum(call2,calltime) + "_" + call2 + "_" + calltime +
"_" + call1 + "_" + duration + "_0" ;
//保存数据
Put calleePut = new Put(Bytes.toBytes(calleeRowkey));
byte[] calleeFamily = Bytes.toBytes(Names.CF_CALLEE.getValue());
calleePut.addColumn(calleeFamily,Bytes.toBytes("call1"),Bytes.toBytes(call2));
calleePut.addColumn(calleeFamily,Bytes.toBytes("call2"),Bytes.toBytes(call1));
calleePut.addColumn(calleeFamily,Bytes.toBytes("calltime"),Bytes.toBytes(calltime));
calleePut.addColumn(calleeFamily,Bytes.toBytes("duration"),Bytes.toBytes(duration));
calleePut.addColumn(calleeFamily,Bytes.toBytes("flg"),Bytes.toBytes("0"));
table.put(calleePut);
//关闭表
table.close();
}
}
/**
* 使用内部类来调用抽象类中的方法来生成分区号
*/
private class CoprocessorDao extends BaseDao{
public int getRegionNum(String tel,String time){
return genRegionNum(tel,time);
}
}
}