Haddoop大数据教程笔记_010_HBASE安装及使用

目录

HBASE安装及使用

HBASE简介:

HBASE是一个数据库----可以提供数据的实时随机读写

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

HBASE安装:

HBASE是一个分布式系统

安装准备:

安装步骤:

1.安装zookeeper(前文已述)

2.安装hbase

3.启动hbase集群(hdfs,zk集群正常运行):

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

HBASE表模型

hbase表模型的要点:

hbase命令行客户端操作

namespace(相当于RDBMS里的database,对table进行分组)

1.建表:

2.插入数据:

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

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

5.删除一个kv数据

6.删除整个表:

Hbase重要特性--排序特性(行键)

HBASE客户端API操作

1.DDL操作

2.DML操作

批量数据如何快速导入HBASE

HBASE的性能调优

MAPREDUCE分析HBASE中的数据

HBASE中的数据建索引


HBASE安装及使用

HBASE简介:

HBASE是一个数据库----可以提供数据的实时随机读写

HBASE与mysql、oralce、db2、sqlserver等关系型数据库不同,它是一个NoSQL数据库(非关系型数据库)

Hbase的表模型与关系型数据库的表模型不同:

Hbase的表没有固定的字段定义;

Hbase的表中每行存储的都是一些key-value对

Hbase的表中有列族的划分,用户可以指定将哪些kv插入哪个列族

Hbase的表在物理存储上,是按照列族来分割的,不同列族的数据一定存储在不同的文件中

Hbase的表中的每一行都固定有一个行键,而且每一行的行键在表中不能重复

Hbase中的数据,包含行键,包含key,包含value,都是byte[ ]类型,hbase不负责为用户维护数据类型

HBASE对事务的支持很差

Hbase表模型示意图

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

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

从而,hbase具备如下特性:

存储容量可以线性扩展

数据存储的安全性可靠性极高

HBASE安装:

HBASE是一个分布式系统

其中有一个管理角色:  HMaster(一般2台,一台active,一台backup)

其他的数据节点角色:  HRegionServer(很多台,看数据容量)

安装准备:

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

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

然后,安装HBASE

角色分配如下:

master:  namenode  datanode  regionserver  hmaster

hdp-01:  datanode   regionserver  QuorumPeerMain

hdp-02:  datanode   regionserver  QuorumPeerMain

hdp-03:  datanode   regionserver  QuorumPeerMain

安装步骤:

1.安装zookeeper(前文已述)

2.安装hbase

解压hbase安装包

修改hbase-env.sh

    export JAVA_HOME=/usr/local/jdk
    export HBASE_MANAGES_ZK=false  
    # Tell HBase whether it should manage it's own instance of Zookeeper or not(是否启用HBase自己的ZK,因为集群zk还要实现其他组件的高可用配置,故统一维护,如果集群出现多个zk集群,会出现端口占用等问题)

修改hbase-site.xml

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

修改 regionservers

    hdp-01
    hdp-02
    hdp-03

环境变量配置

/root/apps/hbase-1.2.1/bin

复制到集群其他节点上.

    scp -r /root/apps/hbase-1.2.1 hdp-01:/root/apps

3.启动hbase集群(hdfs,zk集群正常运行):

    bin/start-hbase.sh

启动完后,还可以在集群中找任意一台机器启动一个备用的master

    bin/hbase-daemon.sh start master

新启的这个master会处于backup状态

外网web端口:(内部服务端口:16000)

http://master:16010/

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

    bin/hbase shell
    Hbase> list     // 查看表
    Hbase> status   // 查看集群状态
    Hbase> version  // 查看集群版本

启动后可查看zookeeper中对HBASE的节点监控内容:

    [zk: localhost:2181(CONNECTED) 13] ls /hbase
    [backup-masters, draining, flush-table-proc, hbaseid, master, meta-region-server, namespace, online-snapshot, recovering-regions, region-in-transition, replication, rs, running, splitWAL, table, table-lock]
    [zk: localhost:2181(CONNECTED) 13] ls /hbase/backup-masters
    [hdp-02,16000,1586781803612]
    [zk: localhost:2181(CONNECTED) 14] get /hbase/backup-masters/hdp-02
    org.apache.zookeeper.KeeperException$NoNodeException: KeeperErrorCode = NoNode for /hbase/backup-masters/hdp-02

HBASE表模型

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

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

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

hbase表模型的要点:

1、一个表,有表名

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

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

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

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

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

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

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

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

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

hbase中只支持byte[]  hbase不负责为客户端维护数据类型

此处的byte[] 包括了:rowkey,key,value,列族名,表名

HBASE表的物理存储结构

hbase整体工作机制示意图

hbase命令行客户端操作

namespace(相当于RDBMS里的database,对table进行分组)

    list_namespace  #查看所有namespace 相当于show databases
      default、hbase 2个内置namespace .
      hbase:用来存放系统相关的一些元数据等,相当于mysql中的mysql数据库
      建表时未指定namespace的表放在 default namespace中
    create_namespace "test" #创建新的namespace{可添加一些说明}
    create_namespace "test002", {"author"=>"CC11001100", "create_time"=>"2018-11-4 17:51:53"}
    describe_namespace "test002"" #查看说明
    alter_namespace "test002", {METHOD=>"set", "author"=>"ChenEr"}  #修改说明
    drop_namespace "test002"  #删除namespace(必须为空)
    create "test:user", "userInfo" #创建表时, "test:user" 表名前:指定namespace名
    list_namespace_tables "test" #查看namespace下都有哪些表

1.建表:

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

 表名      列族名   列族名

2.插入数据:

    hbase(main):011:0> put 't_user_info','001','base_info:username','zhangsan'
    0 row(s) in 0.2420 seconds

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     
         

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

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

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重要特性--排序特性(行键)

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

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

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

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

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

查询某个省的所有用户

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

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

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

HBASE客户端API操作

1.DDL操作


  /**
   * Hbase java 客户端API  (DDL)
   *  1、构建连接
   *  2、从连接中取到一个表DDL操作工具admin
   *  3、admin.createTable(表描述对象);
   *  4、admin.disableTable(表名);
    5、admin.deleteTable(表名);
    6、admin.modifyTable(表名,表描述对象);  
   */
​
​
  public class HbaseClientDDL {
    Connection conn = null;
    /**
     * 构建一个HBASE连接
     */
    @Before
    public void getConn() throws Exception{
      // 构建一个HBaseConfiguration链接对象,默认加载hbase-site.xml
      Configuration conf = HBaseConfiguration.create();
      // 增加zookeeper配置
      conf.set("hbase.zookeeper.quorum", "hdp-01:2181,hdp-02:2181,hdp-03:2181");
      conn = ConnectionFactory.createConnection(conf);
    }
    
    /**
     * 建表
     */
    @Test
    public void testCreateTable() throws Exception{
      // 从链接中构造一个DDL操作器
      Admin admin = conn.getAdmin();
      // 创建表定义描述对象
      HTableDescriptor hTableDescriptor = new HTableDescriptor(TableName.valueOf("user_info"));
      // 创建列族定义描述对象
      HColumnDescriptor hColumnDescriptor1 = new HColumnDescriptor("base_info");
      HColumnDescriptor hColumnDescriptor2 = new HColumnDescriptor("extra_info");
      // 设置该列族中存放数据的最大版本数,默认为1
      hColumnDescriptor1.setMaxVersions(3);
      hColumnDescriptor2.setMaxVersions(3);
      // 列族定义信息对象 放入 表定义对象中
      hTableDescriptor.addFamily(hColumnDescriptor1);
      hTableDescriptor.addFamily(hColumnDescriptor2);
      // 使用ddl操作器对象  创建表
      admin.createTable(hTableDescriptor);
      // 关闭连接
      admin.close();
      conn.close();
    }
    
    /**
     * 删除表
     */
    @Test
    public void testDropTable() throws Exception{
      Admin admin = conn.getAdmin();
      // 停用表  HBASE删除表,必须先停用
      admin.disableTable(TableName.valueOf("user_info"));
      // 删除表
      admin.deleteTable(TableName.valueOf("user_info"));
      admin.close();
      conn.close();
    }
    
    /**
     * 修改表
     */
    @Test
    public void testAlterTable() throws Exception{
      Admin admin = conn.getAdmin();
      // 获取 表描述对象
      HTableDescriptor tableDescriptor = admin.getTableDescriptor(TableName.valueOf("user_info"));
      System.out.println(tableDescriptor.toString());
      // 创建新的列族定义对象
      HColumnDescriptor hColumnDescriptor = new HColumnDescriptor("other_info");
      // 设置该列族的布隆过滤器类型
      hColumnDescriptor.setBloomFilterType(BloomType.ROWCOL);
      // 列族定义添加到表定义对象中
      tableDescriptor.addFamily(hColumnDescriptor);
      // 修改过的表定义对象 提交给ddl操作器执行Alter操作
      admin.modifyTable(TableName.valueOf("user_info"), tableDescriptor);
      // 查看当前表的列族信息
      for (HColumnDescriptor hCol : tableDescriptor.getColumnFamilies()) {
        System.out.println(hCol.getNameAsString());
      }
      admin.close();
      conn.close();
    }
  }

2.DML操作


  /**
   *  Hbase客户端API (DML 增删改查)
   */
  public class HbaseClientDML {
    Connection conn = null;
    /**
     * 构建一个HBASE连接
     */
    @Before
    public void getConn() throws Exception{
      // 构建一个HBaseConfiguration链接对象,默认加载hbase-site.xml
      Configuration conf = HBaseConfiguration.create();
      // 增加zookeeper配置
      conf.set("hbase.zookeeper.quorum", "hdp-01:2181,hdp-02:2181,hdp-03:2181");
      conn = ConnectionFactory.createConnection(conf);
    }
    
    /**
     * 增:put  改:put(同rowkey数据覆盖)
     * @throws Exception 
     */
    @Test
    public void testPut() throws Exception{
      // 通过Hbase链接获取表描述对象,进行DML操作
      Table table = conn.getTable(TableName.valueOf("user_info"));
      // 构造一个Put对象类型,存放数据,最后插入表中.(一个put对象只能对应一个rowkey).
      // HbaseJava客户端封装的api都比较底层,数据存入时,都是直接传入的二进制byte. 
      //Put put = new Put("001".getBytes()); 
      // 以下使用了hbase工具库实现二进制,效果一致
      Put put = new Put(Bytes.toBytes("001"));
      put.addColumn(Bytes.toBytes("base_info"), Bytes.toBytes("name"), Bytes.toBytes("张三"));
      put.addColumn(Bytes.toBytes("base_info"), Bytes.toBytes("age"), Bytes.toBytes("18"));
      put.addColumn(Bytes.toBytes("extra_info"), Bytes.toBytes("adrr"), Bytes.toBytes("北京"));
      Put put2 = new Put(Bytes.toBytes("002"));
      put2.addColumn(Bytes.toBytes("base_info"), Bytes.toBytes("name"), Bytes.toBytes("李四"));
      put2.addColumn(Bytes.toBytes("base_info"), Bytes.toBytes("age"), Bytes.toBytes("28"));
      put2.addColumn(Bytes.toBytes("base_info"), Bytes.toBytes("sex"), Bytes.toBytes("male"));
      put2.addColumn(Bytes.toBytes("extra_info"), Bytes.toBytes("adrr"), Bytes.toBytes("北京"));
      
      ArrayList<Put> puts = new ArrayList<>();
      puts.add(put);
      puts.add(put2);
      // 数据put:可以单个put,也可以put Put对象list
      table.put(puts);
      table.close();
      conn.close();
    }
    
    /**
     * 删
     * @throws Exception 
     */
    @Test
    public void testDelete() throws Exception{
      // 通过Hbase链接获取表描述对象,进行DML操作
      Table table = conn.getTable(TableName.valueOf("user_info"));
      // 创建Delete对象,封装要删除的数据  (用rowkey识别)
      Delete delete = new Delete(Bytes.toBytes("001"));
      // Delete对象不增加其他数据列,则删除整个数据,若设置其他列,则删除该列kv
      Delete delete2 = new Delete(Bytes.toBytes("002"));
      delete2.addColumn(Bytes.toBytes("base_info"), Bytes.toBytes("sex"));
      
      ArrayList<Delete> deletes = new ArrayList<>();
      deletes.add(delete);
      deletes.add(delete2);
      
      table.delete(deletes);
      table.close();
      conn.close();
    }
    
    /**
     * 查询
     * @throws Exception
     */
    @Test
    public void testGet() throws Exception{
      // 通过Hbase链接获取表描述对象,进行DML操作
      Table table = conn.getTable(TableName.valueOf("user_info"));
      Get get = new Get(Bytes.toBytes("002"));
      Result result = table.get(get);
      byte[] value = result.getValue(Bytes.toBytes("base_info"), Bytes.toBytes("name"));
      System.out.println(new String(value));
      byte[] row = result.getRow();
      System.out.println(new String(row));
      
      CellScanner cellScanner = result.cellScanner();
      while(cellScanner.advance()){
        Cell cell = cellScanner.current();
        byte[] rowArray = cell.getRowArray();// 行键字节数组
        byte[] familyArray = cell.getFamilyArray(); // 列族字节数组
        byte[] qualifierArray = cell.getQualifierArray(); // 列名字节数组
        byte[] valueArray = cell.getValueArray(); // value字节数组
        
        String rowkey = new String(rowArray,cell.getRowOffset(),cell.getRowLength());
        String familykey = new String(familyArray,cell.getFamilyOffset(),cell.getFamilyLength());
        String qualifierkey = new String(qualifierArray,cell.getQualifierOffset(),cell.getQualifierLength());
        String valueval = new String(valueArray,cell.getValueOffset(),cell.getValueLength());
        
        System.out.println("rowkey:"+rowkey+","+"familykey:"+familykey+","+"qualifierkey:"+qualifierkey+","+"valueval:"+valueval);
      }
    }
    
    /**
     * 按rowkey范围查询数据
     * @throws Exception 
     */
    @Test
    public void getScan() throws Exception{
      Table table = conn.getTable(TableName.valueOf("user_info"));
      Scan scan = new Scan(Bytes.toBytes("000"),Bytes.toBytes("100"));
      ResultScanner scanner = table.getScanner(scan);
      Iterator<Result> iterator = scanner.iterator();
      while(iterator.hasNext()){
        Result res = iterator.next();
        while(res.advance()){
          Cell cell = res.current();
          byte[] rowArray = cell.getRowArray();// 行键字节数组
          byte[] familyArray = cell.getFamilyArray(); // 列族字节数组
          byte[] qualifierArray = cell.getQualifierArray(); // 列名字节数组
          byte[] valueArray = cell.getValueArray(); // value字节数组
          
          String rowkey = new String(rowArray,cell.getRowOffset(),cell.getRowLength());
          String familykey = new String(familyArray,cell.getFamilyOffset(),cell.getFamilyLength());
          String qualifierkey = new String(qualifierArray,cell.getQualifierOffset(),cell.getQualifierLength());
          String valueval = new String(valueArray,cell.getValueOffset(),cell.getValueLength());
          
          System.out.println("rowkey:"+rowkey+","+"familykey:"+familykey+","+"qualifierkey:"+qualifierkey+","+"valueval:"+valueval);
        }
      }
    }
  }  

(以下内容属于Hbase高级,很重要但暂时没有相关资料待补充...)

批量数据如何快速导入HBASE

bulkloader

HBASE的性能调优

MAPREDUCE分析HBASE中的数据

HBASE中的数据建索引

HBASE的过滤查询

二级索引创建

自己建(协处理器)

Solr(可以直接跟HBASE整合做全文检索)

elastic search(也可以跟HBASE整合做二级索引)

布隆过滤器思想示意图

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值