HBase实训:纸币冠字号查询任务

一、实验目的

  1. 理解分布式数据存储系统HBase的架构和工作原理。

  2. 掌握HBase表的设计原则,能够根据实际业务需求设计合理的表结构。

  3. 学习使用HBase Java API进行数据的插入、查询和管理。

  4. 实践分布式数据存储系统在大数据环境下的应用,提升实际操作能力和问题解决能力。

二、安装配置HBase集群

1、安装并配置一个HBase集群,确保集群中的各个组件正常运行。

2、确保集群中的主节点(Master)和多个从节点(RegionServers)都可以正常通信。

三、设计HBase表结构

根据钞票交易数据的业务需求,设计合适的HBase表结构,考虑如何存储和检索钞票交易数据。

HBase表设计:

表名:currency_transactions

行键:<冠字号>#<交易时间>(确保唯一性,按时间查询)

列族:

info:存储钞票基本信息,如面额、交易金额。

transaction:存储交易相关信息,如交易时间、交易地点、类型。

meta:其他信息。

四、插入部分钞票交易数据并探索数据特征

1、将一部分钞票交易数据插入到设计的HBase表中。

(1)创建表:create 'currency_transactions', 'info', 'transaction', 'meta'

插入数据:

put 'currency_transactions', '123456ABC#20241201', 'info:denomination', '100'
put 'currency_transactions', '123456ABC#20241201', 'info:amount', '100'
put 'currency_transactions', '123456ABC#20241201', 'transaction:time', '2024-12-01 10:00'
put 'currency_transactions', '123456ABC#20241201', 'transaction:location', 'Beijing'
put 'currency_transactions', '123456ABC#20241201', 'transaction:type', 'Deposit'
put 'currency_transactions', '123456ABC#20241201', 'meta:notes', 'First deposit'

使用基础的HBase查询语句,探索钞票交易数据的结构和特征,确保数据可以正确存储和访问。

(1)查看表中所有数据:scan 'currency_transactions'

(2)查询特定行键的数据:

get 'currency_transactions', '123456ABC#20241201'

(3)查询特定列的数据:get 'currency_transactions', '123456ABC#20241201', 'transaction:location'

五、使用HBase Java API进行操作

1、创建Maven项目并添加相关依赖

(1)在IDEA上面新建Maven项目,下载与虚拟机中HBase一致的jdk版本1.8

(2)新建项目

(3)编辑pom.xml文件,内容如下:

XML 复制代码
<?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>com.example</groupId>
    <artifactId>javaapi</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- HBase Client -->
        <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-client</artifactId>
            <version>1.2.5</version>
        </dependency>

        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    </dependencies>
</project>
log4j.properties:
# Set root logger level and appender
log4j.rootLogger=INFO, console
# Console appender
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.target=System.out
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

2、HBase Java API的基本操作之表的创建

(1)代码部分:

java 复制代码
package com.example;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;

import java.io.IOException;

public class HBaseTableCreator {
    public static void main(String[] args) throws IOException {
        Configuration config = HBaseConfiguration.create();
        config.addResource(new Path("hbase-site.xml"));
        config.set("hbase.zookeeper.quorum", "192.168.125.101");
        config.set("hbase.zookeeper.property.clientPort", "2181");

        try (Connection connection = ConnectionFactory.createConnection(config);
             Admin admin = connection.getAdmin()) {

            TableName tableName = TableName.valueOf("currency_transactions");

            // 使用 HBase 1.x API 定义列族
            HTableDescriptor tableDescriptor = new HTableDescriptor(tableName);
            tableDescriptor.addFamily(new HColumnDescriptor("info"));
            tableDescriptor.addFamily(new HColumnDescriptor("transaction"));
            tableDescriptor.addFamily(new HColumnDescriptor("meta"));

            // 检查表是否存在
            if (admin.tableExists(tableName)) {
                System.out.println("Table already exists. Deleting and recreating...");
                admin.disableTable(tableName);
                admin.deleteTable(tableName);
            }

            // 创建表
            admin.createTable(tableDescriptor);
            System.out.println("Table created successfully.");
        }
    }
}

(2)运行结果:

3、HBase Java API的基本操作------数据的插入

(1)代码部分:

java 复制代码
package com.example;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;

import java.io.IOException;

public class HBaseDataInserter {

    public static void main(String[] args) throws IOException {
        // 配置 HBase 连接
        Configuration config = HBaseConfiguration.create();
        config.addResource(new Path("hbase-site.xml"));
        config.set("hbase.zookeeper.quorum", "192.168.125.101");
        config.set("hbase.zookeeper.property.clientPort", "2181");

        // 定义表名
        String tableName = "currency_transactions";

        try (Connection connection = ConnectionFactory.createConnection(config)) {
            // 插入多行数据
            addRows(connection, tableName);
        }
    }

    public static void addRows(Connection connection, String tableName) throws IOException {
        try (Table table = connection.getTable(TableName.valueOf(tableName))) {
            // 创建 Put 对象,插入行1 (Alice)
            Put put1 = new Put("row1".getBytes());
            put1.addColumn("info".getBytes(), "name".getBytes(), "Alice".getBytes());
            put1.addColumn("info".getBytes(), "age".getBytes(), "30".getBytes());
            put1.addColumn("transaction".getBytes(), "amount".getBytes(), "1000".getBytes());
            put1.addColumn("transaction".getBytes(), "currency".getBytes(), "USD".getBytes());

            // 创建 Put 对象,插入行2 (Bob)
            Put put2 = new Put("row2".getBytes());
            put2.addColumn("info".getBytes(), "name".getBytes(), "Bob".getBytes());
            put2.addColumn("info".getBytes(), "age".getBytes(), "40".getBytes());
            put2.addColumn("transaction".getBytes(), "amount".getBytes(), "500".getBytes());
            put2.addColumn("transaction".getBytes(), "currency".getBytes(), "EUR".getBytes());

            // 批量插入
            table.put(put1);
            table.put(put2);

            System.out.println("Rows added successfully.");
        }
    }
}

(2)运行结果:

4、根据冠字号(行键)查询单行数据

(1)实现代码

java 复制代码
package com.example;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;

import java.io.IOException;

public class HBaseDataRetriever {

    public static void main(String[] args) throws IOException {
        // 配置 HBase 连接
        Configuration config = HBaseConfiguration.create();
        config.addResource(new Path("hbase-site.xml"));
        config.set("hbase.zookeeper.quorum", "192.168.125.101");
        config.set("hbase.zookeeper.property.clientPort", "2181");

        // 定义表名和行键(冠字号)
        String tableName = "currency_transactions";
        String rowKey = "row1"; // 冠字号对应的行键

        try (Connection connection = ConnectionFactory.createConnection(config)) {
            // 查询单行数据
            retrieveRowByKey(connection, tableName, rowKey);
        }
    }

    public static void retrieveRowByKey(Connection connection, String tableName, String rowKey) throws IOException {
        try (Table table = connection.getTable(TableName.valueOf(tableName))) {
            // 创建 Get 对象
            Get get = new Get(rowKey.getBytes());

            // 指定需要的列族和列(可选)
            get.addFamily("info".getBytes()); // 获取 "info" 列族的所有列
            get.addColumn("transaction".getBytes(), "amount".getBytes()); // 获取特定列

            // 获取结果
            Result result = table.get(get);

            // 遍历结果
            System.out.println("Row Key: " + rowKey);
            result.listCells().forEach(cell -> {
                String family = new String(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength());
                String qualifier = new String(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength());
                String value = new String(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());
                System.out.println(family + ":" + qualifier + " = " + value);
            });
        }
    }
}

(2)运行结果

5、批量检索所有数据(扫描)

(1)实现代码

java 复制代码
package com.example;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;

import java.io.IOException;

public class HBaseDataScanner {

    public static void main(String[] args) throws IOException {
        // 配置 HBase 连接
        Configuration config = HBaseConfiguration.create();
        config.addResource(new Path("hbase-site.xml"));
        config.set("hbase.zookeeper.quorum", "192.168.125.101");
        config.set("hbase.zookeeper.property.clientPort", "2181");

        // 定义表名
        String tableName = "currency_transactions";

        try (Connection connection = ConnectionFactory.createConnection(config)) {
            // 扫描表数据
            scanTableData(connection, tableName);
        }
    }

    public static void scanTableData(Connection connection, String tableName) throws IOException {
        try (Table table = connection.getTable(TableName.valueOf(tableName))) {
            // 创建 Scan 对象
            Scan scan = new Scan();

            // 指定列族或列(可选)
            scan.addFamily("info".getBytes()); // 扫描 "info" 列族
            scan.addColumn("transaction".getBytes(), "currency".getBytes()); // 扫描特定列

            // 获取结果
            ResultScanner scanner = table.getScanner(scan);

            // 遍历结果
            for (Result result : scanner) {
                String rowKey = new String(result.getRow());
                System.out.println("Row Key: " + rowKey);

                result.listCells().forEach(cell -> {
                    String family = new String(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength());
                    String qualifier = new String(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength());
                    String value = new String(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());
                    System.out.println(family + ":" + qualifier + " = " + value);
                });

                System.out.println("------------");
            }
        }
    }
}

(2)运行结果

6、根据列值(如冠字号、金额等)过滤数据

(1)实现代码

java 复制代码
package com.example;

        import org.apache.hadoop.conf.Configuration;
        import org.apache.hadoop.fs.Path;
        import org.apache.hadoop.hbase.HBaseConfiguration;
        import org.apache.hadoop.hbase.TableName;
        import org.apache.hadoop.hbase.client.*;
        import org.apache.hadoop.hbase.filter.*;

        import java.io.IOException;

public class HBaseFilteredScan {

    public static void main(String[] args) throws IOException {
        // 配置 HBase 连接
        Configuration config = HBaseConfiguration.create();
        config.addResource(new Path("hbase-site.xml"));
        config.set("hbase.zookeeper.quorum", "192.168.125.101");
        config.set("hbase.zookeeper.property.clientPort", "2181");

        // 定义表名
        String tableName = "currency_transactions";

        try (Connection connection = ConnectionFactory.createConnection(config)) {
            // 使用过滤器检索数据
            scanTableWithFilter(connection, tableName, "transaction", "currency", "USD");
        }
    }

    public static void scanTableWithFilter(Connection connection, String tableName, String columnFamily, String columnQualifier, String valueToFilter) throws IOException {
        try (Table table = connection.getTable(TableName.valueOf(tableName))) {
            // 创建 Scan 对象
            Scan scan = new Scan();

            // 添加列值过滤器
            SingleColumnValueFilter filter = new SingleColumnValueFilter(
                    columnFamily.getBytes(),           // 列族
                    columnQualifier.getBytes(),        // 列名
                    CompareFilter.CompareOp.EQUAL,     // 比较操作
                    valueToFilter.getBytes());         // 目标值

            // 设置过滤器
            scan.setFilter(filter);

            // 获取结果
            ResultScanner scanner = table.getScanner(scan);

            // 遍历结果
            for (Result result : scanner) {
                String rowKey = new String(result.getRow());
                System.out.println("Row Key: " + rowKey);

                result.listCells().forEach(cell -> {
                    String family = new String(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength());
                    String qualifier = new String(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength());
                    String value = new String(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());
                    System.out.println(family + ":" + qualifier + " = " + value);
                });

                System.out.println("------------");
            }
        }
    }
}

(2)运行结果

相关推荐
dal118网工任子仪2 分钟前
40,【5】CTFHUB WEB SQL 时间盲注
数据库
凌龍墨6 分钟前
SQL 递归 ---- WITH RECURSIVE 的用法
数据库·sql·mysql·回归
对自己不够狠7 分钟前
SQL ON与WHERE区别
数据库·sql
weisian1518 分钟前
Mysql--实战篇--连接泄漏问题(什么是连接泄漏,未关闭SqlSession,长事务处理,连接池管理等)
数据库·mysql
doubt。9 分钟前
【BUUCTF】[GXYCTF2019]BabySQli
网络·数据库·笔记·sql·mysql·安全·web安全
京东零售技术28 分钟前
2024 京东零售技术年度总结
大数据·人工智能
港股研究社28 分钟前
医药新零售的下半场,叮当健康找到增长搭子
大数据·人工智能·零售
XinShun41 分钟前
sqlalchemy The transaction is active - has not been committed or rolled back.
前端·数据库·python
draymond710744 分钟前
redis-排查命中率降低问题
数据库·redis·缓存
dal118网工任子仪1 小时前
51,【1】BUUCTF WEB GxYCTF2019babysqli
数据库·sql