实现HBase序列号需要借用C++的序列号工具:protobuf

版本:protobuf-2.5.0.tar.gz

  1. 安装步骤
    1. 解压tar -zxvf
    2. 安装依赖环境
    3. 进入protobuf-2.5.0,运行./configure
    4. 报错,原因是没有对应C环境
      报错没有对应环境
      configure: error: in `/tmp/bigdata/protobuf-2.5.0':
      configure: error: no acceptable C compiler found in $PATH
    5. yum grouplist 查看需要的环境(通过这个命令来安装一批依赖环境)
    6. yum groupinstall "Development tools" 安装该环境
    7. ./configure(会生成一个Makefile文件,才能执行下面make命令)
    8. make && make install
  2. 编写序列化信息
    package com.ke;
    message PhoneDetail
    {
         required string otherNumber = 1;
         required string length = 2;
         required string type = 3;
         required string date = 4;
    }
    
    // 要和自己项目的包名、字段 一致

     

  3. 创建.proto文件,将上面序列化信息保存到文件中,文件的名称就是后面生成序列化文件的类名
    vi phoneInfo.proto
  4. cd /usr/local/bin/ 有一个文件:protoc
    protoc --help查询具体命令信息
  5. 执行命令:/usr/local/bin/protoc phoneInfo.proto --java_out=/root/
  6. root目录生成:com/xiaoke/PhoneInfo.java文件
  7. 将.java文件引入项目中,该文件可以直接序列化
  8. 使用序列化、反序列化进行插入、查询操作
    1.进入刚才生成的序列化文件PhoneInfo.java
    2.继续使用类:HBaseDemo,保持原来初始化、销毁方法
    
    
        /**
         * 序列化数据: 可以减少内存、存储的数据量大小
         * @throws Exception
         */
        @Test
        public void insertMangerByProtoBufData() throws Exception{
            List<Put> puts = new ArrayList<Put>();
            for (int i = 0; i < 10; i++) {
                String myNumber = getNumber("177");
                for (int j = 0; j < 10000; j++) {
                    // 模拟数据 别人的手机号码、通话时长、通话时间、通话类型
                    String otherNumber = getNumber("177");
                    String length = String.valueOf(random.nextInt(100));
                    String date = getDate("2019");
                    String type = String.valueOf(random.nextInt(2));
    
                    // rowkey 设计为我的手机号码 + 时间戳反转(也可以将手机号码倒过来进行数据分散)
                    String rowkey = myNumber+"_"+(Long.MAX_VALUE-sdf.parse(date).getTime());
    
                    PhoneInfo.PhoneDetail.Builder builder = PhoneInfo.PhoneDetail.newBuilder();
                    builder.setDate(date);
                    builder.setLength(length);
                    builder.setType(type);
                    builder.setOtherNumber(otherNumber);
                    Put put = new Put(Bytes.toBytes(rowkey));
                    // 序列化后就没有列名了,所以需要自定义列名
                    put.addColumn(Bytes.toBytes("cf"), Bytes.toBytes("phone"), builder.build().toByteArray());
                    puts.add(put);
                }
            }
            table.put(puts);
            /*
            HBase中序列化数据:
    17786774306_9223370490639607807                             column=cf:phone, timestamp=1605756025604, value=\x0A\x0B17714285591\x12\x0241\x1A\x010"\x0E20190100081248
    17786774306_9223370490642379807                                     column=cf:phone, timestamp=1605756025604, value=\x0A\x0B17794212043\x12\x0274\x1A\x010"\x0E20190100072636
             */
        }
    
    
        /**
         * 查看数据,需要反序列化
         * @throws Exception
         */
        @Test
        public void getByProtoBuf() throws Exception {
            Get get = new Get("17786774306_9223370490639607807".getBytes());
            Result result = table.get(get);
            byte[] info = CellUtil.cloneValue(result.getColumnLatestCell(Bytes.toBytes("cf"), Bytes.toBytes("phone")));
            PhoneInfo.PhoneDetail phoneDetail = PhoneInfo.PhoneDetail.parseFrom(info);
            System.out.println(phoneDetail);
            /*
            结果:
            otherNumber: "17714285591"
            length: "41"
            type: "0"
            date: "20190100081248"
             */
        }

     

  9. HDFS目录:/hbase/data/default/phoneInfo/0b155055d15cc66d9f56067b72d9447d/cf, 文件大小节省空间、1/3
  10. 为什么linux文件名不加后缀、windows需要?
    linux在执行的时候,你是先写了一个命令,在写文件名,意味着你已经知道那个应用程序执行了
  11. 代码:https://gitee.com/Xiaokeworksveryhard/big-data.git
posted on 2020-11-21 19:00  陕西小楞娃  阅读(617)  评论(0编辑  收藏  举报