分布式NoSQL列存储数据库Hbase Java API(三)

简介: 分布式NoSQL列存储数据库Hbase Java API(三)

分布式NoSQL列存储数据库Hbase(三)

知识点01:课程回顾

  1. Hbase使用场景
  • 集群管理:定时调度管理的脚本
  • 定时调度:Azkaban、Oozie、Linux Crontab
  • Hbase脚本
  • 将Hbase命令写入一个文件
  • hbase shell运行文件即可
  • 测试开发:Hbase命令
  • DDL
  • list_namespace/create_namespace
  • create/list/desc
  • DML
  • put:插入、更新
  • 插入:每次是为每行插入一列
  • 更新:通过插入数据来代替了更新,用于提高性能
  • 语法
put 表 rowkey    列族:列    值
  • delete:删除数据
  • delete:删除列
  • deleteall:删除行
  • truncate:清空表
  • get:获取某个rowkey的数据
  • 优点:查询数据最快的方式,根据rowkey进行查询
  • rowkey是Hbase中的唯一索引
  • 缺点
  • get最多返回一个rowkey的所有列
  • 语法
get 表名    rowkey    【列族:列】
  • scan:查询符合条件的数据
  • 优点:返回需要的多条Hbase的数据
  • 缺点:很多情况下是不走索引【不能根据rowkey进行检索】
  • 语法
scan 表名
scan 表名 + Filter
  • 生产开发:JavaAPI
  • Connection:连接对象
  • Configuration:配置管理对象
  • HbaseAdmin:Hbase管理员对象:用于实现DDL操作

知识点02:课程目标

  1. Hbase JavaAPI实现DML操作【重点内容】
  • put:数据的写入或者更新
  • get:查询数据
  • delete:删除数据
  • scan:扫描数据
  • Filter:过滤器
  1. Hbase存储设计【掌握原理】
  • 表、RegionServer关系?
  • 表的分布式如何实现的?
  • Region的划分规则?
  • 数据如何决定进入哪个分区哪?
  • 分区内部是如何存储数据的?

知识点03:Java API:DML:Table

  • 需求:通过JavaAPI实现对Hbase的DML操作
  • 分析
  • step1:构建连接对象
  • step2:构建Table对象
  • 所有的DML操作,必须构建一个表的对象
  • 实现
//todo:1-构建一个连接对象
Configuration conf = HBaseConfiguration.create();
//指定Hbase集群的服务端地址:给定ZK的地址
conf.set("hbase.zookeeper.quorum","node1:2181,node2:2181,node3:2181");
Connection conn = ConnectionFactory.createConnection(conf);
//todo:2-所有的DML必须构建一个Table表的对象
//构建一个表的对象
TableName tbname = TableName.valueOf("itcast:t1");
Table table = conn.getTable(tbname);
  • 总结
  • step1:先构建一个连接对象:Connection
  • step2:根据所做的操作决定构建哪种对象
  • DDL:HbaseAdmin
  • DML:Table

知识点04:Java API:DML:Put

  • 需求:JavaAPI实现往Hbase表中写入数据
put   表   rowkey    列族:列    值
  • 分析
  • step1:Hbase中实现put操作,需要构建Put对象
  • step2:为Put对象添加列族、列名、值
  • step3:对表执行put操作
  • 实现
/**
     * 用于实现使用Put插入数据到表中:put   表   rowkey    列族:列    值
     * @param table
     */
    private void putData(Table table) throws IOException {
        //step1:构建Put对象,必须指定插入的rowkey的数据
        Put put = new Put(Bytes.toBytes("20201001_888"));
        //step2:初始化put,添加列族、列、值
        put.addColumn(
                Bytes.toBytes("basic"),//指定列族
                Bytes.toBytes("name"),//指定列的名称
                Bytes.toBytes("laoba")//指定列的值
        );
        //step3:让表执行put操作
        table.put(put);     
    }
  • 总结[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a57OCTc7-1616631335573)(20210318_分布式NoSQL列存储数据库Hbase(三).assets/image-20210318084424081.png)]
  • Put对象:专门用于往Hbase写入数据的对象
  • 指定Rowkey,添加列族、列、值信息
  • table.put

知识点05:Java API:DML:Get

  • 需求:JavaAPI实现从Hbase表中读取某个Rowkey的数据
get 表名  rowkey  【列族,列】
  • 分析
  • step1:Hbase中实现get操作,需要构建Get对象
  • step2:为Get对象添加列族、列名
  • step3:对表执行get操作,获取返回值,打印输出
table.get(Get)
  • 实现
/**
     * 使用Get查询Hbase表中的数据:get 表名 rowkey  【列族,列】
     * @param table
     */
    private void getData(Table table) throws IOException {
        //step1:构建Get对象,必须指定Rowkey
        Get get = new Get(Bytes.toBytes("20201001_888"));
        //step2:可选的,配置Get需要的参数:列族、列
//        get.addColumn()//指定获取某一列的数据
//        get.addFamily()//指定获取某个列族的数据
        //step3:表执行get操作
        Result result = table.get(get);//Get操作的返回值为Result类型对象
        /**
         * 迭代输出Result对应的rowkey中的每一列的数据,一个Rowkey包含很多列,循环迭代输出每一列的数据
         *      Result:一个Result对象就是一个Rowkey的数据
         *      Cell:一个Cell代表一个rowkey中一列的数据
         *      一个Result对象中会包含多个Cell
         */
        for(Cell cell : result.rawCells()){
            //输出每一列Cell对象中的数据:20201001_888  column=basic:age, timestamp=1616029665232, value=20
            System.out.println(
                    Bytes.toString(CellUtil.cloneRow(cell)) //获取这一列的rowkey,转换为字符串类型
                    +"\t"+
                    Bytes.toString(CellUtil.cloneFamily(cell)) //获取这一列的列族,转换为字符串类型
                    +"\t"+
                    Bytes.toString(CellUtil.cloneQualifier(cell)) //获取这一列的名称,转换为字符串类型
                    +"\t"+
                    Bytes.toString(CellUtil.cloneValue(cell)) //获取这一列的值,转换为字符串类型
                    +"\t"+
                    cell.getTimestamp() //获取时间戳
            );
        }
    }
  • 总结
  • step1:先构建Get
  • step2:执行Get,得到返回值
  • Result:一个Result就是一个Rowkey的数据,包含一个Cell数组
  • Cell:一个Cell就是一列的数据

知识点06:Java API:DML:Delete

  • 需求:JavaAPI实现从Hbase表删除某个Rowkey的某列的数据
  • 分析
  • step1:Hbase中实现delete操作,需要构建Delete对象
  • step2:为Delete对象添加列族、列名
  • step3:对表执行delete操作
table.delete(Delete)
  • 实现
/**
     * 删除某个Rowkey的某一列的数据:delete  表名     rowkey      列族:列
     * @param table
     */
    private void deleteData(Table table) throws IOException {
        //step1:构建删除对象
        Delete delete = new Delete(Bytes.toBytes("20201001_888"));
        //step2:添加删除配置
//        delete.addColumn(Bytes.toBytes("basic"),Bytes.toBytes("name")); //只删除最新版本
        delete.addColumns(Bytes.toBytes("basic"),Bytes.toBytes("name")); //删除所有版本
        //step3:执行删除
        table.delete(delete);
    }
  • 总结
  • step1:构建Delete对象
  • step2:根据需求调用配置方法:添加列族、列
  • step3:表对象指定delete对象即可

知识点07:Java API:DML:Scan

  • 需求:JavaAPI实现从Hbase表中读取所有数据
scan 表
scan 表 + filter
  • 分析
  • step1:Hbase中实现scan操作,需要构建Scan对象
  • step2:对表执行scan操作
  • step3:获取返回值,取出每个Rowkey的数据,打印输出
  • 实现
/**
     * 通过Scan,进行Hbase表的数据查询:scan 表
     * @param table
     */
    private void scanData(Table table) throws IOException {
        //step1:构建Scan对象
        Scan scan = new Scan();
        //step2:执行scan:返回值是ResultScanner,包含了多个Rowkey的数据
        ResultScanner rsScan = table.getScanner(scan);
        /**
         *      ResultScanner:包含多个Rowkey的数据,包含了多个Result对象:Iterator<Result>
         *      Result:一个Rowkey的数据,包含了这个Rowkey多列的数据:Cell[]
         *      Cell :一列的数据
         */
        //step3:打印数据
        //先获取每个rowkey
        for(Result rs:rsScan){
            //直接输出当前rowkey的值
            System.out.println(Bytes.toString(rs.getRow()));
            //再获取每个rowkey中的每一列
            for(Cell cell : rs.rawCells()){
                //输出每一列Cell对象中的数据:20201001_888  column=basic:age, timestamp=1616029665232, value=20
                System.out.println(
                        Bytes.toString(CellUtil.cloneRow(cell)) //获取这一列的rowkey,转换为字符串类型
                                +"\t"+
                                Bytes.toString(CellUtil.cloneFamily(cell)) //获取这一列的列族,转换为字符串类型
                                +"\t"+
                                Bytes.toString(CellUtil.cloneQualifier(cell)) //获取这一列的名称,转换为字符串类型
                                +"\t"+
                                Bytes.toString(CellUtil.cloneValue(cell)) //获取这一列的值,转换为字符串类型
                                +"\t"+
                                cell.getTimestamp() //获取时间戳
                );
            }
            System.out.println("----------------------------------------------------------------------");
        }
    }
  • 总结
  • step1:先构建Scan对象
  • step2:执行Scan操作
  • step3:返回值
  • ResultScanner:包含多个Rowkey的数据的集合
  • Iter《Result》
  • Result:一个Rowkey的数据
  • Cell[]
  • Cell:一列的数据

知识点08:Java API:DML:Filter

  • 需求:JavaAPI实现从Hbase表中根据条件读取部分
  • 需求1:查询2021年1月和2月的数据
  • 需求2:查询2021年的所有数据
  • 需求3:查询所有age = 20的数据
  • 需求4:查询所有数据的name和age这两列
  • 需求5:查询所有年age = 20的人的name和age
  • 分析
  • Rowkey的设计:时间【年月日】+id
  • Rowkey整体有序
  • 前缀匹配
  • 需求1
  • StartRow = 》202101
  • 包含
  • StopRow = 》202103
  • 不包含
  • 需求2
  • 方案一:使用startrow = 2021,stoprow = 2022
  • 方案二:使用Filter:PrefixFilter,Rowkey的前缀过滤器[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3MfZFeVn-1616631335575)(20210318_分布式NoSQL列存储数据库Hbase(三).assets/image-20210318103200422.png)]
  • 构建过滤器,指定Rowkey前缀
  • Scan加载过滤器,返回所有符合rowkey前缀的过滤器
  • 需求三:查询所有age = 20的数据
where age = 20
  • Filter:列值过滤器
  • SingleColumnValueFilter:对某一列的值进行过滤
  • 指定列值过滤器:哪个列族下的哪一列的值等于什么值
  • scan加载过滤器
  • 需求4:查询所有数据的name和age这两列
select name ,age from table
  • Filter:多列前缀过滤器
  • MutipleColumnPrefixFIlter:用于将每条数据中指定的列过滤出来
  • 指定需要过滤哪些列
  • scan加载过滤器即可
  • 需求5:查询所有年age = 20的人的name和age
select name,age from table where age = 20
  • 支持组合过滤器:FilterList
  • 列的过滤:MutipleColumnPrefixFIlter
  • 列值过滤:SingleColumnValueFilter
  • 构建两个过滤器,将两个过滤器组合放入过滤器集合
  • Scan加载过滤器集合
  • 实现
  • 批量写入数据到Hbase
/**
     * 批量写入数据到Hbase
     * @param table
     */
    private void putListData(Table table) throws IOException {
        //step1:构建Put对象,一个Put对象用于表示一个Rowkey写入的数据
        Put put1 = new Put(Bytes.toBytes("20210101_001"));
        Put put2 = new Put(Bytes.toBytes("20210201_002"));
        Put put3 = new Put(Bytes.toBytes("20210301_003"));
        //step2:为Put添加这个Rowkey的每一列
        put1.addColumn(Bytes.toBytes("basic"),Bytes.toBytes("name"),Bytes.toBytes("laoda"));
        put1.addColumn(Bytes.toBytes("basic"),Bytes.toBytes("age"),Bytes.toBytes("18"));
        put1.addColumn(Bytes.toBytes("other"),Bytes.toBytes("phone"),Bytes.toBytes("110"));
        put1.addColumn(Bytes.toBytes("other"),Bytes.toBytes("addr"),Bytes.toBytes("shanghai"));
        put2.addColumn(Bytes.toBytes("basic"),Bytes.toBytes("name"),Bytes.toBytes("laoer"));
        put2.addColumn(Bytes.toBytes("basic"),Bytes.toBytes("age"),Bytes.toBytes("20"));
        put2.addColumn(Bytes.toBytes("other"),Bytes.toBytes("phone"),Bytes.toBytes("120"));
        put3.addColumn(Bytes.toBytes("basic"),Bytes.toBytes("name"),Bytes.toBytes("laosan"));
        put3.addColumn(Bytes.toBytes("basic"),Bytes.toBytes("age"),Bytes.toBytes("22"));
        put3.addColumn(Bytes.toBytes("other"),Bytes.toBytes("addr"),Bytes.toBytes("beijing"));
        //step3:将多个Put封装到List中
        List<Put> puts = new ArrayList<Put>();
        puts.add(put1);
        puts.add(put2);
        puts.add(put3);
        //step4:执行PutList
        table.put(puts);
    }
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ijNYbrbY-1616631335576)(20210318_分布式NoSQL列存储数据库Hbase(三).assets/image-20210318101928785.png)]
  • 需求一:实现范围过滤
//需求一:查询2021年1月和2月的数据
scan.withStartRow(Bytes.toBytes("202101"));
scan.withStopRow(Bytes.toBytes("202103"));
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kUtwEsEy-1616631335577)(20210318_分布式NoSQL列存储数据库Hbase(三).assets/image-20210318102604990.png)]
  • 需求二实现
//需求2:查询2021年的所有数据
Filter prefixFiter = new PrefixFilter(Bytes.toBytes("2021"));
//将过滤器加载到scan中
scan.setFilter(prefixFiter);
  • 需求三实现
//需求三:查询所有age = 20的数据
        /**
         *    * @param family name of column family
         *    * @param qualifier name of column qualifier
         *    * @param op operator
         *    * @param value value to compare column values against
         */
        Filter valueFilter = new SingleColumnValueFilter(
                Bytes.toBytes("basic"),//指定列族
                Bytes.toBytes("age"),//指定列
                CompareOperator.EQUAL,//指定比较器类型
                Bytes.toBytes("20")  //比较的值
        );
        //将过滤器加载到scan中
        scan.setFilter(valueFilter);
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sP5MLfRe-1616631335579)(20210318_分布式NoSQL列存储数据库Hbase(三).assets/image-20210318104213375.png)]
  • 需求四实现
//需求4:查询所有数据的name和age这两列
        //构建所有需要过滤的列
        byte[][] prefixes = {
            Bytes.toBytes("name"),
            Bytes.toBytes("age")
        };
        Filter columnFilter = new MultipleColumnPrefixFilter(prefixes);
        //将过滤器加载到scan中
        scan.setFilter(columnFilter);
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vkQbO9w9-1616631335580)(20210318_分布式NoSQL列存储数据库Hbase(三).assets/image-20210318104930496.png)]
  • 需求五实现
Filter valueFilter = new SingleColumnValueFilter(
                Bytes.toBytes("basic"),//指定列族
                Bytes.toBytes("age"),//指定列
                CompareOperator.EQUAL,//指定比较器类型
                Bytes.toBytes("20")  //比较的值
        );
        //需求4:查询所有数据的name和age这两列
        //构建所有需要过滤的列
        byte[][] prefixes = {
            Bytes.toBytes("name"),
            Bytes.toBytes("age")
        };
        Filter columnFilter = new MultipleColumnPrefixFilter(prefixes);
        //需求5:查询所有age = 20的人的name和age
        //构建FIlterList
        FilterList lists = new FilterList();//MUST_PASS_ALL:and,MUST_PASS_ONE:or
        //添加过滤器
        lists.addFilter(valueFilter);
        lists.addFilter(columnFilter);
        //将过滤器加载到scan中
        scan.setFilter(lists);
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GaXWQJwf-1616631335581)(20210318_分布式NoSQL列存储数据库Hbase(三).assets/image-20210318110732471.png)]
  • 总结
  • Rowkey范围过滤:StartRow和StopRow
  • Rowkey前缀过滤:PrefixFilter
  • Rowkey中列的值的过滤:SingleColumnValueFilter
  • Rowkey中列的过滤:MultipleColumnPrefixFilter
  • 多种条件的组合过滤:FilterList

知识点09:存储设计:存储架构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QFiNIbeF-1616631335582)(20210318_分布式NoSQL列存储数据库Hbase(三).assets/image-20210317190105892.png)]

  • 问题:Hbase整体如何实现数据的存储?
  • 分析

知识点10:存储设计:Table、Region、RegionServer的关系


  • 问题:客户端操作的是表,数据最终存在RegionServer中,表和RegionServer的关系是什么?
  • 分析

知识点11:存储设计:Region的划分规则

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xGxSZiF6-1616631335582)(20210318_分布式NoSQL列存储数据库Hbase(三).assets/image-20210317191202582.png)]

  • 问题:一张表划分为多个Region,划分的规则是什么?写一条数据到表中,这条数据会写入哪个Region,分配规则是什么?
  • 分析

知识点12:存储设计:Region内部存储结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KRgBXSLA-1616631335583)(20210318_分布式NoSQL列存储数据库Hbase(三).assets/image-20210317191716413.png)]

  • 问题:数据在Region的内部是如何存储的?
  • 分析

知识点13:存储设计:HDFS中的存储结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-10viiw3z-1616631335583)(20210318_分布式NoSQL列存储数据库Hbase(三).assets/image-20210317191754182.png)]

  • 问题:Hbase的数据在HDFS中是如何存储的?
  • 分析

egionServer的关系


  • 问题:客户端操作的是表,数据最终存在RegionServer中,表和RegionServer的关系是什么?
  • 分析

知识点11:存储设计:Region的划分规则

[外链图片转存中…(img-xGxSZiF6-1616631335582)]

  • 问题:一张表划分为多个Region,划分的规则是什么?写一条数据到表中,这条数据会写入哪个Region,分配规则是什么?
  • 分析

知识点12:存储设计:Region内部存储结构

[外链图片转存中…(img-KRgBXSLA-1616631335583)]

  • 问题:数据在Region的内部是如何存储的?
  • 分析

知识点13:存储设计:HDFS中的存储结构

[外链图片转存中…(img-10viiw3z-1616631335583)]

  • 问题:Hbase的数据在HDFS中是如何存储的?
  • 分析


相关实践学习
云数据库HBase版使用教程
&nbsp; 相关的阿里云产品:云数据库 HBase 版 面向大数据领域的一站式NoSQL服务,100%兼容开源HBase并深度扩展,支持海量数据下的实时存储、高并发吞吐、轻SQL分析、全文检索、时序时空查询等能力,是风控、推荐、广告、物联网、车联网、Feeds流、数据大屏等场景首选数据库,是为淘宝、支付宝、菜鸟等众多阿里核心业务提供关键支撑的数据库。 了解产品详情:&nbsp;https://cn.aliyun.com/product/hbase &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
8天前
|
关系型数据库 MySQL 分布式数据库
《MySQL 简易速速上手小册》第6章:MySQL 复制和分布式数据库(2024 最新版)
《MySQL 简易速速上手小册》第6章:MySQL 复制和分布式数据库(2024 最新版)
45 2
|
1月前
|
运维 监控 Java
推荐一款好用的Java分布式任务调度框架!
推荐一款好用的Java分布式任务调度框架!
168 0
|
3天前
|
安全 Java 程序员
|
3天前
|
存储 分布式计算 Hadoop
基于Hadoop分布式数据库HBase1.0部署及使用
基于Hadoop分布式数据库HBase1.0部署及使用
|
3天前
|
Dubbo Java 应用服务中间件
Java从入门到精通:3.2.2分布式与并发编程——了解分布式系统的基本概念,学习使用Dubbo、Spring Cloud等分布式框架
Java从入门到精通:3.2.2分布式与并发编程——了解分布式系统的基本概念,学习使用Dubbo、Spring Cloud等分布式框架
|
7天前
|
Java API Apache
ZooKeeper【基础 03】Java 客户端 Apache Curator 基础 API 使用举例(含源代码)
【4月更文挑战第11天】ZooKeeper【基础 03】Java 客户端 Apache Curator 基础 API 使用举例(含源代码)
24 11
|
9天前
|
安全 Java API
java借助代理ip,解决访问api频繁导致ip被禁的问题
java借助代理ip,解决访问api频繁导致ip被禁的问题
|
11天前
|
存储 安全 Java
说说Java 8 引入的Stream API
说说Java 8 引入的Stream API
12 0
|
11天前
|
分布式计算 Java API
Java 8新特性之Lambda表达式与Stream API
【4月更文挑战第16天】本文将介绍Java 8中的两个重要新特性:Lambda表达式和Stream API。Lambda表达式是Java 8中引入的一种新的编程语法,它允许我们将函数作为参数传递给其他方法,从而使代码更加简洁、易读。Stream API是Java 8中引入的一种新的数据处理方式,它允许我们以声明式的方式处理数据,从而使代码更加简洁、高效。本文将通过实例代码详细讲解这两个新特性的使用方法和优势。
|
12天前
|
安全 Java API
RESTful API设计与实现:Java后台开发指南
【4月更文挑战第15天】本文介绍了如何使用Java开发RESTful API,重点是Spring Boot框架和Spring MVC。遵循无状态、统一接口、资源标识和JSON数据格式的设计原则,通过创建控制器处理HTTP请求,如示例中的用户管理操作。此外,文章还提及数据绑定、验证、异常处理和跨域支持。最后,提出了版本控制、安全性、文档测试以及限流和缓存的最佳实践,以确保API的稳定、安全和高效。

热门文章

最新文章