• HBASE API 操作


    1. IDEA 连接 HBASE

    1、idea 创建一个 maven 项目

    2、添加相关依赖(HBASE 客户端(最主要)、服务端),pom.xml

    <dependencies>
        <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-server</artifactId>
            <version>1.2.6</version>
        </dependency>
    
        <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-client</artifactId>
            <version>1.2.6</version>
        </dependency>
    </dependencies>
    

    3、在 resources 中添加 core-site.xml、hbase-site.xml

    4、修改本机的 hosts 文件(在C:WindowsSystem32driversetc下),添加集群的 IP 名称:

    192.168.131.137 hadoop1
    192.168.131.138 hadoop2
    192.168.131.139 hadoop3
    

    注意:此步骤不添加,有可能会导致 idea 执行不成功!

    项目结构:

    F:.
    │  pom.xml
    ├─src
    │  ├─main
    │  │  ├─java
    │  │  │  └─com
    │  │  │      └─jun
    │  │  │          └─test
    │  │  │                  TestApi.java
    │  │  │
    │  │  └─resources
    │  │          core-site.xml
    │  │          hbase-site.xml
    │  │
    │  └─test
    │      └─java
    └─target
        │  test_one.jar
        │
        ├─classes
        │  │  core-site.xml
        │  │  hbase-site.xml
        │  │
        │  └─com
        │      └─jun
        │          └─test
        │                  TestApi.class
    

    参考文章:在本地用idea连接虚拟机上的hbase集群的实现代码

    2. DDL 表操作

    DDL 与表操作有关,比如:

    • 判断表是否存在
    • 创建、删除、修改表
    • 创建命名空间

    2.1 配置连接

    package com.jun.test;
    
    import org.apache.hadoop.conf.Configuration;
    import org.apache.hadoop.hbase.*;
    import org.apache.hadoop.hbase.client.Admin;
    import org.apache.hadoop.hbase.client.Connection;
    import org.apache.hadoop.hbase.client.ConnectionFactory;
    
    import java.io.IOException;
    
    public class TestApi {
        public static Connection connection = null;
        public static Admin admin = null;
    
        static {
            try {
                // 获取配置信息
                Configuration configuration = HBaseConfiguration.create();
                configuration.set("hbase.zookeeper.quorum", "hadoop1,hadoop2,hadoop3");
    
                // 创建连接对象
                connection = ConnectionFactory.createConnection(configuration);
    
                // 创建 admin 对象
                admin = connection.getAdmin();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        // 关闭连接
        public static void close() {
            if (admin != null) {
                try {
                    admin.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
    
            if (connection != null) {
                try {
                    connection.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        public static void main(String[] args) throws IOException {
            // 判断表是否存在
    //        System.out.println(isTableExists("t1"));
    
            // 创建表
    //        createTable("t2", "info");
    
            // 将表创建到命名空间中
    //        createTable("0808:t2", "info");
    
            // 删除表
    //        deleteTable("t2");
    
            // 创建命名空间
    //        createNameSpace("0808");
    
            // 关闭资源
            close();
        }
    }
    

    2.2 判断表是否存在

    // 判断表是否存在
    public static boolean isTableExists(String tableName) throws IOException {
        boolean exists = admin.tableExists(TableName.valueOf(tableName));
        return exists;
    }
    

    2.3 创建表

    创建表包括:添加列族信息、还可以将表添加到命名空间,创建之前可以先检查该表是否存在:

    // 创建表
    public static void createTable(String tableName, String... cfs) throws IOException {
        // 判断列族信息
        if (cfs.length <= 0) {
            System.out.println("请设置列族信息!!!");
            return;
        }
    
        // 判断表是否存在
        if (isTableExists(tableName)) {
            System.out.println(tableName + " 表已存在!!!");
            return;
        }
    
        // 创建表描述器对象
        HTableDescriptor descriptor = new HTableDescriptor(TableName.valueOf(tableName));
    
        // 循环添加列族
        for (String cf : cfs) {
            descriptor.addFamily(new HColumnDescriptor(cf));
        }
    
        // 创建表
        admin.createTable(descriptor);
        System.out.println("表 " + tableName + " 创建成功!!!");
    }
    

    2.4 删除表

    // 删除表
    public static void deleteTable(String tableName) throws IOException {
        if (isTableExists(tableName)) {
            admin.disableTable(TableName.valueOf(tableName));   // 先停用表,再删除
            admin.deleteTable(TableName.valueOf(tableName));
            System.out.println("表 " + tableName + " 删除成功!!!");
        } else {
            System.out.println("表 " + tableName + " 不存在!!!");
        }
    }
    

    2.5 创建命名空间

    // 创建命名空间
    public static void createNameSpace(String ns) {
        // 创建命名空间描述器
        NamespaceDescriptor namespaceDescriptor = NamespaceDescriptor.create(ns).build();
    
        // 创建命名空间
        try {
            admin.createNamespace(namespaceDescriptor);
            System.out.println(ns + "命名空间创建成功!!!");
        } catch (NamespaceExistException e) {
            System.out.println("命名空间 " + ns + " 已存在!!!");
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    
    }
    

    可以在 hbase shell 中使用 list_namespace 查看命名空间:

    hbase(main):012:0> list_namespace
    NAMESPACE                                                                                 0808                                                                                     default                                                                                   hbase                                                                                                                                
    3 row(s) in 0.0420 seconds
        
    // t2 表在 0808 命名空间里
    hbase(main):014:0> list
    TABLE                                                                                     0808:t2                                                                                   t1                                                                                                                                   
    2 row(s) in 0.0430 seconds
    
    => ["0808:t2", "t1"]
    

    3. DML 表记录操作

    DML主要是针对表的记录的操作,如插入、删除记录、查询记录等

    3.1 插入数据

    插入单条数据

     // 插入数据
    public static void putData(String tableName, String rowKey, String cf, String cn, String value) throws IOException {
        // 获取表对象
        Table table = connection.getTable(TableName.valueOf(tableName));
    
        // 获取 Put 对象
        Put put = new Put(Bytes.toBytes(rowKey));
    
        // 给 put 对象赋值
        put.addColumn(Bytes.toBytes(cf), Bytes.toBytes(cn), Bytes.toBytes(value));
    
        // 插入数据
        table.put(put);
    
        System.out.println("数据插入成功!!!");
    
        // 关闭表连接
        table.close();
    }
    

    测试:

    // 插入数据
    putData("t2", "10001", "info", "name", "rose");
    

    插入多条数据

    使用集合:

    public static byte[] getBytes(String value) {
        return Bytes.toBytes(value);
    }
    
    // 插入多条数据
    public static void putManyData(String tableName, String cf, String cn, String value) throws IOException {
        Table table = connection.getTable(TableName.valueOf(tableName));
    
        // 定义一个集合
        List<Put> puts = new ArrayList<>();
        int row_key = 10001;
    
        for (int i = 1; i <= 5; i++) {
            row_key = row_key + i;
            Put put = new Put(getBytes(String.valueOf(row_key)));
            put.addColumn(getBytes(cf), getBytes(cn + i), getBytes(value + i));
            puts.add(put);
        }
        table.put(puts);
        System.out.println("成功插入多行数据!");
        table.close();
    }
    

    测试:

    // 插入多条数据
    putManyData("t2", "info", "alias", "jun");
    
    // scan t2
    hbase(main):005:0> scan 't2'
    ROW                            COLUMN+CELL                                                                          
    10001                         column=info:name, timestamp=1628369721705, value=rose     10002                         column=info:alias1, timestamp=1628383262854, value=jun1     10004                         column=info:alias2, timestamp=1628383262854, value=jun2     10007                         column=info:alias3, timestamp=1628383262854, value=jun3     10011                         column=info:alias4, timestamp=1628383262854, value=jun4     10016                         column=info:alias5, timestamp=1628383262854, value=jun5                              
    6 row(s) in 0.0860 seconds
    

    3.2 get 数据

    获取某行数据

    // get 单条数据
    public static void getData(String tableName, String rowKey) throws IOException {
        Table table = connection.getTable(TableName.valueOf(tableName));
    
        Get get = new Get((Bytes.toBytes(rowKey)));
    
        // 获取最大版本数
        System.out.println(get.getMaxVersions());
        //        System.out.println(get.setTimeStamp());
    
        // 获取整行数据
        Result result = table.get(get);
        for (Cell cell : result.rawCells()) {
            System.out.println("行键: " + Bytes.toString(result.getRow()));
            System.out.println("列族: " + Bytes.toString(CellUtil.cloneFamily(cell)));
            System.out.println("列: " + Bytes.toString(CellUtil.cloneQualifier(cell)));
            System.out.println("值: " + Bytes.toString(CellUtil.cloneValue(cell)));
            System.out.println("时间戳: " + cell.getTimestamp());
    
        }
        table.close();
    }
    

    测试数据:

    // 获取数据
    getData("t2", "10001");
    
    1
    行键: 10001
    列族: info
    列: name
    值: rose
    时间戳: 1628369721705
    

    指定列族、列名

    // 指定列族
    get.addFamily(Bytes.toBytes(cf));
    
    // 指定列名
    get.addColumn(Bytes.toBytes(cn));
    

    3.3 scan 数据

    // scan 所有数据
    public static void scanData(String tableName) throws IOException {
        Table table = connection.getTable(TableName.valueOf(tableName));
    
        Scan scan = new Scan();
        ResultScanner resultScanner = table.getScanner(scan);
        for (Result result : resultScanner) {
            Cell[] cells = result.rawCells();
            for (Cell cell : cells) {
                System.out.println("行键: " + Bytes.toString(result.getRow()));
                System.out.println("列族: " + Bytes.toString(CellUtil.cloneFamily(cell)));
                System.out.println("列: " + Bytes.toString(CellUtil.cloneQualifier(cell)));
                System.out.println("值: " + Bytes.toString(CellUtil.cloneValue(cell)));
                System.out.println("时间戳: " + cell.getTimestamp());
                System.out.println("-------------------------------------------
    
    ");
            }
        }
    	table.close();
    }
    

    测试数据:

    // 扫描所有数据
    scanData("t2");
    
    行键: 10001
    列族: info
    列: name
    值: rose
    时间戳: 1628369721705
    -------------------------------------------
    
    
    行键: 10002
    列族: info
    列: alias1
    值: jun1
    时间戳: 1628383262854
    -------------------------------------------
    
    
    行键: 10004
    列族: info
    列: alias2
    值: jun2
    时间戳: 1628383262854
    -------------------------------------------
    
    
    行键: 10007
    列族: info
    列: alias3
    值: jun3
    时间戳: 1628383262854
    -------------------------------------------
    
    
    行键: 10011
    列族: info
    列: alias4
    值: jun4
    时间戳: 1628383262854
    -------------------------------------------
    
    
    行键: 10016
    列族: info
    列: alias5
    值: jun5
    时间戳: 1628383262854
    -------------------------------------------
    

    建议

    使用 scan 扫描全表时,最好设置 startRow、endRow,亦或者是带过滤条件的翻页,而非全表扫描:

    // 设置 startRow
    Scan(Bytes.toBytes("startRow"))
      
    // 设置 startRow、endRow
    Scan(Bytes.toBytes("startRow"), Bytes.toBytes("endRow"))
        
    // 实际工作中一般不知道 endRow,而是带过滤条件的翻页
    Scan(Bytes.toBytes("startRow"), Filter filter)
        
    ResultScanner resultScanner = table.getScanner(scan);
    

    3.4 删除数据

    删除单行数据

    // 删除单行数据
    public static void deleteData(String tableName, String rowKey) throws IOException {
        Table table = connection.getTable(TableName.valueOf(tableName));
    
        // 获取 delete 对象
        Delete delete = new Delete(Bytes.toBytes(rowKey));
    
        // 删除指定的列族、列名
        //        delete.addColumn(Bytes.toBytes(cf), Bytes.toBytes(cn));
    
        table.delete(delete);
        System.out.println(rowKey + " 删除成功!!!");
        table.close();
    }
    

    测试:

    // 删除单行数据
    deleteData("t2", "10001");
    
    hbase(main):007:0> scan 't2'
    ROW                                COLUMN+CELL                                                                                       
     10002                             column=info:alias1, timestamp=1628383262854, value=jun1                                           
     10004                             column=info:alias2, timestamp=1628383262854, value=jun2                                           
     10007                             column=info:alias3, timestamp=1628383262854, value=jun3                                           
     10011                             column=info:alias4, timestamp=1628383262854, value=jun4                                           
     10016                             column=info:alias5, timestamp=1628383262854, value=jun5                                           
    5 row(s) in 0.1290 seconds
    

    删除多行数据

    // 删除多行数据
    public static void deleteManyData(String tableName, String... rows) throws IOException {
        Table table = connection.getTable(TableName.valueOf(tableName));
    
        List<Delete> deletes = new ArrayList<>();
    
        for (String row : rows) {
            Delete delete = new Delete(Bytes.toBytes(row));
            deletes.add(delete);
        }
    
        table.delete(deletes);
        System.out.println("删除成功!!!");
        table.close();
    }
    

    测试:

    // 删除多行数据
    deleteManyData("t2", "10002", "10007");
    
    hbase(main):008:0> scan 't2'
    ROW                                COLUMN+CELL                                                                                       
     10004                             column=info:alias2, timestamp=1628383262854, value=jun2                                           
     10011                             column=info:alias4, timestamp=1628383262854, value=jun4                                           
     10016                             column=info:alias5, timestamp=1628383262854, value=jun5                                           
    3 row(s) in 0.1140 seconds
    

    4. 过滤器

    要完成一个过滤的操作,至少需要两个参数。一个是抽象的操作符,Hbase 提供了枚举类型的变量来表示这些抽象的操作符:LESS/LESS_OR_EQUAL/EQUAL/NOT_EUQAL等;另外一个就是具体的比较器(Comparator),代表具体的比较逻辑,如果可以提高字节级的比较、字符串级的比较等。有了这两个参数,我们就可以清晰的定义筛选的条件,过滤数据。

    抽象操作符(比较运算符)

    LESS <
    LESS_OR_EQUAL <=
    EQUAL =
    NOT_EQUAL <>
    GREATER_OR_EQUAL >=
    GREATER >
    NO_OP 排除所有
    

    比较器(指定比较机制)

    BinaryComparator 按字节索引顺序比较指定字节数组,采用 Bytes.compareTo(byte[])
    
    BinaryPrefixComparator 跟前面相同,只是比较左端的数据是否相同
    
    NullComparator 判断给定的是否为空
    
    BitComparator 按位比较
    
    RegexStringComparator 提供一个正则的比较器,仅支持 EQUAL 和非 EQUAL
    
    SubstringComparator 判断提供的子串是否出现在 value 中
    

    4.1 行键过滤器

    过滤出 rowkey 大于 10004 的数据:

    // 过滤器
    public static void scanFilterData(String tableName) throws IOException {
        Table table = connection.getTable(TableName.valueOf(tableName));
    
        // GREATER 大于、 BinaryComparator 按字节索引顺序比较指定字节数组
        Filter rowFilter = new RowFilter(CompareFilter.CompareOp.GREATER, new BinaryComparator("10004".getBytes()));
        Scan scan = new Scan();
        scan.setFilter(rowFilter);
    
        ResultScanner resultScanner = table.getScanner(scan);
        for (Result result: resultScanner) {
            Cell[] cells = result.rawCells();
            for (Cell cell: cells) {
                System.out.println("行键: " + Bytes.toString(result.getRow()));
                System.out.println("列族: " + Bytes.toString(CellUtil.cloneFamily(cell)));
                System.out.println("列: " + Bytes.toString(CellUtil.cloneQualifier(cell)));
                System.out.println("值: " + Bytes.toString(CellUtil.cloneValue(cell)));
    
            }
        }
        table.close();
    }
    

    测试:

    // t2 表中所有数据
    hbase(main):008:0> scan 't2'
    ROW                                COLUMN+CELL                                                                                       
    10004                             column=info:alias2, timestamp=1628383262854, value=jun2                                           
    10011                             column=info:alias4, timestamp=1628383262854, value=jun4                                           
    10016                             column=info:alias5, timestamp=1628383262854, value=jun5                                           
    3 row(s) in 0.1140 seconds
    
    // 过滤器
    scanFilterData("t2");
    
    行键: 10011
    列族: info
    列: alias4
    值: jun4
    
    行键: 10016
    列族: info
    列: alias5
    值: jun5
    

    5. 参考文章

  • 相关阅读:
    Heritrix源码分析(十) Heritrix中的Http Status Code(Http状态码)(转)
    Heritrix源码分析(九) Heritrix的二次抓取以及如何让Heritrix抓取你不想抓取的URL
    Heritrix源码分析(八) Heritrix8个处理器(Processor)介绍(转)
    HTML 的 iframe 元素
    CSS 选择器及其优先级
    在触屏设备中拖动 overflow 元素
    关于博客园博问标签的自我实现
    ABAP中读取EXCEL中不同的SHEET数据
    创建表索引
    Call Transaction
  • 原文地址:https://www.cnblogs.com/midworld/p/15116690.html
Copyright © 2020-2023  润新知