一、扫描:原生扫描(专家) ----------------------------------------------------------- 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内容的变化