大数据系列之数据库Hbase知识整理(七)扫描器缓存与批量扫描

到目前为之,每一个next()调用都会为每行数据生成一个单独的RPC请求,即使使用next(int nbRow)方法,也是如此,因为该方法仅仅是在客户端循环地调用next()方法。很显然,当单元格数据较小时,这样做的性能不会很好。因此,如果一次RPC请求可以获取多行数据,这样会更有意义,更加节约资源的使用,减少负载。这样的方法可以由扫描器缓存(scanner caching)实现,默认情况下,这个缓存是关闭的。可以在两个层面上打开他:在表的层面上,这个表所有扫描实例的缓存都会生效;也可以在扫描层面,这样便只会影响当前的扫描实例。

            

1.开启服务器端扫描器缓存
        a)表层面(全局)
            <property>
                <name>hbase.client.scanner.caching</name>
                <!-- 整数最大值 -->
                <value>2147483647</value>
                <source>hbase-default.xml</source>
            </property>

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

代码:

@Test
/**
  * @Description: 扫描器缓存,面向行
  * @param ${tags}
  * @return ${return_type}
  * @throws
  * @author 邹培贤
  * @date 2018/7/21 15:23
  */
public void getScanCache() throws IOException {
    Configuration conf = HBaseConfiguration.create();
    Connection conn = ConnectionFactory.createConnection(conf);
    TableName tableName = TableName.valueOf("ns1:t1");
    Scan scan = new Scan();
    //缓存5000行数据,10000条数据只需要2次rpc请求
    scan.setCaching(5000);
    Table table = conn.getTable(tableName);
    ResultScanner rs = table.getScanner(scan);
    long start = System.currentTimeMillis();
    Iterator<Result> iterator = rs.iterator();
    while(iterator.hasNext()){
        Result r = iterator.next();
        System.out.println(r.getColumnLatestCell(Bytes.toBytes("f1"), Bytes.toBytes("name")));
    }
    System.out.println(System.currentTimeMillis()-start);

}

但是,有一个问题存在,那就是,我们如果缓存了太多的数据,直接发给客户端使用,有可能造成客户端无法承受,造成客户端的压力过大。有什么好的方法可以解决呢,那就是使用批处理扫描,就是把从服务器获得的缓存数据再进行按照列的切割,客户端没次next()就会获得由缓存数据切分的多列数据,直到调用完数据这样就不会给客户端造成太大的压力。

@Test
 /**
   * @Description:批量扫描,面向列
   * @param ${tags}
   * @return ${return_type}
   * @throws
   * @author 邹培贤
   * @date 2018/7/21 15:33
   */
public void testBatchAndCaching() throws IOException {
     Configuration conf = HBaseConfiguration.create();
     Connection conn = ConnectionFactory.createConnection(conf);
     TableName tableName = TableName.valueOf("ns1:t7");
     Scan scan=new Scan();
     //每次缓存多少行数据
     scan.setCaching(2);
     //将缓存的行数据切分4列,每次调用就会返回每行数据的4列数据
     scan.setBatch(4);
     Table table = conn.getTable(tableName);
     ResultScanner rs = table.getScanner(scan);
     Iterator<Result> iterator = rs.iterator();
     while(iterator.hasNext()){
         Result r = iterator.next();
         //得到一行的所有map,key=f1,value=Map<Col,Map<Timestamp,value>>
         NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> map = r.getMap();
         for(Map.Entry<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> entry:map.entrySet()){
             //得到列族
             String f = Bytes.toString(entry.getKey());
             NavigableMap<byte[], NavigableMap<Long, byte[]>> colDataMap = entry.getValue();
             for(Map.Entry<byte[], NavigableMap<Long, byte[]>> ets:colDataMap.entrySet()){
                 String c = Bytes.toString(ets.getKey());
                 NavigableMap<Long, byte[]> tsValueMap = ets.getValue();
                 for(Map.Entry<Long, byte[]> e :tsValueMap.entrySet()){
                     Long ts = e.getKey();
                     String value = Bytes.toString(e.getValue());
                     System.out.print(f + "/" + c + "/" + ts + "=" + value + ",");
                 }
             }

         }
         System.out.println();

     }

 }

猜你喜欢

转载自blog.csdn.net/u011444062/article/details/81146365