zoukankan      html  css  js  c++  java
  • HBase笔记

    1.1. 什么是HBASE

    1.1.1. 概念特性

      HBASE是一个数据库----可以提供数据的实时随机读写。HBASE与mysql、oralce、db2、sqlserver等关系型数据库不同,它是一个NoSQL数据库(非关系型数据库)

    • Hbase的表模型与关系型数据库的表模型不同:
    • Hbase的表没有固定的字段定义;
    • Hbase的表中每行存储的都是一些key-value对
    • Hbase的表中有列族的划分,用户可以指定将哪些kv插入哪个列族
    • Hbase的表在物理存储上,是按照列族来分割的,不同列族的数据一定存储在不同的文件中
    • Hbase的表中的每一行都固定有一个行键,而且每一行的行键在表中不能重复
    • Hbase中的数据,包含行键,包含key,包含value,都是byte[ ]类型,hbase不负责为用户维护数据类型
    • HBASE对事务的支持很差 

      HBASE相比于其他nosql数据库(mongodb、redis、cassendra、hazelcast)的特点:

      Hbase的表数据存储在HDFS文件系统中

      从而,hbase具备如下特性:存储容量可以线性扩展; 数据存储的安全性可靠性极高!

    1.2 安装HBASE

      HBASE是一个分布式系统。其中有一个管理角色:HMaster(一般2台,一台active,一台backup);其他的数据节点角色:  HRegionServer(很多台,看数据容量)

    1.2.1. 安装准备:

      首先,要有一个HDFS集群,并正常运行; regionserver应该跟hdfs中的datanode在一起

      其次,还需要一个zookeeper集群,并正常运行

      然后,安装HBASE

      角色分配如下:

        Hdp01:  namenode  datanode  regionserver  hmaster  zookeeper

        Hdp02:  datanode   regionserver  zookeeper

        Hdp03:  datanode   regionserver  zookeeper

    1.2.2. 安装步骤:

    1.安装zookeeper     

    2.安装hbase

      解压hbase安装包

      修改hbase-env.sh

    export JAVA_HOME=/root/apps/jdk1.7.0_67
    export HBASE_MANAGES_ZK=false

      修改hbase-site.xml 

    <configuration>
    <!-- 指定hbase在HDFS上存储的路径 -->
            <property>
                    <name>hbase.rootdir</name>
                    <value>hdfs://hdp01:9000/hbase</value>
            </property>
    <!-- 指定hbase是分布式的 -->
            <property>
                    <name>hbase.cluster.distributed</name>
                    <value>true</value>
            </property>
    <!-- 指定zk的地址,多个用“,”分割 -->
            <property>
                    <name>hbase.zookeeper.quorum</name>
                   <value>hdp01:2181,hdp02:2181,hdp03:2181</value>
            </property>
    </configuration>

      修改 regionservers 

    hdp01
    hdp02
    hdp03

    3. 启动hbase集群: 

      bin/start-hbase.sh  启动完后,还可以在集群中找任意一台机器启动一个备用的master

      bin/hbase-daemon.sh start master  新启的这个master会处于backup状态

    4. 启动hbase的命令行客户端

      bin/hbase shell

      Hbase> list     // 查看表

      Hbase> status   // 查看集群状态

      Hbase> version  // 查看集群版本

    1.3. HBASE表模型

      hbase的表模型跟mysql之类的关系型数据库的表模型差别巨大

      hbase的表模型中有:行的概念;但没有字段的概念

      行中存的都是key-value对,每行中的key-value对中的key可以是各种各样,每行中的key-value对的数量也可以是各种各样

    1.3.1. hbase表模型的要点:

      1、一个表,有表名

      2、一个表可以分为多个列族(不同列族的数据会存储在不同文件中)

      3、表中的每一行有一个“行键rowkey”,而且行键在表中不能重复

      4、表中的每一对kv数据称作一个cell

      5、hbase可以对数据存储多个历史版本(历史版本数量可配置)

      6、整张表由于数据量过大,会被横向切分成若干个region(用rowkey范围标识),不同region的数据也存储在不同文件中

      7、hbase会对插入的数据按顺序存储:

        要点一:首先会按行键排序

        要点二:同一行里面的kv会按列族排序,再按k排序 

    1.3.2. hbase的表中能存储什么数据类型

      hbase中只支持byte[]。此处的byte[] 包括了: rowkey,key,value,列族名,表名

    1.3.3. HBASE表的物理存储结构

    1.4. 3/ hbase命令行客户端操作

    1.4.0.1. 建表:

      create 't_user_info','base_info','extra_info'

                   表名      列族名   列族名

    1.4.0.2. 插入数据:

    hbase(main):011:0> put 't_user_info','001','base_info:username','zhangsan'
    0 row(s) in 0.2420 seconds
    hbase(main):012:0> put 't_user_info','001','base_info:age','18'
    0 row(s) in 0.0140 seconds
    hbase(main):013:0> put 't_user_info','001','base_info:sex','female'
    0 row(s) in 0.0070 seconds
    hbase(main):014:0> put 't_user_info','001','extra_info:career','it'
    0 row(s) in 0.0090 seconds
    hbase(main):015:0> put 't_user_info','002','extra_info:career','actoress'
    0 row(s) in 0.0090 seconds
    hbase(main):016:0> put 't_user_info','002','base_info:username','liuyifei'
    0 row(s) in 0.0060 seconds

    1.4.0.3. 查询数据方式一:scan 扫描

    hbase(main):017:0> scan 't_user_info'
    ROW                               COLUMN+CELL                                                                                     
     001                              column=base_info:age, timestamp=1496567924507, value=18                                         
     001                              column=base_info:sex, timestamp=1496567934669, value=female                                     
     001                              column=base_info:username, timestamp=1496567889554, value=zhangsan                              
     001                              column=extra_info:career, timestamp=1496567963992, value=it                                     
     002                              column=base_info:username, timestamp=1496568034187, value=liuyifei                              
     002                              column=extra_info:career, timestamp=1496568008631, value=actoress                               
    2 row(s) in 0.0420 seconds

    1.4.0.4. 查询数据方式二:get 单行数据

    hbase(main):020:0> get 't_user_info','001'
    COLUMN                            CELL                                                                                            
     base_info:age                    timestamp=1496568160192, value=19                                                               
     base_info:sex                    timestamp=1496567934669, value=female                                                           
     base_info:username               timestamp=1496567889554, value=zhangsan                                                         
     extra_info:career                timestamp=1496567963992, value=it                                                               
    4 row(s) in 0.0770 seconds 

    1.4.0.5. 删除一个kv数据

    hbase(main):021:0> delete 't_user_info','001','base_info:sex'
    0 row(s) in 0.0390 seconds

      删除整行数据: 

    hbase(main):024:0> deleteall 't_user_info','001'
    0 row(s) in 0.0090 seconds
    hbase(main):025:0> get 't_user_info','001'
    COLUMN                            CELL                                                                                            
    0 row(s) in 0.0110 seconds 

    1.4.0.6. 删除整个表:

    hbase(main):028:0> disable 't_user_info'
    0 row(s) in 2.3640 seconds
    hbase(main):029:0> drop 't_user_info'
    0 row(s) in 1.2950 seconds
    hbase(main):030:0> list
    TABLE                                                                                                                             
    0 row(s) in 0.0130 seconds 
    => []

    1.5. 4/ Hbase重要特性--排序特性(行键)

      插入到hbase中去的数据,hbase会自动排序存储:

      排序规则:  首先看行键,然后看列族名,然后看列(key)名; 按字典顺序

      Hbase的这个特性跟查询效率有极大的关系

      比如:一张用来存储用户信息的表,有名字,户籍,年龄,职业....等信息

      然后,在业务系统中经常需要:

      查询某个省的所有用户

      经常需要查询某个省的指定姓的所有用户

      思路:如果能将相同省的用户在hbase的存储文件中连续存储,并且能将相同省中相同姓的用户连续存储,那么,上述两个查询需求的效率就会提高!!!

      做法:将查询条件拼到rowkey内

    1.6. 5/ HBASE客户端API操作

    1.6.1. DDL操作

      1、创建一个连接

        Connection conn = ConnectionFactory.createConnection(conf);

      2、拿到一个DDL操作器:表管理器admin

        Admin admin = conn.getAdmin();

      3、用表管理器的api去建表、删表、修改表定义

        admin.createTable(HTableDescriptor descriptor); 

    1.7. 6 HBASE运行原理

    1.7.1. 组件结构图

     

    1.7.2. MASTER职责

    • 管理HRegionServer,实现其负载均衡。
    • 管理和分配HRegion,比如在HRegion split时分配新的HRegion;在HRegionServer退出时迁移其负责的HRegion到其他HRegionServer上。
    • Admin职能  创建、删除、修改Table的定义。实现DDL操作(namespace和table的增删改,column familiy的增删改等)。
    • 管理namespace和table的元数据(实际存储在HDFS上)。
    • 权限控制(ACL)。
    • 监控集群中所有HRegionServer的状态(通过Heartbeat和监听ZooKeeper中的状态)。

    1.7.3. REGION SERVER职责

    • 管理自己所负责的region数据的读写。
    • 读写HDFS,管理Table中的数据。
    • Client直接通过HRegionServer读写数据(从HMaster中获取元数据,找到RowKey所在的HRegion/HRegionServer后)。

    1.7.4. Zookeeper集群所起作用

    • 存放整个HBase集群的元数据以及集群的状态信息。
    • 实现HMaster主从节点的failover。

      注: HMaster通过监听ZooKeeper中的Ephemeral节点(默认:/hbase/rs/*)来监控HRegionServer的加入和宕机。

      在第一个HMaster连接到ZooKeeper时会创建Ephemeral节点(默认:/hbasae/master)来表示Active的HMaster,其后加进来的HMaster则监听该Ephemeral节点

      如果当前Active的HMaster宕机,则该节点消失,因而其他HMaster得到通知,而将自身转换成Active的HMaster,在变为Active的HMaster之前,它会在/hbase/masters/下创建自己的Ephemeral节点。

    1.7.5. HBASE读写数据流程

      1、在HBase 0.96以前,HBase有两个特殊的Table:-ROOT-和.META. 用来记录用户表的rowkey范围所在的的regionserver服务器;

     

      因而客户端读写数据时需要通过3次寻址请求来对数据所在的regionserver进行定位,效率低下;

      2、而在HBase 0.96以后去掉了-ROOT- Table,只剩下这个特殊的目录表叫做Meta Table(hbase:meta),它存储了集群中所有用户HRegion的位置信息,而ZooKeeper的节点中(/hbase/meta-region-server)存储的则直接是这个Meta Table的位置,并且这个Meta Table如以前的-ROOT- Table一样是不可split的。这样,客户端在第一次访问用户Table的流程就变成了:

      ① 从ZooKeeper(/hbase/meta-region-server)中获取hbase:meta的位置(HRegionServer的位置),缓存该位置信息。

      ② 从HRegionServer中查询用户Table对应请求的RowKey所在的HRegionServer,缓存该位置信息。

      ③ 从查询到HRegionServer中读取Row。

      注:客户会缓存这些位置信息,然而第二步它只是缓存当前RowKey对应的HRegion的位置,因而如果下一个要查的RowKey不在同一个HRegion中,则需要继续查询hbase:meta所在的HRegion,然而随着时间的推移,客户端缓存的位置信息越来越多,以至于不需要再次查找hbase:meta Table的信息,除非某个HRegion因为宕机或Split被移动,此时需要重新查询并且更新缓存。

    1.7.6. hbase:meta表

      hbase:meta表存储了所有用户HRegion的位置信息:

      Rowkey:tableName,regionStartKey,regionId,replicaId等;

      info列族:这个列族包含三个列,他们分别是:

      info:regioninfo列:regionId,tableName,startKey,endKey,offline,split,replicaId;

      info:server列:HRegionServer对应的server:port;

      info:serverstartcode列:HRegionServer的启动时间戳。

    1.7.7. REGION SERVER内部机制

    • WAL即Write Ahead Log,在早期版本中称为HLog,它是HDFS上的一个文件,如其名字所表示的,所有写操作都会先保证将数据写入这个Log文件后,才会真正更新MemStore,最后写入HFile中。WAL文件存储在/hbase/WALs/${HRegionServer_Name}的目录中
    • BlockCache是一个读缓存,即“引用局部性”原理(也应用于CPU,分空间局部性和时间局部性,空间局部性是指CPU在某一时刻需要某个数据,那么有很大的概率在一下时刻它需要的数据在其附近;时间局部性是指某个数据在被访问过一次后,它有很大的概率在不久的将来会被再次的访问),将数据预读取到内存中,以提升读的性能。
    • HRegion是一个Table中的一个Region在一个HRegionServer中的表达。一个Table可以有一个或多个Region,他们可以在一个相同的HRegionServer上,也可以分布在不同的HRegionServer上,一个HRegionServer可以有多个HRegion,他们分别属于不同的Table。HRegion由多个Store(HStore)构成,每个HStore对应了一个Table在这个HRegion中的一个Column Family,即每个Column Family就是一个集中的存储单元,因而最好将具有相近IO特性的Column存储在一个Column Family,以实现高效读取(数据局部性原理,可以提高缓存的命中率)。HStore是HBase中存储的核心,它实现了读写HDFS功能,一个HStore由一个MemStore 和0个或多个StoreFile组成。
    • MemStore是一个写缓存(In Memory Sorted Buffer),所有数据的写在完成WAL日志写后,会 写入MemStore中,由MemStore根据一定的算法将数据Flush到地层HDFS文件中(HFile),通常每个HRegion中的每个 Column Family有一个自己的MemStore。
    • HFile(StoreFile) 用于存储HBase的数据(Cell/KeyValue)。在HFile中的数据是按RowKey、Column Family、Column排序,对相同的Cell(即这三个值都一样),则按timestamp倒序排列。
    • FLUSH详述

        ① 每一次Put/Delete请求都是先写入到MemStore中,当MemStore满后会Flush成一个新的StoreFile(底层实现是HFile),即一个HStore(Column Family)可以有0个或多个StoreFile(HFile)。

        ② 当一个HRegion中的所有MemStore的大小总和超过了hbase.hregion.memstore.flush.size的大小,默认128MB。此时当前的HRegion中所有的MemStore会Flush到HDFS中。

        ③ 当全局MemStore的大小超过了hbase.regionserver.global.memstore.upperLimit的大小,默认40%的内存使用量。此时当前HRegionServer中所有HRegion中的MemStore都会Flush到HDFS中,Flush顺序是MemStore大小的倒序(一个HRegion中所有MemStore总和作为该HRegion的MemStore的大小还是选取最大的MemStore作为参考?有待考证),直到总体的MemStore使用量低于hbase.regionserver.global.memstore.lowerLimit,默认38%的内存使用量。

        ④ 当前HRegionServer中WAL的大小超过了

          hbase.regionserver.hlog.blocksize * hbase.regionserver.max.logs的数量,当前HRegionServer中所有HRegion中的MemStore都会Flush到HDFS中,

    Flush使用时间顺序,最早的MemStore先Flush直到WAL的数量少于

          hbase.regionserver.hlog.blocksize * hbase.regionserver.max.logs这里说这两个相乘的默认大小是2GB,查代码,hbase.regionserver.max.logs默认值是32,而hbase.regionserver.hlog.blocksize默认是32MB。但不管怎么样,因为这个大小超过限制引起的Flush不是一件好事,可能引起长时间的延迟

     

    Java API接口程序

      1 import java.io.IOException;
      2 
      3 import org.apache.hadoop.conf.Configuration;
      4 import org.apache.hadoop.hbase.HBaseConfiguration;
      5 import org.apache.hadoop.hbase.HColumnDescriptor;
      6 import org.apache.hadoop.hbase.HTableDescriptor;
      7 import org.apache.hadoop.hbase.TableName;
      8 import org.apache.hadoop.hbase.client.Admin;
      9 import org.apache.hadoop.hbase.client.Connection;
     10 import org.apache.hadoop.hbase.client.ConnectionFactory;
     11 import org.apache.hadoop.hbase.regionserver.BloomType;
     12 import org.junit.Before;
     13 import org.junit.Test;
     14 
     15 public class HbaseClientDemo {
     16     Connection conn = null;
     17     
     18     @Before
     19     public void getConn() throws Exception{
     20         // 构建一个连接对象
     21         Configuration conf = HBaseConfiguration.create(); // 会自动加载hbase-site.xml
     22         conf.set("hbase.zookeeper.quorum", "hdp2-master:2181,hdp2-slaver1:2181,hdp2-slaver2:2181");
     23         
     24         conn = ConnectionFactory.createConnection(conf);
     25     }
     26     
     27     
     28     /**
     29      * DDL
     30      * @throws Exception 
     31      */
     32     @Test
     33     public void testCreateTable() throws Exception{
     34 
     35         // 从连接中构造一个DDL操作器
     36         Admin admin = conn.getAdmin();
     37         
     38         // 创建一个表定义描述对象
     39         HTableDescriptor hTableDescriptor = new HTableDescriptor(TableName.valueOf("user_info"));
     40         
     41         // 创建列族定义描述对象
     42         HColumnDescriptor hColumnDescriptor_1 = new HColumnDescriptor("base_info");
     43         hColumnDescriptor_1.setMaxVersions(3); // 设置该列族中存储数据的最大版本数,默认是1
     44         
     45         HColumnDescriptor hColumnDescriptor_2 = new HColumnDescriptor("extra_info");
     46         
     47         // 将列族定义信息对象放入表定义对象中
     48         hTableDescriptor.addFamily(hColumnDescriptor_1);
     49         hTableDescriptor.addFamily(hColumnDescriptor_2);
     50         
     51         
     52         // 用ddl操作器对象:admin 来建表
     53         admin.createTable(hTableDescriptor);
     54         
     55         // 关闭连接
     56         admin.close();
     57         conn.close();
     58         
     59     }
     60     
     61     
     62     /**
     63      * 删除表
     64      * @throws Exception 
     65      */
     66     @Test
     67     public void testDropTable() throws Exception{
     68         
     69         Admin admin = conn.getAdmin();
     70         
     71         // 停用表
     72         admin.disableTable(TableName.valueOf("user_info"));
     73         // 删除表
     74         admin.deleteTable(TableName.valueOf("user_info"));
     75         
     76         
     77         admin.close();
     78         conn.close();
     79     }
     80     
     81     // 修改表定义--添加一个列族
     82     @Test
     83     public void testAlterTable() throws Exception{
     84         
     85         Admin admin = conn.getAdmin();
     86         
     87         // 取出旧的表定义信息
     88         HTableDescriptor tableDescriptor = admin.getTableDescriptor(TableName.valueOf("user_info"));
     89         
     90         
     91         // 新构造一个列族定义
     92         HColumnDescriptor hColumnDescriptor = new HColumnDescriptor("other_info");
     93         hColumnDescriptor.setBloomFilterType(BloomType.ROWCOL); // 设置该列族的布隆过滤器类型
     94         
     95         // 将列族定义添加到表定义对象中
     96         tableDescriptor.addFamily(hColumnDescriptor);
     97         
     98         
     99         // 将修改过的表定义交给admin去提交
    100         admin.modifyTable(TableName.valueOf("user_info"), tableDescriptor);
    101         
    102         
    103         admin.close();
    104         conn.close();
    105         
    106     }
    107 }
      1 import java.util.ArrayList;
      2 import java.util.Iterator;
      3 
      4 import org.apache.hadoop.conf.Configuration;
      5 import org.apache.hadoop.hbase.Cell;
      6 import org.apache.hadoop.hbase.CellScanner;
      7 import org.apache.hadoop.hbase.HBaseConfiguration;
      8 import org.apache.hadoop.hbase.TableName;
      9 import org.apache.hadoop.hbase.client.Connection;
     10 import org.apache.hadoop.hbase.client.ConnectionFactory;
     11 import org.apache.hadoop.hbase.client.Delete;
     12 import org.apache.hadoop.hbase.client.Get;
     13 import org.apache.hadoop.hbase.client.Put;
     14 import org.apache.hadoop.hbase.client.Result;
     15 import org.apache.hadoop.hbase.client.ResultScanner;
     16 import org.apache.hadoop.hbase.client.Scan;
     17 import org.apache.hadoop.hbase.client.Table;
     18 import org.apache.hadoop.hbase.util.Bytes;
     19 import org.junit.Before;
     20 import org.junit.Test;
     21 
     22 public class HbaseClientDML {
     23     Connection conn = null;
     24     
     25     @Before
     26     public void getConn() throws Exception{
     27         // 构建一个连接对象
     28         Configuration conf = HBaseConfiguration.create(); // 会自动加载hbase-site.xml
     29         conf.set("hbase.zookeeper.quorum", "hdp2-master:2181,hdp2-slaver1:2181,hdp2-slaver2:2181");
     30         
     31         conn = ConnectionFactory.createConnection(conf);
     32     }
     33     
     34     
     35     /**
     36      * 增
     37      * 改:put来覆盖
     38      * @throws Exception 
     39      */
     40     @Test
     41     public void testPut() throws Exception{
     42         
     43         // 获取一个操作指定表的table对象,进行DML操作
     44         Table table = conn.getTable(TableName.valueOf("user_info"));
     45         
     46         // 构造要插入的数据为一个Put类型(一个put对象只能对应一个rowkey)的对象
     47         Put put = new Put(Bytes.toBytes("001"));
     48         put.addColumn(Bytes.toBytes("base_info"), Bytes.toBytes("username"), Bytes.toBytes("张三"));
     49         put.addColumn(Bytes.toBytes("base_info"), Bytes.toBytes("age"), Bytes.toBytes("18"));
     50         put.addColumn(Bytes.toBytes("extra_info"), Bytes.toBytes("addr"), Bytes.toBytes("北京"));
     51         
     52         
     53         Put put2 = new Put(Bytes.toBytes("002"));
     54         put2.addColumn(Bytes.toBytes("base_info"), Bytes.toBytes("username"), Bytes.toBytes("李四"));
     55         put2.addColumn(Bytes.toBytes("base_info"), Bytes.toBytes("age"), Bytes.toBytes("28"));
     56         put2.addColumn(Bytes.toBytes("extra_info"), Bytes.toBytes("addr"), Bytes.toBytes("上海"));
     57     
     58         
     59         ArrayList<Put> puts = new ArrayList<>();
     60         puts.add(put);
     61         puts.add(put2);
     62         
     63         
     64         // 插进去
     65         table.put(puts);
     66         
     67         table.close();
     68         conn.close();
     69         
     70     }
     71     
     72     
     73     /**
     74      * 循环插入大量数据
     75      * @throws Exception 
     76      */
     77     @Test
     78     public void testManyPuts() throws Exception{
     79         
     80         Table table = conn.getTable(TableName.valueOf("user_info"));
     81         ArrayList<Put> puts = new ArrayList<>();
     82         
     83         for(int i=0;i<100000;i++){
     84             Put put = new Put(Bytes.toBytes(""+i));
     85             put.addColumn(Bytes.toBytes("base_info"), Bytes.toBytes("username"), Bytes.toBytes("张三"+i));
     86             put.addColumn(Bytes.toBytes("base_info"), Bytes.toBytes("age"), Bytes.toBytes((18+i)+""));
     87             put.addColumn(Bytes.toBytes("extra_info"), Bytes.toBytes("addr"), Bytes.toBytes("北京"));
     88             
     89             puts.add(put);
     90         }
     91         
     92         table.put(puts);
     93         
     94     }
     95     
     96     /**
     97      * 删
     98      * @throws Exception 
     99      */
    100     @Test
    101     public void testDelete() throws Exception{
    102         Table table = conn.getTable(TableName.valueOf("user_info"));
    103         
    104         // 构造一个对象封装要删除的数据信息
    105         Delete delete1 = new Delete(Bytes.toBytes("001"));
    106         
    107         Delete delete2 = new Delete(Bytes.toBytes("002"));
    108         delete2.addColumn(Bytes.toBytes("extra_info"), Bytes.toBytes("addr"));
    109         
    110         ArrayList<Delete> dels = new ArrayList<>();
    111         dels.add(delete1);
    112         dels.add(delete2);
    113         
    114         table.delete(dels);
    115         
    116         
    117         table.close();
    118         conn.close();
    119     }
    120     
    121     /**
    122      * 查
    123      * @throws Exception 
    124      */
    125     @Test
    126     public void testGet() throws Exception{
    127         
    128         Table table = conn.getTable(TableName.valueOf("user_info"));
    129         
    130         Get get = new Get("002".getBytes());
    131         
    132         Result result = table.get(get);
    133         
    134         // 从结果中取用户指定的某个key的value
    135         byte[] value = result.getValue("base_info".getBytes(), "age".getBytes());
    136         System.out.println(new String(value));
    137         
    138         System.out.println("-------------------------");
    139         
    140         // 遍历整行结果中的所有kv单元格
    141         CellScanner cellScanner = result.cellScanner();
    142         while(cellScanner.advance()){
    143             Cell cell = cellScanner.current();
    144             
    145             byte[] rowArray = cell.getRowArray();  //本kv所属的行键的字节数组
    146             byte[] familyArray = cell.getFamilyArray();  //列族名的字节数组
    147             byte[] qualifierArray = cell.getQualifierArray();  //列名的字节数据
    148             byte[] valueArray = cell.getValueArray(); // value的字节数组
    149             
    150             System.out.println("行键: "+new String(rowArray,cell.getRowOffset(),cell.getRowLength()));
    151             System.out.println("列族名: "+new String(familyArray,cell.getFamilyOffset(),cell.getFamilyLength()));
    152             System.out.println("列名: "+new String(qualifierArray,cell.getQualifierOffset(),cell.getQualifierLength()));
    153             System.out.println("value: "+new String(valueArray,cell.getValueOffset(),cell.getValueLength()));
    154             
    155         }
    156         
    157         table.close();
    158         conn.close();
    159         
    160     }
    161     
    162     
    163     /**
    164      * 按行键范围查询数据
    165      * @throws Exception 
    166      */
    167     @Test
    168     public void testScan() throws Exception{
    169         
    170         Table table = conn.getTable(TableName.valueOf("user_info"));
    171         
    172         // 包含起始行键,不包含结束行键,但是如果真的想查询出末尾的那个行键,那么,可以在末尾行键上拼接一个不可见的字节(00)
    173         Scan scan = new Scan("10".getBytes(), "1000001".getBytes());
    174         
    175         ResultScanner scanner = table.getScanner(scan);
    176         
    177         Iterator<Result> iterator = scanner.iterator();
    178         
    179         while(iterator.hasNext()){
    180             
    181             Result result = iterator.next();
    182             // 遍历整行结果中的所有kv单元格
    183             CellScanner cellScanner = result.cellScanner();
    184             while(cellScanner.advance()){
    185                 Cell cell = cellScanner.current();
    186                 
    187                 byte[] rowArray = cell.getRowArray();  //本kv所属的行键的字节数组
    188                 byte[] familyArray = cell.getFamilyArray();  //列族名的字节数组
    189                 byte[] qualifierArray = cell.getQualifierArray();  //列名的字节数据
    190                 byte[] valueArray = cell.getValueArray(); // value的字节数组
    191                 
    192                 System.out.println("行键: "+new String(rowArray,cell.getRowOffset(),cell.getRowLength()));
    193                 System.out.println("列族名: "+new String(familyArray,cell.getFamilyOffset(),cell.getFamilyLength()));
    194                 System.out.println("列名: "+new String(qualifierArray,cell.getQualifierOffset(),cell.getQualifierLength()));
    195                 System.out.println("value: "+new String(valueArray,cell.getValueOffset(),cell.getValueLength()));
    196             }
    197             System.out.println("----------------------");
    198         }
    199     }
    200     
    201     @Test
    202     public void test(){
    203         String a = "000";
    204         String b = "000";
    205         
    206         System.out.println(a);
    207         System.out.println(b);
    208         
    209         
    210         byte[] bytes = a.getBytes();
    211         byte[] bytes2 = b.getBytes();
    212         
    213         System.out.println("");
    214         
    215     }
    216 }
  • 相关阅读:
    linux 查看磁盘空间
    nginx面试中最常见的18道题
    spring -mvc service层调用工具类配置
    IntelliJ IDEA tomcat 远程Ddbug调试
    IntelliJ IDEA tomcat 热部署
    Java HttpClient PostMethod
    Java Base64 加密/解密
    启动tomcat时cmd窗口一闪而过
    remote staging type or host is not specified
    Maven更新后本地仓库jar后缀带有 lastUpdated
  • 原文地址:https://www.cnblogs.com/zhangchao162/p/9858471.html
Copyright © 2011-2022 走看看