hbase--JavaAPI

1、DDL

  • Hbase 存储
    • 用户行为数据的存储
    • 用户在平台上做的操作
      • 浏览:15个字段
        • userid
        • ip
        • ……
      • 订单:20
        • userid
        • ip
        • orderid
        • goodid
      • 支付:18
        • userid
        • orderid
        • paytype
        • resultprice
        • ……
      • 收藏:12
        • goodid
        • ……
      • 添加购物车
    • 不同的操作产生的日志的字段不一样
    • 所有的日志都存储在一个文件中
    • ETL以后将每一行的数据写入Hbase,一天一张表
      • 每天处理昨天的数据
      • 程序中获取昨天的日期,创建一张Hbase表
  • 问题:Java Client如何知道Hbase的地址呢?
    • 目标:让Congratulation对象获取服务端地址
    • 服务端地址是谁:Zookeeper的地址
      • Hbase的所有客户端都要连接Zookeeper
    • 方式一:要么将hbase-site.xml放入resources目录中
      • 程序运行时会加载这个目录中的文件
    • 方式二:在configuration对象中定义服务端地址
      • conf.set(“hbase.zookeeper.quorum”,“node-01:2181,node-02:2181,node-03:2181”);
  • 代码实现
public class HbaseClientDDL {private String nsName = "nstest";
    private String tbName = "hanjiaxiaozhi01:tbtest";public static void main(String[] args) throws IOException {
        //构建一个对象
        HbaseClientDDL clientDDL = new HbaseClientDDL();
        //todo:1-构建一个Hbase的连接
        //用于管理整个程序的配置
        Configuration conf = HBaseConfiguration.create();
        //配置Hbase客户端连接的服务端地址:zookeeper的地址
//        conf.set("hbase.zookeeper.quorum","node-01:2181,node-02:2181,node-03:2181");
        //构建连接
        Connection conn = clientDDL.createHbaseConn(conf);//todo:2-构建一个Hbase管理员对象
        HBaseAdmin admin = clientDDL.createHbaseAdmin(conn);//todo:3-实现DDL
        //创建NS
//        clientDDL.createHbaseNS(admin);
        //删除NS
//        clientDDL.deleteHbaseNS(admin);
        //列举NS
//        clientDDL.listHbaseNS(admin);
        //创建Table
//        clientDDL.createHbaseTB(admin);
        //删除Table
        clientDDL.deleteHbaseTB(admin);
        //列举Table
        clientDDL.listHbaseTB(admin);
​
​
        //todo:4-释放资源
        admin.close();
        conn.close();
    }private void deleteHbaseTB(HBaseAdmin admin) throws IOException {
        //先判断表是否存在,如果存在,就删除
        if(admin.tableExists(tbName)){
            //如果存在,就删除
            //先禁用
            admin.disableTable(tbName);
            //再删除
            admin.deleteTable(tbName);
        }
    }private void listHbaseTB(HBaseAdmin admin) throws IOException {
        //获取所有表的名称对象
        TableName[] tableNames = admin.listTableNames();
        for (TableName tableName : tableNames) {
            //将每张表的名称打印
            System.out.println(tableName.getNameAsString());
        }
    }private void createHbaseTB(HBaseAdmin admin) throws IOException {
        //先判断表是否存在,如果存在,先删除再创建
        if(admin.tableExists(tbName)){
            //如果存在,就删除
            //先禁用
            admin.disableTable(tbName);
            //再删除
            admin.deleteTable(tbName);
        }
        //创建表:create  'ns:tbname',列族
        //构建表的对象
        HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(tbName));
        //构建列族的对象
        HColumnDescriptor family = new HColumnDescriptor("family");
        HColumnDescriptor info = new HColumnDescriptor("info");
        //修改列族的属性
        info.setMaxVersions(3);//设置这个列族的版本数
        //添加列族
        desc.addFamily(family);
        desc.addFamily(info);
        //管理员创建表
        admin.createTable(desc);
    }//删除NS
    private void deleteHbaseNS(HBaseAdmin admin) throws IOException {
        admin.deleteNamespace(nsName);
    }//列举NameSpace
    private void listHbaseNS(HBaseAdmin admin) throws IOException {
        //获取所有NS的对象
        NamespaceDescriptor[] descriptors = admin.listNamespaceDescriptors();
        //迭代打印名称
        for (NamespaceDescriptor descriptor : descriptors) {
            //打印每个NS的名字
            System.out.println(descriptor.getName());
        }
    }//创建NameSpace
    private void createHbaseNS(HBaseAdmin admin) throws IOException {
        //创建一个NS对象
        NamespaceDescriptor descriptor = NamespaceDescriptor.create(nsName).build();
        //让管理员创建NS
        admin.createNamespace(descriptor);
    }//用于获取并返回Hbase的管理员对象
    private HBaseAdmin createHbaseAdmin(Connection conn) throws IOException {
        HBaseAdmin admin = (HBaseAdmin) conn.getAdmin();
        return admin;
    }//用于构建并返回一个Hbase的连接
    private Connection createHbaseConn(Configuration conf) throws IOException {
        Connection conn = ConnectionFactory.createConnection(conf);
        return conn;
    }
}
  • 重点:非常熟练
    • 构建连接
    • 创建管理员
    • 创建表
    • 删除表

2、DML

  • Hbase的数据类型:没有数据类型
  • 所有数据都是以字节的形式存储
  • put
  //插入数据到表数据
    private void putData(Table table) throws IOException {
        //构建一个Put对象,必须指定字节数组类型的rowkey
        //put  'ns:tbname','rowkey','cf:col',value
        Put put = new Put(Bytes.toBytes("20200304_000"));
        //配置put对象
        put.addColumn(Bytes.toBytes("basic"),Bytes.toBytes("name"),Bytes.toBytes("laowu"));
        //让表执行put操作
        table.put(put);
    }
  • get
//获取单个Rowkey的数据
    private void getData(Table table) throws IOException {
        //构建一个Get对象
//        get 'ns:tbname','rowkey'
//        get 'ns:tbname','rowkey','cf'
//        get 'ns:tbname','rowkey','cf:colname'
        Get get = new Get(Bytes.toBytes("20200101_001"));
        //配置get对象
//        get.addFamily(Bytes.toBytes("basic"));//get 'ns:tbname','rowkey','cf'
//        get.addColumn(Bytes.toBytes("basic"),Bytes.toBytes("name")); //get 'ns:tbname','rowkey','cf:colname'
        //让表执行get操作
        Result result = table.get(get);
        //记住:一个Result对象就是一个Rowkey的数据,包含一个Cell数组,Cell数组中是多个Cell
        //记住:一个Cell就是一列的数据:20200101_001            column=basic:age, timestamp=1593247238403, value=18
        //迭代取出每一列的数据
        for(Cell cell : result.rawCells()){
            //取出每个Cell就是每一行,进行打印
            System.out.println(
                    Bytes.toString(CellUtil.cloneRow(cell))+"\t"+
                            Bytes.toString(CellUtil.cloneFamily(cell))+"\t"+
                            Bytes.toString(CellUtil.cloneQualifier(cell))+"\t"+
                            Bytes.toString(CellUtil.cloneValue(cell))+"\t"+
                            cell.getTimestamp()
            );
        }
    }
  • delete
//删除某列的数据
    private void deleteData(Table table) throws IOException {
        //构建delete对象:delete 'ns:tbname','rowkey','cf:col'
        Delete del = new Delete(Bytes.toBytes("20200103_002"));
        //配置
//        del.addColumns(Bytes.toBytes("basic"),Bytes.toBytes("name"));//Delete all versions of the specified column.
        del.addColumn(Bytes.toBytes("basic"),Bytes.toBytes("name"));//Delete the latest version of the specified column.
//        del.addColumn(Bytes.toBytes("basic"),Bytes.toBytes("name"),1593247929546L);//指定版本删除
        //让表执行delete
        table.delete(del);
    }

scan

//扫描全表
    private void scanData(Table table) throws IOException {
        //构建Scan对象
        Scan scan = new Scan();
        //让表执行scan
        ResultScanner scanner = table.getScanner(scan);
        //注意:ResultScanner就是一个Result的集合,就是多个Rowkey的集合
        //先迭代取出每个Rowkey
        for (Result result : scanner) {
            //打印每个Rowkey的值
            System.out.println("==========================================");
            System.out.println(Bytes.toString(result.getRow()));
            //输出rowkey的每一列
            for(Cell cell : result.rawCells()){
                //取出每个Cell就是每一行,进行打印
                System.out.println(
                        Bytes.toString(CellUtil.cloneRow(cell))+"\t"+
                                Bytes.toString(CellUtil.cloneFamily(cell))+"\t"+
                                Bytes.toString(CellUtil.cloneQualifier(cell))+"\t"+
                                Bytes.toString(CellUtil.cloneValue(cell))+"\t"+
                                cell.getTimestamp()
                );
            }
        }
    }
  • 重点
    • 构建连接
    • 构建表的对象
    • 构建Put的使用
  • Scan的使用
  • Cell:就一列的内容
    在这里插入图片描述
  • Result:就是一个Rowkey的内容,里面有一个Cell数组
    在这里插入图片描述
  • ResultScanner:就是多个Rowkey的返回值,里面是多个Result对象
    在这里插入图片描述

3、Filter

  • Scan + Filter查询是工作中最常用的方式
  • 命令行
scan 't1', {ROWPREFIXFILTER => 'row2', FILTER => "
    (QualifierFilter (>=, 'binary:xyz')) AND (TimestampsFilter ( 123, 456))"}
    
ROWPREFIXFILTER:rowkey的前缀过滤器
QualifierFilter:列标签过滤器
TimestampsFilter:时间戳过滤器
  • 常用
STARTROW:从哪个rowkey可以开始
STOPROW:到哪个rowkey结束,不包含stoprow
​
从某个位置开始查询
scan 'student:stu',{STARTROW=>'20200102_003'}
用于定义范围查询:前闭后开区间
scan 'student:stu',{STARTROW=>'20200102_003',STOPROW=>'20200304_000'}
  • 请记住:
    • Hbase中scan查询对Rowkey的匹配是前缀匹配
    • 只要rowkey前缀符合就可以进行查询,不需要给定完整的rowkey
      • scan ‘student:stu’,{STARTROW=>‘2020’}
      • scan ‘student:stu’,{STARTROW=>‘20200103’}
    • 因为底层的rowkey按照asc码进行比较排序的
    • 应用
      • 如果我的rowkey是这么设计的
        • 年月日_用户id
        • 20200101_001
        • 20200102_002
        • 20200803_003
        • 20210101_001
      • 我想走索引查询所有2020年的数据
        • scan ‘student:stu’,{STARTROW=>‘2020’,STOPROW=>‘2021’}
      • 我想走是索引查询所有2020年8月和9月的数据
        • scan ‘student:stu’,{STARTROW=>‘20200801’,STOPROW=>‘20201001’}
    • Rowkey的前缀是什么至关重要:决定了可以按照什么 条件做索引查询
      • 如果我想查询用户id为001的用户的数据
      • 不能走索引,只能全表扫描
      • 前缀是日期,只能按照日期做索引检索
      • hbase按照rowkey的前缀进行检索匹配
  • 实现
public class HbaseClientFilter {public static void main(String[] args) throws IOException {
        //构建一个客户端对象
        HbaseClientFilter clientDML = new HbaseClientFilter();
        //todo:1-获取一个Hbase连接
        Configuration conf  = HBaseConfiguration.create();
        Connection conn = clientDML.createHbaseConn(conf);
        //todo:2-构建表的对象
        Table table = clientDML.createHTable(conn);
        //todo:3-实现增删改查
        //scan
        clientDML.scanData(table);
        //todo:4-释放连接
        table.close();
        conn.close();
    }//扫描全表
    private void scanData(Table table) throws IOException {
        //构建Scan对象
        Scan scan = new Scan();/**
         * 为Scan配置过滤器
         */
        //rowkey的过滤器:过滤rowkey不等于20200101_001
        RowFilter rowFilter = new RowFilter(CompareFilter.CompareOp.NOT_EQUAL, new BinaryComparator(Bytes.toBytes("20200101_001")));
        //列族的过滤器:过滤列族的名称中包含sic的列族
        FamilyFilter familyFilter = new FamilyFilter(CompareFilter.CompareOp.EQUAL,new SubstringComparator("sic"));
        //列标签的过滤器:过滤列的名称不等于name的列
        QualifierFilter qualifierFilter = new QualifierFilter(CompareFilter.CompareOp.NOT_EQUAL,new BinaryComparator(Bytes.toBytes("name")));
        //列值过滤器:过滤所有列值中包含lao的列
        ValueFilter valueFilter = new ValueFilter(CompareFilter.CompareOp.EQUAL,new SubstringComparator("lao"));
        //rowkey的前缀过滤器,符合这个前缀的rowkey就会被返回
        PrefixFilter prefixFilter = new PrefixFilter(Bytes.toBytes("20200102"));
        //单列值过滤器
        SingleColumnValueFilter singleColumnValueFilter = new SingleColumnValueFilter(
                Bytes.toBytes("basic"),
                Bytes.toBytes("name"),
                CompareFilter.CompareOp.EQUAL,
                Bytes.toBytes("laoda")
        );
        //多列前缀过滤器
        byte[][] prefixes = {
          Bytes.toBytes("name")
        };
        MultipleColumnPrefixFilter multipleColumnPrefixFilter = new MultipleColumnPrefixFilter(prefixes);
        //组合过滤条件:将所有数据中的name这一列过滤出来,并且name的值等于laoda
        FilterList filterList = new FilterList();
        filterList.addFilter(singleColumnValueFilter);
        filterList.addFilter(multipleColumnPrefixFilter);
        //分页过滤器
        scan.setStartRow(Bytes.toBytes("20200102_003"));//设置从哪一条开始
        PageFilter pageFilter = new PageFilter(2);//参数代表每一页显示几条内容//让Scan加载过滤器
        scan.setFilter(pageFilter);
//        scan.setStartRow(Bytes.toBytes("20200102_003"));
//        scan.setStopRow(Bytes.toBytes("20200103_002"));
        //让表执行scan
        ResultScanner scanner = table.getScanner(scan);
        //注意:ResultScanner就是一个Result的集合,就是多个Rowkey的集合
        //先迭代取出每个Rowkey
        for (Result result : scanner) {
            //打印每个Rowkey的值
            System.out.println("==========================================");
            System.out.println(Bytes.toString(result.getRow()));
            //输出rowkey的每一列
            for(Cell cell : result.rawCells()){
                //取出每个Cell就是每一行,进行打印
                System.out.println(
                        Bytes.toString(CellUtil.cloneRow(cell))+"\t"+
                                Bytes.toString(CellUtil.cloneFamily(cell))+"\t"+
                                Bytes.toString(CellUtil.cloneQualifier(cell))+"\t"+
                                Bytes.toString(CellUtil.cloneValue(cell))+"\t"+
                                cell.getTimestamp()
                );
            }
        }
    }//创建一个表的对象并返回
    private Table createHTable(Connection conn) throws IOException {
        //构建stu这张表的对象
        Table table = conn.getTable(TableName.valueOf("student:stu"));
        return table;
    }
​
​
    //用于构建并返回一个Hbase的连接
    private Connection createHbaseConn(Configuration conf) throws IOException {
        Connection conn = ConnectionFactory.createConnection(conf);
        return conn;
    }
}
  • 重要
    • SingleColumnValueFilter:列值过滤器
      • 用户行为分析中,用于过滤用户不同的操作
      • event=pay/collect/add
      • 用于事件分析
    • MultipleColumnPrefixFilter:多列前缀过滤器
      • 这个是最常用的
      • 分布式计算程序中需要处理某些列,但不需要这张表的所有列
      • 在Hbase读取时直接过滤,然后在程序中直接处理
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值