HBase安装及javaAPI crud操作

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/fooelliot/article/details/86620112

HBase

HBase 核心概念介绍

什么是hbase?

HBase是一个开源的非关系型分布式数据库(NoSQL),它参考了谷歌的BigTable建模,实现的编程语言为 Java。它是Apache软件基金会的Hadoop项目的一部分,运行于HDFS文件系统之上,为 Hadoop 提供类似于BigTable 规模的服务。因此,它可以对稀疏文件提供极高的容错率。HBase在列上实现了BigTable论文提到的压缩算法、内存操作和布隆过滤器。HBase的表能够作为MapReduce任务的输入和输出,可以通过JavaAPI来访问数据,也可以通过REST、Avro或者Thrift的API来访问。
虽然最近性能有了显著的提升,HBase 还不能直接取代SQL数据库。如今,它已经应用于多个数据驱动型网站,包括 Facebook的消息平台。在 Eric Brewer的CAP理论中,HBase属于CP类型的系统。

HBASE表模型

1、hbase的表模型跟mysql之类的关系型数据库的表模型差别巨大
2、hbase的表模型中有:行的概念;但没有字段的概念
3、行中存的都是key-value对,每行中的key-value对中的key可以是各种各样,每行中的key-value对的数量也可以是各种各样

hbase表模型的要点

1、一个表,有表名
2、一个表可以分为多个列族(不同列族的数据会存储在不同文件中)
3、表中的每一行有一个“行键rowkey”,而且行键在表中不能重复
4、表中的每一对kv数据称作一个cell
5、hbase可以对数据存储多个历史版本(历史版本数量可配置)
6、整张表由于数据量过大,会被横向切分成若干个region(用rowkey范围标识),不同region的数据也存储在不同文件中

概念特性

HBASE与mysql、oralce、db2、sqlserver等关系型数据库不同,它是一个NoSQL数据库(非关系型数据库)HBASE相比于其他nosql数据库(mongodb、redis、cassendra、hazelcast)的特点:
Hbase的表数据存储在HDFS文件系统中从而,hbase具备如下特性:存储容量可以线性扩展; 数据存储的安全性可靠性极高!

  • Hbase的表模型与关系型数据库的表模型不同

  • Hbase的表没有固定的字段定义

  • Hbase的表中每行存储的都是一些key-value对

  • Hbase的表中有列族的划分,用户可以指定将哪些kv插入哪个列族

  • Hbase的表在物理存储上,是按照列族来分割的,不同列族的数据一定存储在不同的文件中

  • Hbase的表中的每一行都固定有一个行键,而且每一行的行键在表中不能重复

  • Hbase中的数据,包含行键,包含key,包含value,都是byte[]类型,hbase不负责为用户维护数据类型

  • HBASE对事务的支持很差

HBase 核心组件

master

  • 管理HRegionServer,实现其负载均衡。

  • 管理和分配HRegion,比如在HRegion split时分配新的HRegion;在HRegionServer退出时迁移其负责的HRegion到其他HRegionServer上。

  • Admin职能创建、删除、修改Table的定义。实现DDL操作(namespace和table的增删改,column familiy的增删改等)。

  • 管理namespace和table的元数据(实际存储在HDFS上)。

  • 权限控制(ACL)。

  • 监控集群中所有HRegionServer的状态(通过Heartbeat和监听ZooKeeper中的状态)。

region server

  • 管理自己所负责的region数据的读写。

  • 读写HDFS,管理Table中的数据。

  • Client直接通过HRegionServer读写数据(从HMaster中获取元数据,找到RowKey所在的HRegion/HRegionServer后)。

Zookeeper集群所起作用

  • 存放整个HBase集群的元数据以及集群的状态信息。

  • 实现HMaster主从节点的failover。

注: HMaster通过监听ZooKeeper中的Ephemeral节点(默认:/hbase/rs/*)来监控HRegionServer的加入和宕机。
在第一个HMaster连接到ZooKeeper时会创建Ephemeral节点(默认:/hbasae/master)来表示Active的HMaster,其后加进来的HMaster则监听该Ephemeral节点
如果当前Active的HMaster宕机,则该节点消失,因而其他HMaster得到通知,而将自身转换成Active的HMaster,在变为Active的HMaster之前,它会在/hbase/masters/下创建自己的Ephemeral节点。

HBase读写数据流程

1、在HBase 0.96以前,HBase有两个特殊的Table:-ROOT-和.META. 用来记录用户表的rowkey范围所在的的regionserver服务器;因而客户端读写数据时需要通过3次寻址请求来对数据所在的regionserver进行定位,效率低下;

2、而在HBase 0.96以后去掉了-ROOT- Table,只剩下这个特殊的目录表叫做Meta Table(hbase:meta),它存储了集群中所有用户HRegion的位置信息,而ZooKeeper的节点中(/hbase/meta-region-server)存储的则直接是这个Meta Table的位置,并且这个Meta Table如以前的-ROOT- Table一样是不可split的。这样,客户端在第一次访问用户Table的流程就变成了:
A.从ZooKeeper(/hbase/meta-region-server)中获取hbase:meta的位置(HRegionServer的位置),缓存该位置信息。
B.从HRegionServer中查询用户Table对应请求的RowKey所在的HRegionServer,缓存该位置信息。
C.从查询到HRegionServer中读取Row。

注:客户会缓存这些位置信息,然而第二步它只是缓存当前RowKey对应的HRegion的位置,因而如果下一个要查的RowKey不在同一个HRegion中,则需要继续查询hbase:meta所在的HRegion,然而随着时间的推移,客户端缓存的位置信息越来越多,以至于不需要再次查找hbase:meta Table的信息,除非某个HRegion因为宕机或Split被移动,此时需要重新查询并且更新缓存。

  • hbase:meta表存储了所有用户HRegion的位置信息:

  • Rowkey:tableName,regionStartKey,regionId,replicaId等;

  • info列族:这个列族包含三个列,他们分别是:

    • info:regioninfo列:

    • regionId,tableName,startKey,endKey,offline,split,replicaId;

    • info:server列:HRegionServer对应的server:port;

    • info:serverstartcode列:HRegionServer的启动时间戳。

region server 内部机制

  • WAL即Write Ahead Log,在早期版本中称为HLog,它是HDFS上的一个文件,如其名字所表示的,所有写操作都会先保证将数据写入这个Log文件后,才会真正更新MemStore,最后写入HFile中。WAL文件存储在/hbase/WALs/${HRegionServer_Name}的目录中

  • BlockCache是一个读缓存,即“引用局部性”原理(也应用于CPU,分空间局部性和时间局部性,空间局部性是指CPU在某一时刻需要某个数据,那么有很大的概率在一下时刻它需要的数据在其附近;时间局部性是指某个数据在被访问过一次后,它有很大的概率在不久的将来会被再次的访问),将数据预读取到内存中,以提升读的性能。

  • HRegion是一个Table中的一个Region在一个HRegionServer中的表达。一个Table可以有一个或多个Region,他们可以在一个相同的HRegionServer上,也可以分布在不同的HRegionServer上,一个HRegionServer可以有多个HRegion,他们分别属于不同的Table。HRegion由多个Store(HStore)构成,每个HStore对应了一个Table在这个HRegion中的一个Column Family,即每个Column Family就是一个集中的存储单元,因而最好将具有相近IO特性的Column存储在一个Column Family,以实现高效读取(数据局部性原理,可以提高缓存的命中率)。HStore是HBase中存储的核心,它实现了读写HDFS功能,一个HStore由一个MemStore 和0个或多个StoreFile组成。

  • MemStore是一个写缓存(In Memory Sorted Buffer),所有数据的写在完成WAL日志写后,会 写入MemStore中,由MemStore根据一定的算法将数据Flush到地层HDFS文件中(HFile),通常每个HRegion中的每个 Column Family有一个自己的MemStore。

  • HFile(StoreFile) 用于存储HBase的数据(Cell/KeyValue)。在HFile中的数据是按RowKey、Column Family、Column排序,对相同的Cell(即这三个值都一样),则按timestamp倒序排列。

  • FLUSH详述

    • 每一次Put/Delete请求都是先写入到MemStore中,当MemStore满后会Flush成一个新的StoreFile(底层实现是HFile),即一个HStore(Column Family)可以有0个或多个StoreFile(HFile)。

    • 当一个HRegion中的所有MemStore的大小总和超过了hbase.hregion.memstore.flush.size的大小,默认128MB。此时当前的HRegion中所有的MemStore会Flush到HDFS中。

    • 当全局MemStore的大小超过了hbase.regionserver.global.memstore.upperLimit的大小,默认40%的内存使用量。此时当前HRegionServer中所有HRegion中的MemStore都会Flush到HDFS中,Flush顺序是MemStore大小的倒序(一个HRegion中所有MemStore总和作为该HRegion的MemStore的大小还是选取最大的MemStore作为参考?有待考证),直到总体的MemStore使用量低于hbase.regionserver.global.memstore.lowerLimit,默认38%的内存使用量。

    • 当前HRegionServer中WAL的大小超过了
      hbase.regionserver.hlog.blocksize * hbase.regionserver.max.logs
      的数量,当前HRegionServer中所有HRegion中的MemStore都会Flush到HDFS中,
      Flush使用时间顺序,最早的MemStore先Flush直到WAL的数量少于
      hbase.regionserver.hlog.blocksize * hbase.regionserver.max.logs
      这里说这两个相乘的默认大小是2GB,查代码,hbase.regionserver.max.logs默认值是32,而hbase.regionserver.hlog.blocksize默认是32MB。但不管怎么样,因为这个大小超过限制引起的Flush不是一件好事,可能引起长时间的延迟

HBase 安装和使用

hbase安装

HBASE是一个分布式系统,其中有一个管理角色: HMaster(一般2台,一台active,一台backup)
其他的数据节点角色:HRegionServer(很多台,看数据容量)

首先,要有一个HDFS集群,并正常运行; regionserver应该跟hdfs中的datanode在一起
其次,还需要一个zookeeper集群,并正常运行
然后,安装HBASE

# 下载
wget http://archive.apache.org/dist/hbase/hbase-1.2.9/hbase-1.2.9-bin.tar.gz

# 解压
tar -zxvf hbase-1.2.9-bin.tar.gz -C /xxx/xxx 

# 修改$HBASE_HOME/bin/hbase-env.sh文件修改配置如下
export JAVA_HOME=/usr/local/jdk1.8.0_192
export HBASE_MANAGES_ZK=false

# 修改或新建$HBASE_HOME/bin/hbase-site.xml文件
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>

    <!-- 指定hbase在HDFS上存储的路径 -->
  <property>
    <name>hbase.rootdir</name>
    <value>hdfs://node-1:9000/hbase</value>
  </property>

    <!-- 指定hbase是分布式的 -->
  <property>
    <name>hbase.cluster.distributed</name>
    <value>true</value>
  </property>

    <!-- 指定zk的地址,多个用“,”分割 -->
  <property>
    <name>hbase.zookeeper.quorum</name>
    <value>node-2,node-3,node-4</value>
  </property>

</configuration>


# 修改 $HBASE_HOME/bin/regionservers文件
node-2
node-3
node-4


# 启动集群

$HBASE_HOME/bin/start-hbase.sh
启动完后,还可以在集群中找任意一台机器启动一个备用的master
$HBASE_HOME/bin/hbase-daemon.sh start master
新启的这个master会处于backup状态

# 启动hbase的命令行客户端

$HBASE_HOME/bin/hbase shell
Hbase> list     // 查看表
Hbase> status   // 查看集群状态
Hbase> version  // 查看集群版本

常用shell命令

command 操作 描述
alter alter ‘t_test’,‘f4’ 修改列族(column family)模式
count count ‘t_test’ 统计表中行的数量
create create ‘t_test’,{NAME=>‘f1’,VERSION=>2},{NAME=>‘f2’,VERSION=>2} 创建表
describe describe ‘t_test’ 显示表相关的详细信息
delete delete ‘t_test’,‘r1’,‘f1:c1’ 删除指定对象的值(可以为表,行,列对应的值,另外也可以指定时间戳的值)
deleteall deleteall ‘t_test’,‘r1’ 删除指定行的所有元素值
disable disable ‘t_test’ 使表无效
drop drop ‘t_test’ 删除表(需要先禁用表)
enable enable ‘t_test’ 使表有效
exists exists ‘t_test’ 测试表是否存在
exit exit 退出hbase shell
get get ‘t_test’,‘r2’ 获取行或单元(cell)的值
list list 列出hbase中存在的所有表
put put ‘t_test’,‘r2’,‘f1:c1’,‘v2’ 向指向的表单元添加值
tools tools 列出hbase所支持的工具
scan scan ‘t_test’ 通过对表的扫描来获取对用的值
status status 返回hbase集群的状态信息
shutdown shutdown 关闭hbase集群(与exit不同)
version version 返回hbase版本信息
truncate truncate ‘t_person’ 清空表数据
desc desc ‘t_person’ 查看表结构

java api 操作hbase

  • pom.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">

    <artifactId>bit-data-hbase</artifactId>
    <groupId>com.andy</groupId>
    <version>1.0.1.RELEASE</version>
    
    <modelVersion>4.0.0</modelVersion>

    <dependencies>
        <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-client</artifactId>
            <version>1.2.9</version>
        </dependency>

        <dependency>
            <groupId>com.andy</groupId>
            <artifactId>big-data-common</artifactId>
            <version>1.0.1.RELEASE</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.7.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

  • hbase DDL操作
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Admin;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.regionserver.BloomType;
import org.apache.hadoop.hbase.util.Bytes;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * <p> HBase ddl 操作
 *
 * @author leone
 * @since 2018-12-16
 **/
public class HBaseClientTest {

    private static final Logger logger = LoggerFactory.getLogger(HBaseCrudTest.class);

    private Connection conn;

    private Admin admin;

    private String tableName = "t_person";

    private String f1 = "f1";

    private String f2 = "f2";

    private String f3 = "f3";

    @Before
    public void init() throws Exception {
        // 创建连接对象,会自动加载HBase配置文件 zookeeper集群的URL配置信息
        Configuration conf = HBaseConfiguration.create();
        conf.set("hbase.zookeeper.quorum", "node-2:2181,node-3:2181,node-4:2181");
        conn = ConnectionFactory.createConnection(conf);
        // 创建ddl描述对象
        admin = conn.getAdmin();
    }

    /**
     * 创建表
     * create 't_person','f1','f2','f3'
     *
     * @throws Exception
     */
    @Test
    public void createTableTest() throws Exception {
        // 创建表描述对象
        HTableDescriptor table = new HTableDescriptor(TableName.valueOf(tableName));

        // 创建列簇描述对象
        HColumnDescriptor column1 = new HColumnDescriptor(f1);
        // 设置保存数据的最大半本数量是3
        column1.setMaxVersions(3);

        HColumnDescriptor column2 = new HColumnDescriptor(f2);

        table.addFamily(column1);
        table.addFamily(column2);

        admin.createTable(table);

        admin.close();
        conn.close();
    }


    /**
     * 删除表
     * disable 't_person'
     * drop 't_person'
     *
     * @throws Exception
     */
    @Test
    public void dropTableTest() throws Exception {
        // 先停用表
        admin.disableTable(TableName.valueOf(tableName));

        // 再删除表
        admin.deleteTable(TableName.valueOf(tableName));

        admin.close();
        conn.close();
    }


    /**
     * 修改表添加列簇
     * alter 't_person','f4'
     *
     * @throws Exception
     */
    @Test
    public void modifyTableTest() throws Exception {
        // 取出旧的的表的描述信息
        HTableDescriptor table = admin.getTableDescriptor(TableName.valueOf(tableName));

        HColumnDescriptor column = new HColumnDescriptor(f3);
        // 设置布隆过滤器
        column.setBloomFilterType(BloomType.ROWCOL);

        table.addFamily(column);

        admin.modifyTable(TableName.valueOf(tableName), table);

        admin.close();
        conn.close();
    }

    /**
     * 查看表定义信息
     * desc 't_person'
     *
     * @throws Exception
     */
    @Test
    public void descTableTest() throws Exception {
        HTableDescriptor table = admin.getTableDescriptor(TableName.valueOf(tableName));
        HColumnDescriptor[] columnFamilies = table.getColumnFamilies();
        for (HColumnDescriptor hcd : columnFamilies) {
            logger.info("HColumn: {}", Bytes.toString(hcd.getName()));
        }
        admin.close();
        conn.close();
    }

}

  • hbase CRUD测试
import com.andy.common.utils.RandomValue;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * <p> HBase crud
 *
 * @author leone
 * @since 2018-12-16
 **/
public class HBaseCrudTest {

    private static final Logger logger = LoggerFactory.getLogger(HBaseCrudTest.class);

    private String tableName = "t_person";

    private String f1 = "f1", f2 = "f2", f3 = "f3";

    private Connection conn;

    private Configuration conf;

    @Before
    public void init() throws Exception {
        // 创建连接对象,会自动加载HBase配置文件
        conf = HBaseConfiguration.create();
        conf.set("hbase.zookeeper.quorum", "node-2:2181,node-3:2181,node-4:2181");
        conn = ConnectionFactory.createConnection(conf);
    }


    /**
     * DML 操作,向 HBase 插入数据
     * put 't_person','r2','f1:c1','v1'
     *
     * @throws Exception
     */
    @Test
    public void insertTest() throws Exception {
        // 获取指定表对象,进行dml操作
        Table table = conn.getTable(TableName.valueOf(tableName));
        List<Put> rows = new ArrayList<>();

        for (int i = 1; i <= 20; i++) {
            Put row = new Put(Bytes.toBytes(String.valueOf(i)));
            row.addColumn(Bytes.toBytes(f1), Bytes.toBytes("name"), Bytes.toBytes(RandomValue.getName()));
            row.addColumn(Bytes.toBytes(f1), Bytes.toBytes("age"), Bytes.toBytes(String.valueOf(RandomValue.getNumber(50))));
            row.addColumn(Bytes.toBytes(f2), Bytes.toBytes("address"), Bytes.toBytes(RandomValue.getAddress()));
            rows.add(row);
        }
        logger.info("size:{}", rows.size());
        table.put(rows);
        conn.close();
    }

    /**
     * DML 操作,删除数据 HBase 中数据
     * delete 't_person','r1','f1:c1'
     *
     * @throws Exception
     */
    @Test
    public void deleteTest() throws Exception {
        // 获取指定表对象,进行dml操作
        Table table = conn.getTable(TableName.valueOf(tableName));

        Delete delete1 = new Delete(Bytes.toBytes("0"));

        Delete delete2 = new Delete(Bytes.toBytes("1"));
        delete2.addColumn(Bytes.toBytes(f1), Bytes.toBytes("name"));

        List<Delete> deleteList = new ArrayList<>();
        deleteList.add(delete1);
        deleteList.add(delete2);

        table.delete(deleteList);

        conn.close();
    }


    /**
     * DML 操作,删除数据 HBase 中数据
     * deleteall 't_person','r1'
     *
     * @throws Exception
     */
    @Test
    public void deleteAllTest() throws Exception {
        // 获取指定表对象,进行dml操作
        Table table = conn.getTable(TableName.valueOf(tableName));

        Delete delete = new Delete(Bytes.toBytes("3"));

        table.delete(delete);

        conn.close();
    }

    /**
     * DML 操作,修改数据 HBase 中数据
     *
     * @throws Exception
     */
    @Test
    public void updateTest() throws Exception {
        // 获取指定表对象,进行dml操作
        Table table = conn.getTable(TableName.valueOf(tableName));

        conn.close();
    }


    /**
     * DML 操作 HBase 查询数据
     * get 't_person','r2'
     *
     * @throws Exception
     */
    @Test
    public void getTest() throws Exception {
        // 获取指定表对象,进行dml操作
        Table table = conn.getTable(TableName.valueOf(tableName));
        List<Get> gets = new ArrayList<>();
        for (int i = 1; i <= 20; i++) {
            Get get = new Get(Bytes.toBytes(String.valueOf(i)));
            gets.add(get);
        }
        Result[] results = table.get(gets);
        for (Result result : results) {
            CellScanner cellScanner = result.cellScanner();
            while (cellScanner.advance()) {
                Cell cell = cellScanner.current();
                // 行键的字节数组
                byte[] rowArray = cell.getRowArray();
                // 列簇的字节数组
                byte[] familyArray = cell.getFamilyArray();
                // 列名的字节数组
                byte[] qualifierArray = cell.getQualifierArray();
                // value的字节数组
                byte[] valueArray = cell.getValueArray();
                logger.info("行键:{} \t 列簇:{} \t key:{} \t value:{}", new Object[]{new String(rowArray, cell.getRowOffset(), cell.getRowLength()), new String(familyArray, cell.getFamilyOffset(), cell.getFamilyLength()), new String(qualifierArray, cell.getQualifierOffset(), cell.getQualifierLength()), new String(valueArray, cell.getValueOffset(), cell.getValueLength())});
            }
        }

        conn.close();
    }

    /**
     * DML 操作 HBase 查询数据
     * scan 't_person'
     *
     * @throws Exception
     */
    @Test
    public void scanTest() throws Exception {
        // 获取指定表对象,进行dml操作
        Table table = conn.getTable(TableName.valueOf(tableName));
        // 可以指定开始行键和结束行键
        Scan scan = new Scan(Bytes.toBytes("2"), Bytes.toBytes("3"));

        ResultScanner result = table.getScanner(scan);

        Iterator<Result> iterator = result.iterator();
        while (iterator.hasNext()) {
            Result rs = iterator.next();
            CellScanner cellScanner = rs.cellScanner();
            while (cellScanner.advance()) {
                Cell cell = cellScanner.current();
                byte[] rowArray = cell.getRowArray();
                // 列簇的字节数组
                byte[] familyArray = cell.getFamilyArray();
                // 列名的字节数组
                byte[] qualifierArray = cell.getQualifierArray();
                // value的字节数组
                byte[] valueArray = cell.getValueArray();
                logger.info("行键:{} \t 列簇:{} \t key:{} \t value:{}", new Object[]{new String(rowArray, cell.getRowOffset(), cell.getRowLength()), new String(familyArray, cell.getFamilyOffset(), cell.getFamilyLength()), new String(qualifierArray, cell.getQualifierOffset(), cell.getQualifierLength()), new String(valueArray, cell.getValueOffset(), cell.getValueLength())});
            }
        }
        conn.close();
    }


    /**
     * 查询某列数据的某个版本
     *
     * @throws Exception
     */
    @Test
    public void getVersionTest() throws Exception {
        HTable htable = new HTable(conf, tableName);

        Get get = new Get(Bytes.toBytes("2"));

        get.addColumn(Bytes.toBytes(f1), Bytes.toBytes("name"));
        get.setMaxVersions(2);
        Result result = htable.get(get);
        for (KeyValue cell : result.list()) {
            byte[] rowArray = cell.getRowArray();
            // 列簇的字节数组
            byte[] familyArray = cell.getFamilyArray();
            // 列名的字节数组
            byte[] qualifierArray = cell.getQualifierArray();
            // value的字节数组
            byte[] valueArray = cell.getValueArray();
            logger.info("行键:{} \t 列簇:{} \t key:{} \t value:{} \ttimestamp:{}", new Object[]{new String(rowArray, cell.getRowOffset(), cell.getRowLength()), new String(familyArray, cell.getFamilyOffset(), cell.getFamilyLength()), new String(qualifierArray, cell.getQualifierOffset(), cell.getQualifierLength()), new String(valueArray, cell.getValueOffset(), cell.getValueLength()), cell.getTimestamp()});
        }
        conn.close();
    }

}

猜你喜欢

转载自blog.csdn.net/fooelliot/article/details/86620112
今日推荐