读书笔记-HBase in Action-第二部分Advanced concepts-(2)Coprocessor

读书笔记-HBase in Action-第二部分Advanced concepts-(2)Coprocessor

大家好,又见面了,我是全栈君。

Coprocessor是HBase 0.92.0引入的特性。使用Coprocessor。能够将一些计算逻辑下推到HBase节点,HBase由一个单纯的存储系统升级为分布式数据处理平台。

Coprocessor分为两种:Observer和Endpoint。

Observer能改动扩展已有的client操作功能。而Endpoint能引入新的client操作。

Observer

Observer的作用类似于数据库的触发器或者AOP中的advice。下图为Put操作添加Observer,当中1-2-4-6是一次正常的Put操作RPC调用过程,而3和5属于Observer,能够在Put操作之前和之后添加自己定义处理逻辑。

读书笔记-HBase in Action-第二部分Advanced concepts-(2)Coprocessor

Observer包含三种,RegionObserver(针对数据訪问和更新操作,执行在Region上)/WALObserver(针对WAL日志事件,执行在RegionServer上下文)/MasterObserver(针对DDL操作,执行在Master节点)。

Endpoint

Endpoint的作用则类似于数据库存储过程。实现机制是通过扩展HBase RPC协议,给client暴露新的操作接口。

例如以下图,client负责发起调用和收集结果,服务端各节点负责并行计算。

读书笔记-HBase in Action-第二部分Advanced concepts-(2)Coprocessor

实战

以上一章的follows表为例,通过Observer实现followedBy被关注表数据一致性维护。Endpoint实现关注人数量统计。

由于要实如今插入follows表时自己主动插入followedBy表。须要用到关注人/被关注人username信息,所以首先升级schema。

读书笔记-HBase in Action-第二部分Advanced concepts-(2)Coprocessor

实现Observer

代码中有三处凝视值得注意:

  1. postPut方法在put操作之后被调用。
  2. 假设通过hbase-site.xml安装Observer。会应用到全局全部表,所以这里推断put操作的是否follows表。

  3. 这里有点bad smell。Observer执行在服务器端。为了共用代码,又调用client代码,仅为演示作用。

packageHBaseIA.TwitBase.coprocessors;//…publicclass FollowsObserver extends BaseRegionObserver {    private HTablePool pool = null;    @Override    public void start(CoprocessorEnvironment env)throws IOException {        pool = newHTablePool(env.getConfiguration(), Integer.MAX_VALUE);    }    @Override    public void stop(CoprocessorEnvironment env)throws IOException {        pool.close();    }    @Override    public void postPut(//1,在Put操作之后调用            finalObserverContext<RegionCoprocessorEnvironment> e,            final Put put,            final WALEdit edit,            final boolean writeToWAL) throws IOException {        byte[] table=e.getEnvironment().getRegion().getRegionInfo().getTableName();        if (!Bytes.equals(table,FOLLOWS_TABLE_NAME))             return;  //2,推断表名        KeyValue kv =put.get(RELATION_FAM, FROM).get(0);        String from =Bytes.toString(kv.getValue());        kv = put.get(RELATION_FAM,TO).get(0);        String to =Bytes.toString(kv.getValue());        RelationsDAO relations = newRelationsDAO(pool);        relations.addFollowedBy(to,from);//3,插入followedBy表    }}

Observer的安装能够通过改动hbase-site.xml或者使用tableschema改动语句完毕,前者须要重新启动HBase服务,后者仅仅须要又一次上下线相应表。

$ hbase shellHBaseShell; enter 'help<RETURN>' for list of supported commands.Type"exit<RETURN>" to leave the HBase ShellVersion0.92.0, r1231986, Mon Jan 16 13:16:35 UTC 2012hbase(main):001:0>disable 'follows'0 row(s) in 7.0560 secondshbase(main):002:0>alter 'follows', METHOD => 'table_att','coprocessor'=>'file:///Users/ndimiduk/repos/hbaseiatwitbase/target/twitbase-1.0.0.jar|HBaseIA.TwitBase.coprocessors.FollowsObserver|1001|'Updatingall regions with the new schema...1/1regions updated.Done.0 row(s) in 1.0770 secondshbase(main):003:0>enable 'follows'0 row(s) in 2.0760 seconds

当中1001为优先级。当载入多个Observer时。依照优先级次序执行。

实现Endpoint

关注人数量统计能够通过clientScan实现,相比Endpoint方案。有两个待改进点:

  1. 传输全部关注人到client,不必要的网络I/O。

  2. 拿到全部关注人Result结果后。遍历实现计数是单线程的。

实现Endpoint包含三部分

定义PRC接口

publicinterface RelationCountProtocol extends CoprocessorProtocol {    public long followedByCount(String userId) throwsIOException;}

服务端实现

和client不同,InternalScanner执行在特定Region上。返回的是原始的KeyValue对象。

packageHBaseIA.TwitBase.coprocessors;//…publicclass RelationCountImpl extends BaseEndpointCoprocessor implementsRelationCountProtocol {    @Override    public longfollowedByCount(String userId) throws IOException {        byte[]startkey = Md5Utils.md5sum(userId);        Scan scan = newScan(startkey);        scan.setFilter(newPrefixFilter(startkey));        scan.addColumn(RELATION_FAM,FROM);        scan.setMaxVersions(1);        RegionCoprocessorEnvironmentenv= (RegionCoprocessorEnvironment)getEnvironment();        InternalScanner scanner =env.getRegion().getScanner(scan);//1,server端        long sum = 0;        List<KeyValue> results= new ArrayList<KeyValue>();        boolean hasMore = false;        do {            hasMore =scanner.next(results);            sum += results.size();            results.clear();        } while (hasMore);        scanner.close();        return sum;    }}

client代码

參考凝视:

  1. 定义Call实例 
  2. 调用服务端Endpoint。
  3. 聚合全部RegionServer得到的结果

public long followedByCount (final String userId) throws Throwable {    HTableInterface followed =pool.getTable(FOLLOWED_TABLE_NAME);    final byte[] startKey = Md5Utils.md5sum(userId);    final byte[] endKey =Arrays.copyOf(startKey, startKey.length);    endKey[endKey.length-1]++;    Batch.Call<RelationCountProtocol,Long> callable =        newBatch.Call<RelationCountProtocol, Long>() {        @Override        public Longcall(RelationCountProtocol instance) throws IOException {            returninstance.followedByCount(userId);        }    };//1 call instance    Map<byte[], Long>results = followed.coprocessorExec(                                   RelationCountProtocol.class,                                   startKey,                                   endKey,                                   callable);//2 invoke endpoint    long sum = 0;    for(Map.Entry<byte[],Long> e : results.entrySet()) {        sum +=e.getValue().longValue();    }//3 aggreagte results    return sum;}

Endpoint仅仅能通过配置文件部署,还须要将相关jar包增加到HBase classpath。

<property>    <name>hbase.coprocessor.region.classes</name>    <value>HBaseIA.TwitBase.coprocessors.RelationCountImpl</value></property>

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/115767.html原文链接:https://javaforall.net

(0)
上一篇 2022年1月30日 下午8:00
下一篇 2022年1月30日 下午9:00


相关推荐

  • 歌词服务器文件名,lrc是什么格式,MP3的LRC格式歌词同步方法

    歌词服务器文件名,lrc是什么格式,MP3的LRC格式歌词同步方法lrc 是什么格式 MP3 的 LRC 格式歌词同步方法发布时间 2012 03 2217 22 09 作者 佚名我要评论 lrc 是英文 lyric 歌词 的缩写 被用做歌词文件的扩展名 以 lrc 为扩展名的歌词文件可以在各类数码播放器中同步显示 什么是 lrc 格式 lrc 是英文 lyric 歌词 的缩写 被用做歌词文件的扩展名 以 lrc 为扩展名的歌词文件可以在各类数码播放器中同步显示 大部分

    2026年3月18日
    2
  • Android之打开手机系统相册[通俗易懂]

    Android之打开手机系统相册[通俗易懂]1、需求打开系统相册,获取图片进行扫描操作2、代码实现IntentpickIntent=newIntent(Intent.ACTION_PICK,MediaStore.Images.Media.EXTERNAL_CONTENT_URI);pickIntent.setDataAndType(Med…

    2026年2月12日
    7
  • mysql中not exists用法_not exists用法

    mysql中not exists用法_not exists用法notexists是sql中的一个语法,常用在子查询和主查询之间,用于条件判断,根据一个条件返回一个布尔值,从而来确定下一步操作如何进行,notexists也是exists或in的对立面。notexists是exists的对立面,所以要了解notexists的用法,我们首先了解下exists、in的区别和特点:exists:强调的是是否返回结果集,不要求知道返回什么,比如:sele…

    2022年7月15日
    15
  • python编写淘宝秒杀脚本

    python编写淘宝秒杀脚本最近想抢冰墩墩的手办和钥匙圈,但是同志们抢的速度太快了,无奈,还是自己写脚本吧。添加火狐浏览器插件Omnibug是一个插件,可以简化web度量实现的开发。检查每个传出请求(由浏览器发送)的模式;如果出现匹配,URL将显示在开发人员工具面板中,并进行解码以显示请求的详细信息。在火狐浏览器的插件中直接搜索、下载即可安装geckodriver在python中使用selenium爬取动态渲染网页,这个过程之中需要安装浏览器驱动geckodrivergeckodrivergithub链接将下载后到

    2022年6月9日
    31
  • 高效开发[通俗易懂]

    高效开发[通俗易懂]高效开发

    2022年4月22日
    40
  • PHPer面试指南-php 篇(一)「建议收藏」

    PHPer面试指南-php 篇(一)

    2022年2月11日
    55

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号