hadoop生态系统学习之路(五)hbase的简单使用

最近,参与了公司的一个大数据接口平台的开发,具体的处理过程是这样的。我们公司负责数据的入库,也就是一个etl过程,使用MR将数据入到hive里面,然后同步到impala,然后此接口平台提供查询接口,前台会将sql语句以参数传过来,然后接口平台通过调用impala提供的java api接口,将数据查询出来返回给用户。另外,如果查询的数据量很大,那么前台就会传一个taskId过来,第一次只需将数据查询出来,入到impala临时表,下次再查便将数据返回。那么,如何记录此任务的状态变化呢,这里我们就使用到了hbase,以taskId为row key,然后创建一个列簇记录状态信息。

下面,分以下几步对hbase进行介绍。

一、hbase的基本原理

HBase是一个构建在HDFS上的分布式列存储系统,主要用于海量结构化数据存储。

hbase的特点:

1. 大,一个表可以有数十亿行,上百万列;

2. 无模式,每行都有一个可排序的主键和任意多的列,列可以根据需要动态的增加,同一张表中不同的行可以有截然不同的列;

3. 面向列,面向列(族)的存储和权限控制,列(族)独立检索;

4. 稀疏,空(null)列并不占用存储空间,表可以设计的非常稀疏;

5. 数据多版本,每个单元中的数据可以有多个版本,默认情况下版本号自动分配,是单元格插入时的时间戳;

6. 数据类型单一,Hbase中的数据都是字符串,没有类型。

下面,再来看看hbase相关的组件:

Master:为Region server分配region,负责Region server的负载均衡,发现失效的Region server并重新分配其上的region,管理用户对table的增删改查操作。

RegionServer:Regionserver维护region,处理对这些region的IO请求,Regionserver负责切分在运行过程中变得过大的region。

Zookeeper:通过选举,保证任何时候,集群中只有一个master,Master与RegionServers 启动时会向ZooKeeper注册,存贮所有Region的寻址入口,实时监控Region server的上线和下线信息,并实时通知给Master,存储HBase的schema和table元数据,默认情况下,HBase 管理ZooKeeper 实例,比如, 启动或者停止ZooKeeper。Zookeeper的引入使得Master不再是单点故障。

大概的介绍下,关于hbase表结构,笔者下面再进行介绍。

二、hbase的常用命令

首先,我们可以执行hbase shell进入hbase命令行,如下:

然后,执行list,可以看到所有的表,如下:

,接下来,我们可以describe ‘表名’来查看表结构,如下:

可以看到,这个表有一个列族info。

然后,我们可以使用scan ‘表名’来查看,整张表的数据。

下面,我们使用get ‘result_info’,’test02’获取表中某个row key的所有列值,如下:

好了,就说这几个命令,还有很多,大家可以查阅下,多练练就熟了。

三、hbase 的java api基本操作

hbase包依赖,如下:

    <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <hadoop.version>2.3.0-cdh5.0.0</hadoop.version>
      <hbase.version>0.96.1.1-cdh5.0.0</hbase.version>
      <hive.version>0.12.0-cdh5.0.0</hive.version>
    </properties>

        <!-- habase 相关jar-->
        <dependency>
          <groupId>org.apache.hbase</groupId>
          <artifactId>hbase-client</artifactId>
          <version>${hbase.version}</version>
          <exclusions>
              <exclusion>
                  <artifactId>jdk.tools</artifactId>
                  <groupId>jdk.tools</groupId>
              </exclusion>
          </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-common</artifactId>
            <version>${hbase.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-server</artifactId>
            <version>${hbase.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-thrift</artifactId>
            <version>${hbase.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-testing-util</artifactId>
            <version>${hbase.version}</version>
            <scope>test</scope>
        </dependency>

首先,我直接贴出代码,如下:

package org.hbase.demo;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.util.Bytes;

/**
 * 关键点1_:将自动提交关闭,如果不关闭,每写一条数据都会进行提交,是导入数据较慢的做主要因素。
 * 关键点2:设置缓存大小,当缓存大于设置值时,hbase会自动提交。此处可自己尝试大小,一般对大数据量,设置为5M即可,本文设置为3M。
 * 关键点3:每一个分片结束后都进行flushCommits(),如果不执行,当hbase最后缓存小于上面设定值时,不会进行提交,导致数据丢失。
 *
 * @author qiyongkang
 *
 */
public class Example {

    /**
     *
     * insertBatch: 批量插入. <br/>
     *
     * @author qiyongkang
     * @throws IOException
     * @since JDK 1.6
     */
    public static void insertBatch() throws IOException {
        Configuration config = HBaseConfiguration.create();
        config.set("hbase.zookeeper.quorum", "172.31.25.8,172.31.25.2,172.31.25.3");

        HTable htable = new HTable(config, "qyk_info");
        htable.setAutoFlush(false, false); // 关键点1
        htable.setWriteBufferSize(3 * 1024 * 1024); // 关键点2

        int num = 1;
        while (num <= 10) {
            Put put = new Put(Bytes.toBytes(num + ""));
            put.add(Bytes.toBytes("info"), Bytes.toBytes("age"), Bytes.toBytes("18"));
            put.add(Bytes.toBytes("info"), Bytes.toBytes("name"), Bytes.toBytes("qyk" + num));
            put.add(Bytes.toBytes("info"), Bytes.toBytes("id"), Bytes.toBytes(num + ""));
            htable.put(put);

            num++;

            if (num % 100 == 0) {
                System.out.println("..." + num);
            }
        }
        htable.flushCommits();// 关键点3
        htable.close();
    }

    /**
     *
     * insertSingle:单个插入. <br/>
     *
     * @author qiyongkang
     * @throws IOException
     * @since JDK 1.6
     */
    public static void insertSingle() throws IOException {
        Configuration config = HBaseConfiguration.create();
        config.set("hbase.zookeeper.quorum", "172.31.25.8,172.31.25.2,172.31.25.3");

        HTable htable = new HTable(config, "qyk_info");
        Put put = new Put(Bytes.toBytes("0"));
        put.add(Bytes.toBytes("info"), Bytes.toBytes("age"), Bytes.toBytes("18"));
        put.add(Bytes.toBytes("info"), Bytes.toBytes("name"), Bytes.toBytes("qyk" + 0));
        put.add(Bytes.toBytes("info"), Bytes.toBytes("id"), Bytes.toBytes("0"));
        htable.put(put);

        htable.close();
    }

    /**
     *
     * getData:根据row key获取列信息. <br/>
     *
     * @author qiyongkang
     * @throws IOException
     * @since JDK 1.6
     */
    public static void getData() throws IOException {
        Configuration config = HBaseConfiguration.create();
        config.set("hbase.zookeeper.quorum", "172.31.25.8,172.31.25.2,172.31.25.3");

        HTable htable = new HTable(config, "qyk_info");

        Get get = new Get(Bytes.toBytes("1"));
        Result result = htable.get(get);

        String age = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("age")));
        String name = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("name")));
        String id = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("id")));

        System.out.println("age:" + age + ",name:" + name + ",id:" + id);

        htable.close();
    }

    public static void main(String[] args) throws IOException {
        //单个插入
        insertSingle();

        //批量插入
        insertBatch();

        //根据row key获取数据
        getData();
    }

}

分别对应三个操作,首先我们在hbase命令行执行create ‘qyk_info’, ‘info’创建表和列族,然后,再执行程序,可以看到控制台如下:

然后,我们执行scan ‘qyk_info’可以看到,如下:

然后,我们使用单个插入,rowkey还是0,将id改为11,age改为19,执行单个插入。

然后,在命令行执行get ‘qyk_info’, ‘0’可以看到:

其实,这个就是更新操作,cell中的值会有一个时间戳,每次显示此列的最新值。

好了,关于hbase的基本使用就讲到这儿了,比较粗浅,希望给大家带来帮助!

时间: 2024-08-27 10:28:12

hadoop生态系统学习之路(五)hbase的简单使用的相关文章

hadoop生态系统学习之路(八)hbase与hive的数据同步以及hive与impala的数据同步

在之前的博文中提到,hive的表数据是可以同步到impala中去的.一般impala是提供实时查询操作的,像比较耗时的入库操作我们可以使用hive,然后再将数据同步到impala中.另外,我们也可以在hive中创建一张表同时映射hbase中的表,实现数据同步. 下面,笔者依次进行介绍. 一.impala与hive的数据同步 首先,我们在hive命令行执行show databases;可以看到有以下几个数据库: 然后,我们在impala同样执行show databases;可以看到: 目前的数据库

hadoop生态系统学习之路(六)hive的简单使用

一.hive的基本概念与原理 Hive是基于Hadoop之上的数据仓库,能够存储.查询和分析存储在 Hadoop 中的大规模数据. Hive 定义了简单的类 SQL 查询语言,称为 HQL.它同意熟悉 SQL 的用户查询数据,同意熟悉 MapReduce 开发人员的开发自己定义的 mapper 和 reducer 来处理内建的 mapper 和 reducer 无法完毕的复杂的分析工作. Hive 没有专门的数据格式. hive的訪问方式: hive的运行原理: 二.hive的经常使用命令 连接

hadoop生态系统学习之路(九)MR将结果输出到数据库(DB)

最开始讲MapReduce的时候,我们是指定输出目录,然后把结果直接输出到hdfs上.然后,在介绍hive的简单使用时,我们直接将结果输出到了hive表中.另外,MR还可以将结果输出到数据库以及hbase. 今天,笔者就给大家介绍MR将结果输出到db. 首先,笔者要提及一下之前MR将结果输出到hive表,这里需要注意,只能向某张表中入一次数据,再次执行MR报错: org.apache.hive.hcatalog.common.HCatException : 2003 : Non-partitio

Hadoop生态系统学习路线

主要介绍Hadoop家族产品,常用的项目包括Hadoop, Hive, Pig, HBase, Sqoop, Mahout, Zookeeper, Avro, Ambari, Chukwa,新增加的项目包括,YARN, Hcatalog, Oozie, Cassandra, Hama, Whirr, Flume, Bigtop, Crunch, Hue等. 从2011年开始,中国进入大数据风起云涌的时代,以Hadoop为代表的家族软件,占据了大数据处理的广阔地盘.开源界及厂商,所有数据软件,无

hadoop之学习之路

关于Hadoop系列文章 http://mageedu.blog.51cto.com/4265610/1112878 Hadoop系列之四:MapReduce进阶 http://mageedu.blog.51cto.com/4265610/1106263

react.js学习之路五

最近没时间写博客,但是我一直在学习react,我发现react是一个巨大的坑,而且永远填不完的坑 关于字符串的拼接: 在react中,字符串的拼接不允许出现双引号"" ,只能使用单引号' ',例如这样就是可以的,这经常用在使用变量,变换路径的情况下. <img src={'img/sort_goods_0'+(index+1)+'x.png'} />

python学习之路 五:函数式编程

本节重点 掌握函数的作用.语法 掌握作用域.全局变量与局部变量知识 一.函数编程基础知识 1.基本定义 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需要调用函数名即可. 2.特性 ?(1)减少重复代码 ?(2)使程序变得可扩展 ?(3)使程序变得易维护 3.语法定义 def sayhi(): # 函数名 print("Hello,i'm nobody!") 二.函数参数 1.形参变量 只有在被调用时才分配内存单元,在调用结束时,即可释放所分配的内存单元.

Swift学习之路五(构造过程Initialization)

写在前面 喜欢我们的内容,可以订阅我们的官方微信公众账号:乐Coding.我们的iOS高级开发QQ群:386572485. 构造过程(Initialization),Swift中的构造器和Objective-C中的构造函数还是有很大不同的.即使Swift中类的构造器和值类型 (枚举和结构体)的构造器也有所不同. 下面我们慢慢看到底有那些不同. 1. 构造器,构造过程包括为实例中的每个属性设置初始值和为其执行必要的准备和初始化任务: 与 Objective-C 中的构造器不同,Swift 的构造器

Java学习之路(五)

1:补充: 使用super也可以调用父类的成员函数  格式 :  super.函数名(); 2:抽象类与抽象函数 抽象函数的定义: 只有函数的定义,没有函数体的函数被称为抽象函数 抽象类的定义: 使用abstract定义的类被称为抽象类 注意: 1:抽象类不能被实例化 2:如果一个类当中包含有抽象函数,那么这个类必须被声明为抽象类 3:如果一个类中没有抽象函数,那么这个类也可以被声明为抽象类 抽象类不能生成对象  却可以有构造函数 如果一个不是抽象的子类继承了抽象类那就必须实现抽象(父)类中的所