大数据之hbase(三) --- 原生扫描,缓存扫描,批量扫描,扫描过滤器,计数器,coprocessor 协处理器

一、扫描:原生扫描(专家)
-----------------------------------------------------------
    1.一般的扫描,如果不指定版本,仅仅扫描一个版本的数据。指定了就扫指定版本的数据,但是版本不会超过创建表时指定的版本数

    2.但是,如果想扫描更多的版本(大于创建表时指定的版本数),可以使用原生扫描,可以将所有的历史版本全部扫描出来
        $hbase> scan 'ns1:t2', {COLUMN=>'f1', RAW => true, VERSIONS => 10}


二、扫描:缓存扫描和批量扫描
---------------------------------------------------------------
    1.扫描之扫描器缓存--面向行级别的,一次RPC读取多少行

        a.扫描的每一个next()调用都会为每行数据生成一个单独的PRC,当循环调用的时候,很耗费性能

        b.扫描器缓存可以让一次RPC请求获取多行数据。默认扫描器缓存是关闭的

        c.扫描器缓存分为表缓存[整个表的扫描均应用]和单次扫描缓存[仅当次扫描应用]
           a)表层面(全局)
                <property>
                    <name>hbase.client.scanner.caching</name>
                    <!-- 整数最大值 -->
                    <value>2147483647</value>
                    <source>hbase-default.xml</source>
                </property>

            b)操作层面
                //设置量
                scan.setCaching(10);

        d.代码测试
            
/**
             * 测试全表扫描-带扫描器缓存
             */
            @Test
            public void tsScanTable_3() throws Exception {
                long time = System.currentTimeMillis();
                Scan scan = new Scan();
                scan.setCaching(10);     //1 --> 7060ms  10 -->1353ms  1000--> 420ms
                ResultScanner scanner = tb.getScanner(scan);
                Result result = null;
                while((result =  scanner.next()) != null)
                {
                    System.out.print(Bytes.toString(result.getValue(Bytes.toBytes("f1"), Bytes.toBytes("name"))));
                }
                System.out.println();
                System.out.println(System.currentTimeMillis() - time);
            }
    2.扫描之批量扫描 -- 面向列级别的,一次RPC读取多少列
        a.控制scanner的next函数返回的列的数量

        b.scanner.setBatch(5);  //一次next会返回5列,加入一行一共有17列,那么就会分片返回,分4片,5,5,5,2


三、扫描:过滤器
------------------------------------------------------------------
    1.RowFilter 行过滤器
        
/**
         * 测试行过滤器RowFilter
         * 扫描所有rowkey二进制数小于‘row0200’的行
         */
        @Test
        public void tsRowFilter() throws Exception {

            Scan scan = new Scan();
            //新建一个行对比器,使用的是小于或等于对比方式,比较器是二进制比较器BinaryComparator
            RowFilter filter = new RowFilter(CompareFilter.CompareOp.LESS_OR_EQUAL, new BinaryComparator(Bytes.toBytes("row0200")));
            scan.setFilter(filter);
            ResultScanner scanner = tb.getScanner(scan);
            Result result = null;
            while((result =  scanner.next()) != null)
            {
                System.out.println("rowkey-->" + Bytes.toString(result.getRow()));
            }
        }

    2.FamilyFilter 列族过滤器
       
 /**
         * 测试列族过滤器FamilyFilter
         * 扫描所有family二进制数小于‘f2’的列族
         */
        @Test
        public void tsFamilyFilter() throws Exception {

            TableName tbName = TableName.valueOf("ns1:t7");
            tb = conn.getTable(tbName);
            Scan scan = new Scan();
            //新建一个列族对比器,使用的是小于的对比方式,比较器是二进制比较器BinaryComparator
            FamilyFilter filter = new FamilyFilter(CompareFilter.CompareOp.LESS, new BinaryComparator(Bytes.toBytes("f2")));
            scan.setFilter(filter);
            ResultScanner scanner = tb.getScanner(scan);
            Result result = null;
            while((result =  scanner.next()) != null)
            {
                byte[] f1name = result.getValue(Bytes.toBytes("f1"), Bytes.toBytes("name"));
                byte[] f2name = result.getValue(Bytes.toBytes("f2"), Bytes.toBytes("name"));
                byte[] f3name = result.getValue(Bytes.toBytes("f3"), Bytes.toBytes("name"));
                System.out.println(f1name + ":" + f2name + ":" + f3name);
            }
        }

    3.QualifierFilter 列过滤器
       
 /**
        * 测试列过滤器QualifierFilter
        * 扫描所有column二进制数小于‘name’的列族
        */
        @Test
        public void tsColumnFilter() throws Exception {

          TableName tbName = TableName.valueOf("ns1:t7");
          tb = conn.getTable(tbName);
          Scan scan = new Scan();
          QualifierFilter filter = new QualifierFilter(CompareFilter.CompareOp.LESS_OR_EQUAL, new BinaryComparator(Bytes.toBytes("id")));
          scan.setFilter(filter);
          ResultScanner scanner = tb.getScanner(scan);
          Result result = null;
          while((result =  scanner.next()) != null)
          {
              Map<byte[],byte[]> map = result.getFamilyMap(Bytes.toBytes("f1"));
              Set<byte[]> set = map.keySet();
              for( byte [] bs: set )
              {
                  System.out.println(Bytes.toString(bs) + ":" + Bytes.toString(map.get(bs)));
              }
          }
        }

    4.ValueFilter值过滤器
      
  /**
         * 测试Value过滤器ValueFilter
         * 扫描所有含有‘to’的cell
         */
        @Test
        public void tsValueFilter() throws Exception {

            TableName tbName = TableName.valueOf("ns1:t7");
            tb = conn.getTable(tbName);
            Scan scan = new Scan();
            //新建一个值对比器,使用的是等于的对比方式,比较器是字符串比较器SubstringComparator
            ValueFilter filter = new ValueFilter(CompareFilter.CompareOp.EQUAL, new SubstringComparator("tom"));
            scan.setFilter(filter);
            ResultScanner scanner = tb.getScanner(scan);
            Result result = null;
            while((result =  scanner.next()) != null)
            {
                Map<byte[],byte[]> map = result.getFamilyMap(Bytes.toBytes("f1"));
                Set<byte[]> set = map.keySet();
                for( byte [] bs: set )
                {
                    System.out.println(Bytes.toString(bs) + ":" + Bytes.toString(map.get(bs)));
                }
            }
        }


    5.SingleColumnValueFilter单列值过滤器
       
 /**
         * 测试单列值过滤器SingleColumnFilter
         * 如果cell value 不满足条件,整行过滤掉[f1:name列的值不等于tom1的行,全部过滤掉]
         */
        @Test
        public void tsSingleColumnFilter() throws Exception {

            TableName tbName = TableName.valueOf("ns1:t7");
            tb = conn.getTable(tbName);
            Scan scan = new Scan();

            SingleColumnValueFilter filter = new SingleColumnValueFilter(
                    Bytes.toBytes("f1"),
                    Bytes.toBytes("name"),
                    CompareFilter.CompareOp.EQUAL,
                    new BinaryComparator(Bytes.toBytes("tom1"))
            );

            scan.setFilter(filter);
            ResultScanner scanner = tb.getScanner(scan);
            Result result = null;
            while((result =  scanner.next()) != null)
            {
                System.out.println("=================================================");
                byte[] bb = result.getRow();
                System.out.println("row:" + Bytes.toString(bb));
                System.out.println("=================================================");
                //得到一行的所有map==> [ key=>f1 , value=> map< column , map< timestamp, finalvalue > >  ]
                NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> map = result.getMap();
                Set<byte[]> set1 = map.keySet();
                for(byte[] bs1 :  set1)
                {
                    //key => f1
                    String f1 = Bytes.toString(bs1);
                    //System.out.println("列族名:" +f1);
                    //value
                    NavigableMap<byte[], NavigableMap<Long, byte[]>> map2 = map.get(bs1);
                    Set<byte[]> set2 = map2.keySet();
                    for(byte[] bs2 : set2)
                    {
                        String column = Bytes.toString(bs2);
                        //System.out.println(f1 + "_" + column);
                        NavigableMap<Long, byte[]> map3 = map2.get(bs2);
                        Set<Long> set3 = map3.keySet();
                        for(Long l3 : set3)
                        {
                            //System.out.println("time_stamp:" + l3);
                            byte[] value = map3.get(l3);
                            System.out.println(f1 + "_" + column +  "_"+Bytes.toString(value));
                        }
                    }
                }
            }
        }

    6.SingleColumnValueExcludeFilter单列值排除过滤器
        -- 如果cell value 不满足条件,整行过滤掉,而且会将过滤条件中的列也过滤掉
        -- SingleColumnValueExcludeFilter filter = new SingleColumnValueExcludeFilter(
                               Bytes.toBytes("f1"),
                               Bytes.toBytes("name"),
                               CompareFilter.CompareOp.EQUAL,
                               new BinaryComparator(Bytes.toBytes("tom1"))
                       );
        -- 结果会将f1:name列的值不等于tom1的行,全部过滤掉,并且在过滤结果中过滤掉name列的值(不要过滤条件列值)



    7.PrefixFilter 前缀过滤
        -- PrefixFilter filter = new PrefixFilter(Bytes.toBytes("row4"));
        -- 只显示 rowkey 以 ‘row4’ 开头的行[row40,row41,...,row422等等]


    8.分页过滤器PageFilter
        -- PageFilter filter = new PageFilter(10);
        -- 显示表的前10行记录[但是注意,如果一个表分了3个区域储存,就会显示30行数据,显示每个区域的前10行数据]

    9.keyonly过滤器
        -- 只提取key,丢弃value
        -- KeyOnlyFilter filter = new KeyOnlyFilter(true/false);
        -- true  -->结果只显示rowkey,familykey,columnkey,而用value的值的字节数组长度代替。可以帮助查看表结构
        -- false -->结果只显示rowkey,familykey,columnkey,而不显示他们的值。可以帮助查看表结构

    10.首次rowkey过滤器
        -- 当首次找到指定的rowkey,就不再往下找了,类似于循环的break

    11.列分页过滤器
        -- 过滤列,列不在指定范围中,就会被过滤掉
        -- ColumnPaginationFilter filter = new ColumnPaginationFilter(limit:2, offect:4);
        -- limit 2,保留2个列的长度
        -- offect:4,表示偏移量,偏移四列
        -- 结果就是只显示第5列和第6列,这两个列的数据

    12.正则表达式对比器
        -- 只保留RegexStringComparator对比器中的正则表达式的对象
        -- ValueFilter filter = new ValueFilter(CompareFilter.CompareOp.EQUAL, new RegexStringComparator("^tom1"));
        -- 保留所有以tom1开头的值

    13.FilterList 过滤器组合实现复杂查询
        -- 实现类似sql语句的复杂查询:select * from t7 where id <= 4 and name like '%3';
            //where id <= 4
            SingleColumnValueFilter f1 = new SingleColumnValueFilter(
                    Bytes.toBytes("f1"),
                    Bytes.toBytes("id"),
                    CompareFilter.CompareOp.LESS_OR_EQUAL,
                    new BinaryComparator(Bytes.toBytes("4"))
            );

            //where name end with 3
            ValueFilter  f2 = new ValueFilter (
                    CompareFilter.CompareOp.EQUAL,
                    new RegexStringComparator("om6$")  //^3 以3开头
            );

            FilterList flist = new FilterList(FilterList.Operator.MUST_PASS_ALL);
            flist.addFilter(f1);
            flist.addFilter(f2);


四、计数器
------------------------------------------------------
    1.针对实时统计(鼠标点击流等)的优化方案

    2.shell使用
        $hbase> create 'ns1:t8', 'f1'
        $hbase> incr 'ns1:t8' , 'row1','f1:click' , 1       //将ns1:t8的row1行的f1:click + 1 ,模拟点击
        $hbase> get_counter  'ns1:t8','row1', 'f1:click'    //统计点击量

    3.API使用
       
 @Test
        public void tsCounter() throws Exception {

        //        tb.incrementColumnValue(
        //                Bytes.toBytes("row2"),
        //                Bytes.toBytes("f1"),
        //                Bytes.toBytes("click"),
        //                1
        //        );

            //创建计数器
            Increment incr = new Increment(Bytes.toBytes("row1"));
            incr.addColumn(Bytes.toBytes("f1"), Bytes.toBytes("daily"), 1);
            incr.addColumn(Bytes.toBytes("f1"), Bytes.toBytes("weekly"), 10);
            incr.addColumn(Bytes.toBytes("f1"), Bytes.toBytes("monthly"), 100);
            //绑定计数器
            tb.increment(incr);
        }


五、coprocessor 协处理器
------------------------------------------------------------------
    1.相当于mysql中的储存过程。用预制好的语句,来进行批量处理的一种机制。

    2.配置[hbase-site.xml]
        
        <property>
            <name>hbase.coprocessor.region.classes</name>
            <value>coprocessor.RegionObserverExample, coprocessor.AnotherCoprocessor</value>
        </property>
        <property>
            <name>hbase.coprocessor.master.classes</name>
            <value>coprocessor.MasterObserverExample</value>
        </property>
        <property>
            <name>hbase.coprocessor.wal.classes</name>
            <value>coprocessor.WALObserverExample, bar.foo.MyWALObserver</value>
        </property>


    3.协处理框架的类主要分为两个大类,一个是observer[观察者],另一个是endpoint[终端]
        a.观察者
            1)类似触发器,具有回调机制。当感兴趣的事件发生了,就执行注册好的回调方法

            2)重要的实现类
                -- RegionObserver 区域观察者:用户可以用这种处理器处理发生在region上的数据修改事件

                -- MasterObserver 管理观察者:用户可以用这种处理器处理发生在master或者集群层面的DDL类型的数据修改事件

                -- WALObserver WAL观察者:用户可以用这种处理器处理发生在WAL,HLOG层面的数据修改事件

        b.endpoint[终端]
            1)类似于储存过程。预先预制好处理的语句过程,将用户自定义的操作存储在服务端,在服务端层面做一些计算的工作



    4.RegionObserver的执行过程分析
                       [                 RegionObserver          ]
        unassigned --> [ pending open --> open --> pending close ] --> closed


    5.RegionObserver 代码实现:对客户的每次put 或者 get都做一次记录
        a.编写代码
           
 import org.apache.hadoop.hbase.Cell;
            import org.apache.hadoop.hbase.CoprocessorEnvironment;
            import org.apache.hadoop.hbase.client.Delete;
            import org.apache.hadoop.hbase.client.Durability;
            import org.apache.hadoop.hbase.client.Get;
            import org.apache.hadoop.hbase.client.Put;
            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.FileWriter;
            import java.io.IOException;
            import java.util.List;

            /**
             * 测试自定义区域观察者
             */
            public class TsRegionObserver extends BaseRegionObserver {

                //输出日志
                private void outLogs(String str)
                {
                    try {
                        FileWriter fw = new FileWriter("/home/ubuntu/tsRegionServer.txt",true);
                        fw.write(str);
                        fw.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void start(CoprocessorEnvironment e) throws IOException {
                    super.start(e);
                    outLogs("TsRegionObserver.start()");
                }

                @Override
                public void stop(CoprocessorEnvironment e) throws IOException {
                    super.stop(e);
                    outLogs("TsRegionObserver.stop()");
                }

                @Override
                public void preOpen(ObserverContext<RegionCoprocessorEnvironment> e) throws IOException {
                    super.preOpen(e);
                    outLogs("TsRegionObserver.preOpen()");
                }

                @Override
                public void postOpen(ObserverContext<RegionCoprocessorEnvironment> e) {
                    super.postOpen(e);
                    outLogs("TsRegionObserver.postOpen()");
                }

                @Override
                public void preClose(ObserverContext<RegionCoprocessorEnvironment> c, boolean abortRequested) throws IOException {
                    super.preClose(c, abortRequested);
                    outLogs("TsRegionObserver.preClose()");
                }

                @Override
                public void postClose(ObserverContext<RegionCoprocessorEnvironment> e, boolean abortRequested) {
                    super.postClose(e, abortRequested);
                    outLogs("TsRegionObserver.postClose()");
                }

                @Override
                public void preGetOp(ObserverContext<RegionCoprocessorEnvironment> e, Get get, List<Cell> results) throws IOException {
                    super.preGetOp(e, get, results);
                    String rowkey = Bytes.toString(get.getRow());
                    outLogs("TsRegionObserver.preGetOp():rowkey -->" + rowkey );
                }

                @Override
                public void postGetOp(ObserverContext<RegionCoprocessorEnvironment> e, Get get, List<Cell> results) throws IOException {
                    super.postGetOp(e, get, results);
                    String rowkey = Bytes.toString(get.getRow());
                    outLogs("TsRegionObserver.postGetOp():rowkey -->" + rowkey );
                }

                @Override
                public void prePut(ObserverContext<RegionCoprocessorEnvironment> e, Put put, WALEdit edit, Durability durability) throws IOException {
                    super.prePut(e, put, edit, durability);
                    String rowkey = Bytes.toString(put.getRow());
                    outLogs("TsRegionObserver.prePut():rowkey-->" + rowkey);
                }

                @Override
                public void postPut(ObserverContext<RegionCoprocessorEnvironment> e, Put put, WALEdit edit, Durability durability) throws IOException {
                    super.postPut(e, put, edit, durability);
                    String rowkey = Bytes.toString(put.getRow());
                    outLogs("TsRegionObserver.postPut():rowkey-->" + rowkey);
                }

                @Override
                public void preDelete(ObserverContext<RegionCoprocessorEnvironment> e, Delete delete, WALEdit edit, Durability durability) throws IOException {
                    super.preDelete(e, delete, edit, durability);

                    String rowkey = Bytes.toString(delete.getRow());
                    outLogs("TsRegionObserver.preDelete():rowkey-->" + rowkey);
                }

                @Override
                public void postDelete(ObserverContext<RegionCoprocessorEnvironment> e, Delete delete, WALEdit edit, Durability durability) throws IOException {
                    super.postDelete(e, delete, edit, durability);
                    String rowkey = Bytes.toString(delete.getRow());
                    outLogs("TsRegionObserver.postDelete():rowkey-->" + rowkey);
                }
            }

        b.注册协处理器,并分发到所有hbase节点
            [hbase-site.xml]
            <property>
                <name>hbase.coprocessor.region.classes</name>
                <value>ts.hbase.TsRegionObserver</value>
            </property>

        c.导出jar包

        d.拷贝jar包到hbase所有节点的lib目录下

        e.在hbase shell 端进行get和put操作,查看打印日志/home/ubuntu/tsRegionServer.txt内容的变化















猜你喜欢

转载自blog.csdn.net/xcvbxv01/article/details/82725255
今日推荐