• 【HBASE】Hbase的Shell操作



    任务

    1. 搭建分布式HBASE集群
    2. 学会使用基本的shell命令,完成数据增删改查的操作

    1、基本操作

    1.1 进入客户端

    在这之前已经配置好环境变量

    [wzy@hadoop102 hbase]$ hbase shell
    

    1.2 namespace

    1. 创建命名空间
    hbase:001:0> create_namespace 'bigdata'
    
    1. 查看所有的命名空间
    hbase:002:0> list_namespace
    

    在这里插入图片描述

    1.3 DDL

    在这里插入图片描述
    以网上的一个学生成绩表的例子来演示hbase的用法。这里grad对于表来说是一个只有它自己的列族,course对于表来说是一个有两个列的列族,这个列族由两个列组成math和art,当然我们可以根据我们的需要在course中建立更多的列族,如computer,physics等相应的列添加入course列族。

    1. 建立一个表scores,有两个列族grad和course
    hbase:003:0> create 'bigdata:scores','grad','course'
    
    1. 查看所有表名
    hbase:004:0> list
    
    1. 查看表的详情
    hbase:005:0> describe 'bigdata:scores'
    

    在这里插入图片描述
    4.修改表

    • 增加列族和修改信息都使用覆盖的方法
    hbase:006:0> alter 'bigdata:scores',{NAME=>'grad',VERSIONS=>3}
    
    • 删除信息使用特殊的语法
    alter "bigdata:scores",'delete'=>'grad'
    

    5.删除表
    shell中删除表,需要将表格设置为不可用

    disable 'bigdata:scores'
    drop 'bigdata:scores'
    

    1.4 DML

    1. 写入数据
    put 'scores','Tom','grade:','5'
    put 'scores','Tom','course:math','97'
    put 'scores','Tom','course:art','87'
    put 'scores','Jim','grade:','4'
    put 'scores','Jim','course:','89'
    put 'scores','Jim','course:','80'
    

    put命令比较简单,只有这一种用法:

    hbase> put 't1', 'r1', 'c1', 'value', 'ts1' 
    

    t1指表名,r1指行键名,c1指列名,value指单元格值。ts1指时间戳,一般都省略掉了。
    如果重复写入多个rowkey,相同列的数据,会写入多个版本进行覆盖。
    在这里插入图片描述
    2. 读取数据

    • 根据键值查询数据
    get 'scores','Jim' 
    get 'scores','Jim','grade' 
    

    可能你就发现规律了,HBase的shell操作,一个大概顺序就是操作关键词后跟表名,行名,列名这样的一个顺序,如果有其他条件再用花括号加上。
    在这里插入图片描述

    • 扫描所有数据
    scan 'scores'
    

    也可以指定一些修饰词:TIMERANGE, FILTER, LIMIT, STARTROW, STOPROW, TIMESTAMP, MAXLENGTH,or COLUMNS。没任何修饰词,就是上边例句,就会显示所有数据行。
    在这里插入图片描述
    3. 删除数据

    • delete
      delete表示删除一个版本的数据,即为1个cell,不填写版本默认删除最新的版本。
    delete 'scores','Jim','grade' 
    
    • deleteall
      删除所有版本的数据,即为当前行当前列的多个cell。(执行这个命令不会删除数据,而是标记为delete,只有在清理磁盘的时候才会删除
    deleteall 'scores','Jim','grade' 
    

    2. JavaApi连接Hbase

    环境:JAVA1.8 本地操作系统:windows,三台centos7 hadoop集群服务器

    2.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>hbase</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <properties>
            <maven.compiler.source>8</maven.compiler.source>
            <maven.compiler.target>8</maven.compiler.target>
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.apache.hbase</groupId>
                <artifactId>hbase-server</artifactId>
                <version>2.4.11</version>
                <exclusions>
                    <exclusion>
                        <groupId>org.glassfish</groupId>
                        <artifactId>javax.el</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>org.glassfish</groupId>
                <artifactId>javax.el</artifactId>
                <version>3.0.1-b06</version>
            </dependency>
        </dependencies>
    
    </project>
    

    2.2 配置log4j.properties

    log4j.rootLogger=WARN, stdout
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
    
    

    2.3 连接Hbase

    public static Connection HbaseConnect() throws IOException {
            // 1. 创建配置对象
            Configuration conf = new Configuration();
            // 2. 添加配置参数
            conf.set("hbase.zookeeper.quorum", "hadoop102,hadoop103,hadoop104");
            // 3. 创建 hbase 的连接
            // 默认使用同步连接
            Connection connection =
                    ConnectionFactory.createConnection(conf);
            return connection;
        }
    

    2.4 DDL操作

    package com.wzy;
    
    import org.apache.hadoop.conf.Configuration;
    import org.apache.hadoop.hbase.NamespaceDescriptor;
    import org.apache.hadoop.hbase.TableName;
    import org.apache.hadoop.hbase.client.*;
    import org.apache.hadoop.hbase.util.Bytes;
    
    import java.io.IOException;
    
    public class DDL {
        public static Connection HbaseConnect() throws IOException {
            // 1. 创建配置对象
            Configuration conf = new Configuration();
            // 2. 添加配置参数
            conf.set("hbase.zookeeper.quorum", "hadoop102,hadoop103,hadoop104");
            // 3. 创建 hbase 的连接
            // 默认使用同步连接
            Connection connection =
                    ConnectionFactory.createConnection(conf);
            return connection;
        }
    
        // 添加静态属性 connection 指向单例连接
        public static Connection connection;
    
        static {
            try {
                connection = HbaseConnect();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 创建命名空间
         *
         * @param namespace 命名空间名称
         */
        public static void createNamespace(String namespace) throws
                IOException {
            // 1. 获取 admin
            // 此处的异常先不要抛出 等待方法写完 再统一进行处理
            // admin 的连接是轻量级的 不是线程安全的 不推荐池化或者缓存这个连接
            Admin admin = connection.getAdmin();
            // 2. 调用方法创建命名空间
            // 代码相对 shell 更加底层 所以 shell 能够实现的功能 代码一定能实现
            // 所以需要填写完整的命名空间描述
            // 2.1 创建命令空间描述建造者 => 设计师
            NamespaceDescriptor.Builder builder =
                    NamespaceDescriptor.create(namespace);
            // 2.2 给命令空间添加需求
            builder.addConfiguration("user", "wzy");
            // 2.3 使用 builder 构造出对应的添加完参数的对象 完成创建
            // 创建命名空间出现的问题 都属于本方法自身的问题 不应该抛出
            try {
                admin.createNamespace(builder.build());
            } catch (IOException e) {
                System.out.println("命令空间已经存在");
                e.printStackTrace();
            }
            // 3. 关闭 admin
            admin.close();
        }
    
        /**
         * 判断表格是否存在
         *
         * @param namespace 命名空间名称
         * @param tableName 表格名称
         * @return ture 表示存在
         */
        public static boolean isTableExists(String namespace, String
                tableName) throws IOException {
            // 1. 获取 admin
            Admin admin = connection.getAdmin();
            // 2. 使用方法判断表格是否存在
            boolean b = false;
            try {
                b = admin.tableExists(TableName.valueOf(namespace,
                        tableName));
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 3. 关闭 admin
            admin.close();
            // 3. 返回结果
            return b;
        }
    
        /**
         * 创建表格
         *
         * @param namespace      命名空间名称
         * @param tableName      表格名称
         * @param columnFamilies 列族名称 可以有多个
         */
        public static void createTable(String namespace, String
                tableName, String... columnFamilies) throws IOException {
            // 判断是否有至少一个列族
            if (columnFamilies.length == 0) {
                System.out.println("创建表格至少有一个列族");
                return;
            }
            // 判断表格是否存在
            if (isTableExists(namespace, tableName)) {
                System.out.println("表格已经存在");
                return;
            }
            // 1.获取 admin
            Admin admin = connection.getAdmin();
            // 2. 调用方法创建表格
            // 2.1 创建表格描述的建造者
            TableDescriptorBuilder tableDescriptorBuilder =
                    TableDescriptorBuilder.newBuilder(TableName.valueOf(namespace,
                            tableName));
            // 2.2 添加参数
            for (String columnFamily : columnFamilies) {
                // 2.3 创建列族描述的建造者
                ColumnFamilyDescriptorBuilder
                        columnFamilyDescriptorBuilder =
                        ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes(columnFamily));
                // 2.4 对应当前的列族添加参数
                // 添加版本参数
                columnFamilyDescriptorBuilder.setMaxVersions(5);
                // 2.5 创建添加完参数的列族描述
                tableDescriptorBuilder.setColumnFamily(columnFamilyDescriptorBuilder.build());
            }
            // 2.6 创建对应的表格描述
            try {
                admin.createTable(tableDescriptorBuilder.build());
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 3. 关闭 admin
            admin.close();
        }
        /**
         * 修改表格中一个列族的版本
         * @param namespace 命名空间名称
         * @param tableName 表格名称
         * @param columnFamily 列族名称
         * @param version 版本
         */
        public static void modifyTable(String namespace ,String
                tableName,String columnFamily,int version) throws IOException {
            // 判断表格是否存在
            if (!isTableExists(namespace,tableName)){
                System.out.println("表格不存在无法修改");
                return;
            }
            // 1. 获取 admin
            Admin admin = connection.getAdmin();
            try {
                // 2. 调用方法修改表格
                // 2.0 获取之前的表格描述
                TableDescriptor descriptor =
                        admin.getDescriptor(TableName.valueOf(namespace, tableName));
                // 2.1 创建一个表格描述建造者
                // 如果使用填写 tableName 的方法 相当于创建了一个新的表格描述建造者 没有之前的信息
                // 如果想要修改之前的信息 必须调用方法填写一个旧的表格描述
                TableDescriptorBuilder tableDescriptorBuilder =
                        TableDescriptorBuilder.newBuilder(descriptor);
                // 2.2 对应建造者进行表格数据的修改
                ColumnFamilyDescriptor columnFamily1 =
                        descriptor.getColumnFamily(Bytes.toBytes(columnFamily));
                // 创建列族描述建造者
                // 需要填写旧的列族描述
                ColumnFamilyDescriptorBuilder
                        columnFamilyDescriptorBuilder =
                        ColumnFamilyDescriptorBuilder.newBuilder(columnFamily1);
                // 修改对应的版本
                columnFamilyDescriptorBuilder.setMaxVersions(version);
    
                // 此处修改的时候 如果填写的新创建 那么别的参数会初始化
    
                tableDescriptorBuilder.modifyColumnFamily(columnFamilyDescriptorBuilder.build());
                admin.modifyTable(tableDescriptorBuilder.build());
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 3. 关闭 admin
            admin.close();
        }
        /**
         * 删除表格
         * @param namespace 命名空间名称
         * @param tableName 表格名称
         * @return true 表示删除成功
         */
        public static boolean deleteTable(String namespace ,String
                tableName) throws IOException {
            // 1. 判断表格是否存在
            if (!isTableExists(namespace,tableName)){
                System.out.println("表格不存在 无法删除");
                return false;
            }
            // 2. 获取 admin
            Admin admin = connection.getAdmin();
            // 3. 调用相关的方法删除表格
            try {
                // HBase 删除表格之前 一定要先标记表格为不可以
                TableName tableName1 = TableName.valueOf(namespace,
                        tableName);
                admin.disableTable(tableName1);
                admin.deleteTable(tableName1);
                System.out.println(tableName1+"删除完成!");
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 4. 关闭 admin
            admin.close();
            return true;
        }
    }
    
    

    2.5 DML操作

    package com.wzy;
    
    import org.apache.hadoop.conf.Configuration;
    import org.apache.hadoop.hbase.Cell;
    import org.apache.hadoop.hbase.CellUtil;
    import org.apache.hadoop.hbase.CompareOperator;
    import org.apache.hadoop.hbase.TableName;
    import org.apache.hadoop.hbase.client.*;
    import org.apache.hadoop.hbase.filter.ColumnValueFilter;
    import org.apache.hadoop.hbase.filter.FilterList;
    import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;
    import org.apache.hadoop.hbase.util.Bytes;
    
    import java.io.IOException;
    
    
    public class DML {
        public static Connection HbaseConnect() throws IOException {
            // 1. 创建配置对象
            Configuration conf = new Configuration();
            // 2. 添加配置参数
            conf.set("hbase.zookeeper.quorum", "hadoop102,hadoop103,hadoop104");
            // 3. 创建 hbase 的连接
            // 默认使用同步连接
            Connection connection =
                    ConnectionFactory.createConnection(conf);
            return connection;
        }
    
        // 添加静态属性 connection 指向单例连接
        public static Connection connection;
    
        static {
            try {
                connection = HbaseConnect();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 插入数据
         *
         * @param namespace    命名空间名称
         * @param tableName    表格名称
         * @param rowKey       主键
         * @param columnFamily 列族名称
         * @param columnName   列名
         * @param value        值
         */
        public static void putCell(String namespace, String
                tableName, String rowKey, String columnFamily, String
                                           columnName, String value) throws IOException {
            // 1. 获取 table
            Table table =
                    connection.getTable(TableName.valueOf(namespace, tableName));
            // 2. 调用相关方法插入数据
            // 2.1 创建 put 对象
            Put put = new Put(Bytes.toBytes(rowKey));
            // 2.2. 给 put 对象添加数据
            put.addColumn(Bytes.toBytes(columnFamily), Bytes.toBytes(columnName), Bytes.toBytes(value));
            // 2.3 将对象写入对应的方法
            try {
                table.put(put);
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 3. 关闭 table
            table.close();
        }
    
        /**
         * 读取数据 读取对应的一行中的某一列
         *
         * @param namespace    命名空间名称
         * @param tableName    表格名称
         * @param rowKey       主键
         * @param columnFamily 列族名称
         * @param columnName   列名
         */
        public static void getCells(String namespace, String tableName,
                                    String rowKey, String columnFamily, String columnName) throws
                IOException {
            // 1. 获取 table
            Table table =
                    connection.getTable(TableName.valueOf(namespace, tableName));
            // 2. 创建 get 对象
            Get get = new Get(Bytes.toBytes(rowKey));
            // 如果直接调用 get 方法读取数据 此时读一整行数据
            // 如果想读取某一列的数据 需要添加对应的参数
            get.addColumn(Bytes.toBytes(columnFamily),
                    Bytes.toBytes(columnName));
            // 设置读取数据的版本
            get.readAllVersions();
            try {
                // 读取数据 得到 result 对象
                Result result = table.get(get);
                // 处理数据
                Cell[] cells = result.rawCells();
                // 测试方法: 直接把读取的数据打印到控制台
                // 如果是实际开发 需要再额外写方法 对应处理数据
                for (Cell cell : cells) {
                    // cell 存储数据比较底层
                    String value = new String(CellUtil.cloneValue(cell));
                    System.out.println(value);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 关闭 table
            table.close();
        }
    
        /**
         * 扫描数据
         *
         * @param namespace 命名空间
         * @param tableName 表格名称
         * @param startRow  开始的 row 包含的
         * @param stopRow   结束的 row 不包含
         */
        public static void scanRows(String namespace, String tableName,
                                    String startRow, String stopRow) throws IOException {
    
            // 1. 获取 table
            Table table =
                    connection.getTable(TableName.valueOf(namespace, tableName));
            // 2. 创建 scan 对象
            Scan scan = new Scan();
            // 如果此时直接调用 会直接扫描整张表
            // 添加参数 来控制扫描的数据
            // 默认包含
            scan.withStartRow(Bytes.toBytes(startRow));
            // 默认不包含
            scan.withStopRow(Bytes.toBytes(stopRow));
            try {
                // 读取多行数据 获得 scanner
                ResultScanner scanner = table.getScanner(scan);
                // result 来记录一行数据 cell 数组
                // ResultScanner 来记录多行数据 result 的数组
                for (Result result : scanner) {
                    Cell[] cells = result.rawCells();
                    for (Cell cell : cells) {
                        System.out.print(new
                                String(CellUtil.cloneRow(cell)) + "-" + new
                                String(CellUtil.cloneFamily(cell)) + "-" + new
                                String(CellUtil.cloneQualifier(cell)) + "-" + new
                                String(CellUtil.cloneValue(cell)) + "\t");
                    }
                    System.out.println();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 3. 关闭 table
            table.close();
        }
    
        /**
         * 带过滤的扫描
         *
         * @param namespace    命名空间
         * @param tableName    表格名称
         * @param startRow     开始 row
         * @param stopRow      结束 row
         * @param columnFamily 列族名称
         * @param columnName   列名
         * @param value        value 值
         * @throws IOException
         */
        public static void filterScan(String namespace, String tableName,
                                      String startRow, String stopRow, String columnFamily, String
                                              columnName, String value) throws IOException {
            // 1. 获取 table
            Table table =
                    connection.getTable(TableName.valueOf(namespace, tableName));
            // 2. 创建 scan 对象
            Scan scan = new Scan();
            // 如果此时直接调用 会直接扫描整张表
            // 添加参数 来控制扫描的数据
            // 默认包含
            scan.withStartRow(Bytes.toBytes(startRow));
            // 默认不包含
            scan.withStopRow(Bytes.toBytes(stopRow));
            // 可以添加多个过滤
            FilterList filterList = new FilterList();
            // 创建过滤器
            // (1) 结果只保留当前列的数据
            ColumnValueFilter columnValueFilter = new ColumnValueFilter(
                    // 列族名称
                    Bytes.toBytes(columnFamily),
                    // 列名
                    Bytes.toBytes(columnName),
                    // 比较关系
                    CompareOperator.EQUAL,
                    // 值
                    Bytes.toBytes(value)
            );
            // (2) 结果保留整行数据
            // 结果同时会保留没有当前列的数据
            SingleColumnValueFilter singleColumnValueFilter = new
                    SingleColumnValueFilter(
                    // 列族名称
                    Bytes.toBytes(columnFamily),
                    // 列名
                    Bytes.toBytes(columnName),
                    // 比较关系
                    CompareOperator.EQUAL,
                    // 值
                    Bytes.toBytes(value)
            );
            // 本身可以添加多个过滤器
            filterList.addFilter(singleColumnValueFilter);
            // 添加过滤
            scan.setFilter(filterList);
            try {
                // 读取多行数据 获得 scanner
                ResultScanner scanner = table.getScanner(scan);
                // result 来记录一行数据 cell 数组
                // ResultScanner 来记录多行数据 result 的数组
                for (Result result : scanner) {
                    Cell[] cells = result.rawCells();
                    for (Cell cell : cells) {
                        System.out.print(new
                                String(CellUtil.cloneRow(cell)) + "-" + new
                                String(CellUtil.cloneFamily(cell)) + "-" + new
                                String(CellUtil.cloneQualifier(cell)) + "-" + new
                                String(CellUtil.cloneValue(cell)) + "\t");
                    }
                    System.out.println();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 3. 关闭 table
            table.close();
        }
    
        /**
         * 删除 column 数据
         *
         * @param nameSpace
         * @param tableName
         * @param rowKey
         * @param family
         * @param column
         * @throws IOException
         */
        public static void deleteColumn(String nameSpace, String tableName,
                                        String rowKey, String family, String column) throws IOException {
            // 1.获取 table
            Table table = connection.getTable(TableName.valueOf(nameSpace,
                    tableName));
            // 2.创建 Delete 对象
            Delete delete = new Delete(Bytes.toBytes(rowKey));
            // 3.添加删除信息
            // 3.1 删除单个版本
    //
            delete.addColumn(Bytes.toBytes(family), Bytes.toBytes(column));
    
            // 3.2 删除所有版本
            delete.addColumns(Bytes.toBytes(family),
                    Bytes.toBytes(column));
            // 3.3 删除列族
    // delete.addFamily(Bytes.toBytes(family));
            // 3.删除数据
            table.delete(delete);
            // 5.关闭资源
            table.close();
        }
    
        public static void main(String[] args) throws IOException {
     putCell("bigdata","student","1002","info","name","lisi");
    // String cell = getCell("bigdata", "student", "1001", "info","name");
    // System.out.println(cell);
    // List strings = scanRows("bigdata", "student","1001", "2000");
    // for (String string : strings) {
    // System.out.println(string);
    //        deleteColumn("bigdata", "student", "1001", "info", "name");
        }
    
    
    }
    
    
  • 相关阅读:
    R语言使用caret包的modelLookup函数查看模型算法的细节信息、模型是否可用于分类、回归、超参数信息、是否是概率模型
    基础:如何写好一篇学术论文?
    【深入解析spring cloud gateway】08 Reactor 知识扫盲
    deepstream学习笔记(三):deepstream-imagedata-multistream解析与接入适配yolov5模型测试
    LeetCode 面试题 10.01. 合并排序的数组
    小程序当前页面栈以及跳转
    Asp.Net Core&Jaeger实现链路追踪
    Pytorch 最全入门介绍,Pytorch入门看这一篇就够了
    Effective Java学习笔记---------类和接口
    java基础之:聊ThreadLocal类,以及其解决内存泄漏做法
  • 原文地址:https://blog.csdn.net/m0_58598240/article/details/127107740