Hbase详细笔记四[JAVA-API] (附带讲解视频)

1 创建Maven项目

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.example</groupId>
    <artifactId>doit15-hbase</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.6</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-client</artifactId>
            <version>2.0.4</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>2.7.7</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>2.7.7</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-server</artifactId>
            <version>2.0.4</version>
        </dependency>
        <!-- 使用mr程序操作hbase 数据的导入 -->
        <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-mapreduce</artifactId>
            <version>2.0.4</version>
        </dependency>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.5</version>
        </dependency>
        <!-- phoenix 凤凰 用来整合Hbase的工具 -->
        <dependency>
            <groupId>org.apache.phoenix</groupId>
            <artifactId>phoenix-core</artifactId>
            <version>5.0.0-HBase-2.0</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.6</version>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <!-- bind to the packaging phase -->
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

        </plugins>
    </build>
</project>

2 java-API 

2.1 客户端连接核心对象

hbase的java客户端连接hbase的时候只需要连接zookeeper集群即可找到Hbase集群的位置

核心对象如下:

  1.   Configuration  : HBaseConfiguration.create();
  2.   Connection     : ConnectionFactory.createConnection(conf);
  3.   Table               : conn.getTable(TableName.valueOf("tb_b"));  可以对表操作  DML
  4.    Admin            : conn.getAdmin();  操作hbase系统   DDL  名称空间 tools ...
package com._51doit.client;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Admin;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.client.Table;

import java.io.IOException;

/**
 * @Auther: 多易教育-行哥
 * OBJECT:
 *   1  Configuration  : HBaseConfiguration.create();
 *   2  Connection     : ConnectionFactory.createConnection(conf);
 *   3  Table          : conn.getTable(TableName.valueOf("tb_b"));  可以对表操作  DML
 *   4  Admin          : conn.getAdmin();  操作hbase系统   DDL  名称空间 tools ...
 *
 * @Date: 2020/6/12
 * @Description:获取连接hbase的客户端对象
 */
public class ConnectionDemo {
    public static void main(String[] args) throws Exception {
        // 直接连接ZK集群 就能找到对应的Hbase集群
        // 1 创建一个配置信息的对象
        Configuration conf = HBaseConfiguration.create();
       // 2  设置配置存储   设置ZK集群的位置
        conf.set("hbase.zookeeper.quorum" , "linux01:2181,linux02:2181,linux03:2181");
        //3 创建连接对象
        Connection conn = ConnectionFactory.createConnection(conf);
        /**
         * conn.getTable()  --> Table对象 可以对表操作  DML
         *  Admin admin = conn.getAdmin() 获取管理对象    操作hbase系统   DDL  名称空间 tools ...
         */
        Table tb_b = conn.getTable(TableName.valueOf("tb_b"));
        // 获取管理对象
        Admin admin = conn.getAdmin();
        // 获取系统中所有的用户自定义的表   Hbase中对表的抽象  TableName
        TableName[] tableNames = admin.listTableNames() ;
        // 变量表
        for (TableName tableName : tableNames) {
            // 获取表的名称  字节数组
            byte[] name = tableName.getName();
            // 打印
            System.out.println(new String(name));
        }

        // 释放对象
        conn.close();

    }
}

2.2 Java-API 名称空间

hbase中的namespace起到是是类似于mysql中数据库的作用

可以将表进行分类别管理 , 在HDFS系统中其实对应不同的文件夹

package com._51doit.client;

import com._51doit.utils.HbaseUtils;
import org.apache.hadoop.hbase.NamespaceDescriptor;
import org.apache.hadoop.hbase.client.Admin;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @Auther: 多易教育-行哥
 * @Date: 2020/6/12
 * @Description:
 * 1 创建一个名称空间               c   reateNamespace
 * 2 查看系统下所有的名称空间           listNamespaceDescriptors
 * 3 修改名称空间                     modifyNamespace
 * 4 删除                             deleteNamespace
 */
public class NameSpaceDemo {
    public static void main(String[] args) throws Exception {
        // 创建一个名称空间
        Admin admin = HbaseUtils.getHbaseAdmin();
        admin.deleteNamespace("doit");
        admin.close();
    }

    /**
     * 修改名称空间的属性
     * @param admin
     * @throws IOException
     */
    private static void changeNameSpace(Admin admin) throws IOException {
        NamespaceDescriptor.Builder doit = NamespaceDescriptor.create("doit");
        doit.removeConfiguration("author") ;
        doit.addConfiguration("author","JINLONG") ;
        NamespaceDescriptor build = doit.build();
        // 修改属性
        admin.modifyNamespace(build);
    }

    /**
     * 查看系统下所有的名称空间
     * 并且查看配置信息
     * @param admin
     * @throws IOException
     */
    private static void getAllNameSpaces(Admin admin) throws IOException {
        //查看系统下所有的名称空间
        NamespaceDescriptor[] namespaceDescriptors = admin.listNamespaceDescriptors();
        // 遍历
        for (NamespaceDescriptor namespaceDescriptor : namespaceDescriptors) {
            // 一个名称空间对象
            // 名字
            String name = namespaceDescriptor.getName();
            // 属性信息
            Map<String, String> map = namespaceDescriptor.getConfiguration();
            System.out.println(name+"--->"+map.entrySet());
        }
    }

    /**
     * 创建名称空间
     * @param admin
     * @throws IOException
     */
    private static void createNameSpace(Admin admin) throws IOException {
        // 获取名称空间的构建器
        NamespaceDescriptor.Builder doit = NamespaceDescriptor.create("doit");
        Map<String,String> map = new HashMap<>() ;
        map.put("author" , "DOIT") ;
        map.put("desc" ,"my first namespace...");
        // 对名称空间的属性设置
        doit.addConfiguration(map) ;
        //构造名称空间对象
        NamespaceDescriptor namespaceDescriptor = doit.build();
        // 调用方法  创建
        admin.createNamespace(namespaceDescriptor);
    }
}

2.3 Java-API 建表

Hbase在建表的时候指定表名和至少一个列族

/**
 * @Auther: 多易教育-行哥
 * @Date: 2020/6/12
 * @Description:
 * 1 建表 : 表名和列族是必须
 */
public class TableOperation {
    public static void main(String[] args) throws Exception {
        Admin admin = HbaseUtils.getHbaseAdmin();

        admin.close();
    }

    /**
     * 创建多个列族的表
     * @param admin
     * @throws IOException
     */
    private static void createTableWithMoreColumnFamilies(Admin admin) throws IOException {
        //表的构建器 表名   1
        TableDescriptorBuilder tableDescriptorBuilder = TableDescriptorBuilder.newBuilder(TableName.valueOf("tb_demo3"));
        //--------------列族一
        // 列族构建器
        ColumnFamilyDescriptorBuilder cf1 = ColumnFamilyDescriptorBuilder.newBuilder("cf1".getBytes());
        // 设置数据存储的版本的个数
        cf1.setMaxVersions(3) ;
        // 设置列族中数据的存储时间 单位秒
        cf1.setTimeToLive(240) ;
        // 列族的描述对象
        ColumnFamilyDescriptor columnFamilyDescriptor1 = cf1.build();
        //--------------列族二
        // 列族构建器
        ColumnFamilyDescriptorBuilder cf2 = ColumnFamilyDescriptorBuilder.newBuilder("cf2".getBytes());
        // 设置数据存储的版本的个数
        cf2.setMaxVersions(5) ;
        // 设置列族中数据的存储时间 单位秒
        cf2.setTimeToLive(300) ;
        // 列族的描述对象
        ColumnFamilyDescriptor columnFamilyDescriptor2 = cf2.build();
        // -------存储多个列族
        // 存储多个列族对象
        List<ColumnFamilyDescriptor> cfs = new ArrayList<>() ;
        cfs.add(columnFamilyDescriptor1) ;
        cfs.add(columnFamilyDescriptor2) ;

        // -------------------表中添加多个列族
        // 表的构建器 添加列族
        tableDescriptorBuilder.setColumnFamilies(cfs) ;

        //表描述对象
        TableDescriptor tableDescriptor = tableDescriptorBuilder.build();
        // 创建表
        admin.createTable(tableDescriptor);
    }

    /**
     * 创建一个列族的表
     * @param admin
     * @throws IOException
     */
    private static void createTableWithOnColumnFamily(Admin admin) throws IOException {
        //表的构建器 表名
        TableDescriptorBuilder tableDescriptorBuilder = TableDescriptorBuilder.newBuilder(TableName.valueOf("tb_demo2"));
        // 列族构建器
        ColumnFamilyDescriptorBuilder columnFamilyDescriptorBuilder = ColumnFamilyDescriptorBuilder.newBuilder("cf1".getBytes());
        // 设置数据存储的版本的个数
        columnFamilyDescriptorBuilder.setMaxVersions(3) ;
        // 设置列族中数据的存储时间 单位秒
        columnFamilyDescriptorBuilder.setTimeToLive(240) ;
        // 列族的描述对象
        ColumnFamilyDescriptor columnFamilyDescriptor = columnFamilyDescriptorBuilder.build();
        // 表中添加列族
        // 表的构建器 添加列族
        tableDescriptorBuilder.setColumnFamily(columnFamilyDescriptor) ;
        //表描述对象
        TableDescriptor tableDescriptor = tableDescriptorBuilder.build();
        // 创建表
        admin.createTable(tableDescriptor);
    }
}

2.3.1 预分region表

当创建表以后 .由于表中的数据量比较少所以表默认是一个region , 那么此时在短时间内有大量的插入请求就出现了插入性的热点问题!

我们可以在建表的时候指定多个region来避免这种现象

shell客户端操作

create "tb_spl1" , "cf1"  , SPLITS =>['e' , 'm' , 't']
Created table tb_spl1
Took 2.4596 seconds          

# 查看表是否进行了预分region操作
hbase(main):010:0> list_regions "tb_spl1"
                 SERVER_NAME |                                               REGION_NAME |  START_KEY |    END_KEY |  SIZE |   REQ |   LOCALITY |
 --------------------------- | --------------------------------------------------------- | ---------- | ---------- | ----- | ----- | ---------- |
 linux03,16020,1591783680511 |  tb_spl1,,1591824125893.63d4e1005eec815e2c6dd3f0b2762631. |            |          e |     0 |     0 |        0.0 |
 linux02,16020,1591783680684 | tb_spl1,e,1591824125893.cfcb6ece7a484e579feb863eb9d0e084. |          e |          m |     0 |     0 |        0.0 |
 linux01,16020,1591783680829 | tb_spl1,m,1591824125893.884c71c0cdca3f52674e39c99d374f38. |          m |          t |     0 |     0 |        0.0 |
 linux02,16020,1591783680684 | tb_spl1,t,1591824125893.3b7eceae97ef9450eee90ca962c4245d. |          t |            |     0 |     0 |        0.0 |
 4 rows
Took 0.0561 seconds   
## 查看拆分点key的位置     
hbase(main):012:0> locate_region "tb_spl1" , "e"
HOST                           REGION                                                                                
 linux02:16020                 {ENCODED => cfcb6ece7a484e579feb863eb9d0e084, NAME => 'tb_spl1,e,1591824125893.cfcb6ec
                               e7a484e579feb863eb9d0e084.', STARTKEY => 'e', ENDKEY => 'm'}                          
1 row(s)
Took 0.0026 seconds                                                                           

在页面上查看

JAVA-API

   public static void main(String[] args) throws Exception {
        Admin admin = HbaseUtils.getHbaseAdmin();
        // 表的描述器
        TableDescriptorBuilder tableDescriptorBuilder = TableDescriptorBuilder.newBuilder(TableName.valueOf("tb_spl2"));
        // 列族的描述器
        ColumnFamilyDescriptorBuilder cf = ColumnFamilyDescriptorBuilder.newBuilder("cf".getBytes());
        ColumnFamilyDescriptor cfobj = cf.build();
        // 添加到表中
        tableDescriptorBuilder.setColumnFamily(cfobj);
        TableDescriptor tableDescriptor = tableDescriptorBuilder.build();
        byte[][] keys = new byte[][]{"e".getBytes(), "m".getBytes(),"t".getBytes()} ;
        // 建表    指定预分region的key(数组)
        admin.createTable(tableDescriptor,keys);

        admin.close();
    }

2.4 Java-API  修改表结构

  1. admin.modifyTable(tableDescriptor); 参数是表对象 可以修改表的列族名 和列族属性 添加删除列族等
  2. admin.modifyColumnFamily(TableName.valueOf("tb_demo1"), cfobj);  仅仅可以修改表的某个列族的属性值
/**
     * 修改表结构
     * @param admin
     * @throws IOException
     */
    private static void modifyTableDemo(Admin admin) throws IOException {
        //   TableDescriptorBuilder tableDescriptorBuilder = TableDescriptorBuilder.newBuilder(TableName.valueOf("tb_demo1"));
        ColumnFamilyDescriptorBuilder cf = ColumnFamilyDescriptorBuilder.newBuilder("cf1".getBytes());
        // 仅修改某个列族的属性
        cf.setMaxVersions(5);
        ColumnFamilyDescriptor cfobj = cf.build();
        // 添加到表中
       /* tableDescriptorBuilder.setColumnFamily(cfobj);
        TableDescriptor tableDescriptor = tableDescriptorBuilder.build();
        // 添加列族  删除列族
        admin.modifyTable(tableDescriptor);
        */
        admin.modifyColumnFamily(TableName.valueOf("tb_demo1"), cfobj);
    }

2.5 Java-API  删除表 (禁用 是否禁用启用)

  1. 确定表存在
  2. 确定表被禁用
 /**
     * 删除表  先禁用
     * @param admin
     * @throws IOException
     */
    private static void deleteTable(Admin admin) throws IOException {
        TableName tn = TableName.valueOf("tb_demo1");
        // 如果表存在
        if(admin.tableExists(tn)){
            admin.disableTable(tn);
            if(admin.isTableDisabled(tn)){
                admin.deleteTable(tn);
            }else{
                System.out.println("请先禁用表");
            }
        }else {
            System.out.println("表不存在");
        }
    }

2.6 Java-API  插入更新数据 put

  1. put(Put)  插入一行数据
  2. put(List<Put>) 插入多行数据 
  3. 数据的插入必要的内容  表名 行建 列族:属性 值
 public static void main(String[] args) throws Exception {
        // 1 获取表对象  DML
        Table tb = HbaseUtils.getHbaseTable("tb_spl2");
        // tb.getDescriptor().getColumnFamilyNames();  // 获取所有的列族
        //2 Put对象 表  行  列族:属性  值
        // 参数  行建的值
       // Put put = new Put("rk001".getBytes());
        /**
         * 参数一 列族
         * 参数二 属性
         * 参数三 值
         */
     /*   put.addColumn("cf".getBytes(), "uid".getBytes(), "uid001".getBytes());
        put.addColumn("cf".getBytes(), "name".getBytes(), "LSS".getBytes());
        put.addColumn("cf".getBytes(), "gender".getBytes(), "M".getBytes());*/
        // 3  执行嘻插入
        // tb.put(put);  // rpc请求 一次插入一个属性
        List<Put> puts = new ArrayList<>();
        Put put1 = new Put("rk002".getBytes());
        Put put2 = new Put("rk003".getBytes());
        Put put3 = new Put("rk004".getBytes());
        put1.addColumn("cf".getBytes(), "uid".getBytes(), "uid002".getBytes());
        put1.addColumn("cf".getBytes(), "name".getBytes(), "ZSS".getBytes());

        put2.addColumn("cf".getBytes(), "age".getBytes(), "23".getBytes());

        put3.addColumn("cf".getBytes(), "addres".getBytes(), "Beijing".getBytes());
        put3.addColumn("cf".getBytes(), "name".getBytes(), "gunayu".getBytes());

        puts.add(put1);
        puts.add(put2);
        puts.add(put3);

        tb.put(puts);

        // 4 释放资源
        tb.close();

    }

2.6 Java-API 获取数据-get()

  1. get数据
  2. 可以获取一行
  3. 可以获取多行数据List<Get>
  4. 可以获取列族
  5. 可以获取列族中的属性
 /**
     * 获取多行数据
     * @param tb
     * @throws IOException
     */
    private static void getData(Table tb) throws IOException {
        Get get1 = new Get("rk001".getBytes()) ;
        Get get2 = new Get("rk002".getBytes()) ;
        Get get3 = new Get("rk003".getBytes()) ;
        // 指定获取数据的  哪个列族的哪个属性
        get1.addColumn("cf".getBytes(),"name".getBytes());
        // 指定获取哪个列族的数据
        get1.addFamily("cf1".getBytes());

        List<Get> list =  new ArrayList<>() ;
        // 将多个get存储在集合中
        list.add(get1) ;
        list.add(get2) ;
        list.add(get3) ;
        // 查询多行数据 返回每行组成的数组
        Result[] results = tb.get(list);
        // 遍历=数组 获取每行数据
        for (Result result : results) {
          HbaseUtils.showData(result);
        }
    }

    /**
     * 获取一行数据
     * @param tb
     * @throws IOException
     */
    private static void getOneRowData(Table tb) throws IOException {
        // get对象 代表一行数据  (所有的列族 属性)
        Get get =  new Get("rk001".getBytes()) ;
        // 一行结果数据  有很多单元格  单元格的个数不确定  稀疏性
        Result result = tb.get(get);
        while(result.advance()){ // 只要有下一个单元格进入循环
            // 获取当前的单元格对象
            Cell cell = result.current();
         /*   cell.getFamilyArray() ;//列族
            cell.getQualifierArray() ;// 属性
            cell.getValueArray() ; // 值*/
            byte[] r = CellUtil.cloneRow(cell);  // 行
            byte[] family = CellUtil.cloneFamily(cell); // 列族
            byte[] qualifier = CellUtil.cloneQualifier(cell); // 属性
            byte[] value = CellUtil.cloneValue(cell); // 值
            System.out.println(" 行: "+new String(r)+" 列族: "+new String(family)+" 属性:  "+new String(qualifier)+" 值: "+new String(value));
        }
    }

封装一个展示数据内容的工具类

 /**
     * 展示单元格数据
     * @param result
     */
    public  static  void showData(Result result){
        while(result.advance()){
            Cell cell = result.current();
            String row = new String(CellUtil.cloneRow(cell));
            String family = new String(CellUtil.cloneFamily(cell));
            String qualifier = new String(CellUtil.cloneQualifier(cell));
            String value = new String(CellUtil.cloneValue(cell));
            System.out.println(row+"->"+family+":"+qualifier+"->"+value);
        }

    }

2.7 Java-API 获取数据-scan()

  1. 全表扫描数据
  2. 可以指定扫描范围  scan.withStartRow("rk002".getBytes()) ;// 起始行  包括    scan.withStopRow("rk004".getBytes()); // 结束行不包含
  3. 可以指定扫面某个列族
  4. 可以指定扫描某个列族的属性
 /**
     * 扫面数据
     * @param tb
     * @throws IOException
     */
    private static void scanData(Table tb) throws IOException {
        Scan scan = new Scan();// 扫描对象
        scan.withStartRow("rk002".getBytes()) ;// 起始行  包括
        scan.withStopRow("rk004".getBytes()); // 结束行不包含
        ResultScanner scanner = tb.getScanner(scan);
        Iterator<Result> iterator = scanner.iterator();
        while (iterator.hasNext()){
            Result result = iterator.next();
            HbaseUtils.showData(result);
        }
    }

2.8 Java-API 删除数据 delete

  1. 可以删除一行 
  2. 删除一行的列族
  3. 删除某一行的列族的属性
  4. 可以删除多行数据  List<Delete>
public static void main(String[] args) throws Exception {
        Table tb = HbaseUtils.getHbaseTable("tb_gy");
        // 获取删除对象  指定行
        Delete delete = new Delete(Bytes.toBytes("sb001"));
        //设置参数  删除某个属性
        delete.addFamily(Bytes.toBytes("cf1"));
      /*  delete.addColumn();
        delete.addColumn();*/
        // 没有进行任何的参数设置  删除整行数据
        tb.delete(delete);

        tb.close();
    }

猜你喜欢

转载自blog.csdn.net/qq_37933018/article/details/106710506