HBase伪分布式部署及JavaAPI操作

来源:互联网 发布:r数据分析师 编辑:程序博客网 时间:2024/05/22 15:38

HBase伪分布式部署及JavaAPI操作

本篇为HBase基本入门,HBase为Hadoop生态系统中的NoSql实现,所以它是最常用的形式是建立在Hadoop的HDFS上,故安装HBase前需先安装Hadoop(本篇基于Linux mint18 环境):

- Hadoop安装

  • Hadoop的下载
    Hadoop的下载地址为:http://mirror.bit.edu.cn/apache/hadoop/common/,一般下载最新的稳定版,我的下载为:hadoop-2.8.0.tar.gz
  • 配置Hadoop伪分布式部署配置
    Hadoop解压缩到一个当前用户拥有权限的路径,我的路径为:/home/linmint/programs/hadoop-2.8.0,接下来我用Hadoop来代替该解压缩路径。Hadoop的配置文件就位于Hadoop/etc/hadoop目录下,伪分布式部署需要修改2个配置文件:
    1、core-site.xml:在 configuration 标签中添加如下属性:

       <configuration>         <property>            <name>hadoop.tmp.dir</name>            <value>file:/home/linmint/tmp/hadoop</value>            <description>Abase for other temporary directories.</description>        </property>        <property>            <name>fs.defaultFS</name>            <value>hdfs://localhost:9000</value>        </property>    </configuration>

    其中file:/home/linmint/tmp/hadoop为本地临时存储路径。
    2、hdfs-site.xml:在Configuration标签中添加如下属性:

            <configuration>            <property>                <name>dfs.replication</name>                <value>1</value>            </property>            <property>                <name>dfs.namenode.name.dir</name>                <value>file:/home/linmint/tmp/hadoop/dfs/name</value>            </property>            <property>                <name>dfs.datanode.data.dir</name>                <value>file:/home/linmint/tmp/hadoop/dfs/data</value>            </property>        </configuration>

    其中file:/home/linmint/tmp/hadoop/dfs/name和file:/home/linmint/tmp/hadoop/dfs/data均为本地路径。

  • 执行 NameNode 的格式化
    在Hadoop目录下有两个含有大量命令的目录,分别是bin和sbin,bin目录主要用在操作HDFS文件系统上,sbin则包含在Linux环境下执行的命令,比如启动hadoop。
    执行NameNode的格式化命令:Hadoop/bin/hdfs namenode -format,执行成功会在控制台输出中找到successfully formatted的字样。如出现如下显示的错误:Error: JAVA_HOME is not set and could not be found.,表示JAVA_HOME路径没有配置正确,请在~/.bashrc中加入export JAVA_HOME=/usr/local/jdk1.7.80导出JAVA_HOME目录,并立即执行source ~/.bashrc使环境变量生效。该命令会将core-site.xml中配置的hadoop.tmp.dir目录格式化成Hadoop中标准的HDFS分布式文件系统形式。

  • 开启 NameNode 和 DataNode 守护进程
    执行如下命令开启hadoop:Hadoop/sbin/start-dfs.sh,在开户各个结点时会提示输入管理员密码,会有多次输入,可配置SSH公私匙避免多次输入密码。启动完成后,可用jps命令查看到如下信息node信息,浏览器输入 http://localhost:50070可WEB查看NameNode和DataNode结点信息。

  • 运行Hadoop伪分布式实例
    1、利用Hadoop/bin/hdfs dfs 这种shell命令形式操作HDFS文件系统,先建立用户目录:
    Hadoop/bin/hdfs dfs -mkdir /user/hadoop,该命令在HDFS文件系统中建立了一个目录,可以用:
    Hadoop/bin/hdfs dfs -ls / 命令查看目录。
    2、将Hadoop/etc/hadoop中的xml配置文件全部复制到HDFS文件系统中的/user/hadoop/input目录中,执行如下命令:
    Hadoop/bin/hdfs dfs -mkdir /user/hadoop/input
    Hadoop/bin/hdfs dfs -put Hadoop/etc/hadoop/*.xml /user/hadoop/input
    3、重启Hadoop,先停止原先启动的Hadoop,执行命令:Hadoop/sbin/stop-dfs.sh,停止之后再启动:Hadoop/sbin/start-dfs.sh,再用jps查看是否启动成功。
    至此Hadoop伪分布式完成启动。

-HBase安装

安装Hbase的伪分布式模式,首先得保证你的hadoop环境已经安装好,并且可以正常使用,因为hbase底层存储使用的是HDFS,所以安装Hbase前,务必先安装hadoop,并且启动顺序也是先启动Hadoop后启动HBase,同理关闭的顺序就反过来,先关闭HBase后关闭Hadoop。
- HBase的下载
HBase的下载地址为:https://mirrors.tuna.tsinghua.edu.cn/apache/hbase/,我下载的是:hbase-1.1.0-bin.tar.gz

-解压并配置伪分布式
将HBase解压缩到当前用户拥有全部权限的路径,本篇用HBase代替解压缩后路径,我的解压缩路径是:/home/linmint/programs/hbase-1.1.0。接着配置HBase/conf下的两个文件:
1、hbase-env.sh
在# The java implementation to use. Java 1.7+ required.注释下添加两行
export JAVA_HOME=/home/linmint/programs/jdk1.8.0_131(填写自己的jdk路径)
export HBASE_CLASSPATH=/home/linmint/programs/hbase-1.1.0/lib #HBase类路径,填写自己的
在# Tell HBase whether it should manage it’s own instance of Zookeeper or not.注释下添加一行
export HBASE_MANAGES_ZK=true
表示Hbase控制zookeeper的启动和结束,用的Hbase自带的zookeeper。
2、 hbase-site.xml
在configuration标签中添加如下属性:

 <configuration>     <property>              <name>hbase.rootdir</name>              <value>hdfs://localhost:9000/hbase</value>      </property>      <property>              <name>hbase.cluster.distributed</name>              <value>true</value>      </property>      <property>              <name>hbase.zookeeper.quorum</name>              <value>10.0.0.110</value>      </property>      <property>              <name>hbase.zookeeper.property.dataDir</name>              <value>/home/linmint/tmp/zookeeper</value>      </property>      <property>              <name>dfs.replication</name>              <value>2</value>      </property>     <property>        <name>hbase.regionserver.dns.nameserver</name>        <value>10.0.0.110</value>     </property></configuration>

其中,hbase.rootdir表示使用的HDFS文件系统,与Hadoop配置的fs.defaultFS一致。hbase.zookeeper.quorum表示zookeeper地址,默认端口为2181;hbase.regionserver.dns.nameserver一般也为本地地址。
配置完成后,先启动Hadoop,然后启动Hbase,用如下命令:
Hbase/start-hbase.sh,
Hbase/stop-hbase.sh停止Hbase。
用jps查看是否启动成功。
用Hbase/hbase shell 可进入Hbase shell操作客户端,在shell 中输入list 命令可查看表,输入scan ‘表名’可查看表数据。

-Java Client API

新建一个Maven项目,在pom.xml中引入Java Hbase Client API(同时引入spring-hbase,测试spring hbaseTemplate操作hbase):

    <dependencies>    <!-- 添加Spring-core包 -->    <dependency>        <groupId>org.springframework</groupId>        <artifactId>spring-core</artifactId>        <version>4.1.4.RELEASE</version>    </dependency>    <!-- 添加spring-context包 -->    <dependency>        <groupId>org.springframework</groupId>        <artifactId>spring-context</artifactId>        <version>4.1.4.RELEASE</version>    </dependency>    <dependency>        <groupId>org.apache.hbase</groupId>        <artifactId>hbase-client</artifactId>        <version>0.96.2-hadoop2</version>    </dependency>    <dependency>        <groupId>org.apache.hadoop</groupId>        <artifactId>hadoop-hdfs</artifactId>        <version>2.2.0</version>    </dependency>    <dependency>        <groupId>org.springframework.data</groupId>        <artifactId>spring-data-hadoop</artifactId>        <version>2.0.2.RELEASE</version>    </dependency>    <dependency>        <groupId>org.apache.zookeeper</groupId>        <artifactId>zookeeper</artifactId>        <version>3.4.6</version>    </dependency></dependencies>

拉下来直接粘贴对hbase建表及增删改查的代码,具体用户见代码注释:

import java.io.IOException;
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.KeyValue;
import org.apache.hadoop.hbase.client.Delete;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.HBaseAdmin;
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.client.ResultScanner;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.util.Bytes;
public class HBaseClient {
private static Configuration conf = null;
static {
conf = HBaseConfiguration.create();
conf.set(“hbase.zookeeper.quorum”, “10.0.0.110”);
}

/* * 创建表 *  * @tableName 表名 *  * @family 列族列表 */public static void creatTable(String tableName, String[] family)        throws Exception {    HBaseAdmin admin = new HBaseAdmin(conf);    HTableDescriptor desc = new HTableDescriptor(tableName);    for (int i = 0; i < family.length; i++) {        desc.addFamily(new HColumnDescriptor(family[i]));    }    if (admin.tableExists(tableName)) {        System.out.println("table Exists!");        System.exit(0);    } else {        admin.createTable(desc);        System.out.println("create table Success!");    }}/* * 为表添加数据(适合知道有多少列族的固定表) *  * @rowKey rowKey *  * @tableName 表名 *  * @column1 第一个列族列表 *  * @value1 第一个列的值的列表 *  * @column2 第二个列族列表 *  * @value2 第二个列的值的列表 */public static void addData(String rowKey, String tableName,        String[] column1, String[] value1, String[] column2, String[] value2)        throws IOException {    Put put = new Put(Bytes.toBytes(rowKey));// 设置rowkey    HTable table = new HTable(conf, Bytes.toBytes(tableName));// HTabel负责跟记录相关的操作如增删改查等//                                                                // 获取表    HColumnDescriptor[] columnFamilies = table.getTableDescriptor() // 获取所有的列族            .getColumnFamilies();    for (int i = 0; i < columnFamilies.length; i++) {        String familyName = columnFamilies[i].getNameAsString(); // 获取列族名        if (familyName.equals("article")) { // article列族put数据            for (int j = 0; j < column1.length; j++) {                put.add(Bytes.toBytes(familyName),                        Bytes.toBytes(column1[j]), Bytes.toBytes(value1[j]));            }        }        if (familyName.equals("author")) { // author列族put数据            for (int j = 0; j < column2.length; j++) {                put.add(Bytes.toBytes(familyName),                        Bytes.toBytes(column2[j]), Bytes.toBytes(value2[j]));            }        }    }    table.put(put);    System.out.println("add data Success!");}/* * 根据rwokey查询 *  * @rowKey rowKey *  * @tableName 表名 */public static Result getResult(String tableName, String rowKey)        throws IOException {    Get get = new Get(Bytes.toBytes(rowKey));    HTable table = new HTable(conf, Bytes.toBytes(tableName));// 获取表    Result result = table.get(get);    for (KeyValue kv : result.list()) {        System.out.println("family:" + Bytes.toString(kv.getFamily()));        System.out                .println("qualifier:" + Bytes.toString(kv.getQualifier()));        System.out.println("value:" + Bytes.toString(kv.getValue()));        System.out.println("Timestamp:" + kv.getTimestamp());        System.out.println("-------------------------------------------");    }    return result;}/* * 遍历查询hbase表 *  * @tableName 表名 */public static void getResultScann(String tableName) throws IOException {    Scan scan = new Scan();    ResultScanner rs = null;    HTable table = new HTable(conf, Bytes.toBytes(tableName));    try {        rs = table.getScanner(scan);        for (Result r : rs) {            for (KeyValue kv : r.list()) {                System.out.println("row:" + Bytes.toString(kv.getRow()));                System.out.println("family:"                        + Bytes.toString(kv.getFamily()));                System.out.println("qualifier:"                        + Bytes.toString(kv.getQualifier()));                System.out                        .println("value:" + Bytes.toString(kv.getValue()));                System.out.println("timestamp:" + kv.getTimestamp());                System.out                        .println("-------------------------------------------");            }        }    } finally {        rs.close();    }}/* * 遍历查询hbase表 *  * @tableName 表名 */public static void getResultScann(String tableName, String start_rowkey,        String stop_rowkey) throws IOException {    Scan scan = new Scan();    scan.setStartRow(Bytes.toBytes(start_rowkey));    scan.setStopRow(Bytes.toBytes(stop_rowkey));    ResultScanner rs = null;    HTable table = new HTable(conf, Bytes.toBytes(tableName));    try {        rs = table.getScanner(scan);        for (Result r : rs) {            for (KeyValue kv : r.list()) {                System.out.println("row:" + Bytes.toString(kv.getRow()));                System.out.println("family:"                        + Bytes.toString(kv.getFamily()));                System.out.println("qualifier:"                        + Bytes.toString(kv.getQualifier()));                System.out                        .println("value:" + Bytes.toString(kv.getValue()));                System.out.println("timestamp:" + kv.getTimestamp());                System.out                        .println("-------------------------------------------");            }        }    } finally {        rs.close();    }}/* * 查询表中的某一列 *  * @tableName 表名 *  * @rowKey rowKey */public static void getResultByColumn(String tableName, String rowKey,        String familyName, String columnName) throws IOException {    HTable table = new HTable(conf, Bytes.toBytes(tableName));    Get get = new Get(Bytes.toBytes(rowKey));    get.addColumn(Bytes.toBytes(familyName), Bytes.toBytes(columnName)); // 获取指定列族和列修饰符对应的列    Result result = table.get(get);    for (KeyValue kv : result.list()) {        System.out.println("family:" + Bytes.toString(kv.getFamily()));        System.out                .println("qualifier:" + Bytes.toString(kv.getQualifier()));        System.out.println("value:" + Bytes.toString(kv.getValue()));        System.out.println("Timestamp:" + kv.getTimestamp());        System.out.println("-------------------------------------------");    }}/* * 更新表中的某一列 *  * @tableName 表名 *  * @rowKey rowKey *  * @familyName 列族名 *  * @columnName 列名 *  * @value 更新后的值 */public static void updateTable(String tableName, String rowKey,        String familyName, String columnName, String value)        throws IOException {    HTable table = new HTable(conf, Bytes.toBytes(tableName));    Put put = new Put(Bytes.toBytes(rowKey));    put.add(Bytes.toBytes(familyName), Bytes.toBytes(columnName),            Bytes.toBytes(value));    table.put(put);    System.out.println("update table Success!");}/* * 查询某列数据的多个版本 *  * @tableName 表名 *  * @rowKey rowKey *  * @familyName 列族名 *  * @columnName 列名 */public static void getResultByVersion(String tableName, String rowKey,        String familyName, String columnName) throws IOException {    HTable table = new HTable(conf, Bytes.toBytes(tableName));    Get get = new Get(Bytes.toBytes(rowKey));    get.addColumn(Bytes.toBytes(familyName), Bytes.toBytes(columnName));    get.setMaxVersions(5);    Result result = table.get(get);    for (KeyValue kv : result.list()) {        System.out.println("family:" + Bytes.toString(kv.getFamily()));        System.out                .println("qualifier:" + Bytes.toString(kv.getQualifier()));        System.out.println("value:" + Bytes.toString(kv.getValue()));        System.out.println("Timestamp:" + kv.getTimestamp());        System.out.println("-------------------------------------------");    }    /*     * List<?> results = table.get(get).list(); Iterator<?> it =     * results.iterator(); while (it.hasNext()) {     * System.out.println(it.next().toString()); }     */}/* * 删除指定的列 *  * @tableName 表名 *  * @rowKey rowKey *  * @familyName 列族名 *  * @columnName 列名 */public static void deleteColumn(String tableName, String rowKey,        String falilyName, String columnName) throws IOException {    HTable table = new HTable(conf, Bytes.toBytes(tableName));    Delete deleteColumn = new Delete(Bytes.toBytes(rowKey));    deleteColumn.deleteColumns(Bytes.toBytes(falilyName),            Bytes.toBytes(columnName));    table.delete(deleteColumn);    System.out.println(falilyName + ":" + columnName + "is deleted!");}/* * 删除指定的列 *  * @tableName 表名 *  * @rowKey rowKey */public static void deleteAllColumn(String tableName, String rowKey)        throws IOException {    HTable table = new HTable(conf, Bytes.toBytes(tableName));    Delete deleteAll = new Delete(Bytes.toBytes(rowKey));    table.delete(deleteAll);    System.out.println("all columns are deleted!");}/* * 删除表 *  * @tableName 表名 */public static void deleteTable(String tableName) throws IOException {    HBaseAdmin admin = new HBaseAdmin(conf);    admin.disableTable(tableName);    admin.deleteTable(tableName);    System.out.println(tableName + "is deleted!");}public static void main(String[] args) throws Exception {    // TODO Auto-generated method stub    // 创建表    String tableName = "blog2";    String[] family = { "article", "author" };    creatTable(tableName, family);    // 为表添加数据    String[] column1 = { "title", "content", "tag" };    String[] value1 = {            "Head First HBase",            "HBase is the Hadoop database. Use it when you need random, realtime read/write access to your Big Data.",            "Hadoop,HBase,NoSQL" };    String[] column2 = { "name", "nickname" };    String[] value2 = { "nicholas", "lee" };    addData("rowkey1", "blog2", column1, value1, column2, value2);    addData("rowkey2", "blog2", column1, value1, column2, value2);    addData("rowkey3", "blog2", column1, value1, column2, value2);    // 遍历查询    getResultScann("blog2", "rowkey4", "rowkey5");    // 根据row key范围遍历查询    getResultScann("blog2", "rowkey4", "rowkey5");    // 查询    getResult("blog2", "rowkey1");    // 查询某一列的值    getResultByColumn("blog2", "rowkey1", "author", "name");    // 更新列    updateTable("blog2", "rowkey1", "author", "name", "bin");    // 查询某一列的值    getResultByColumn("blog2", "rowkey1", "author", "name");    // 查询某列的多版本    getResultByVersion("blog2", "rowkey1", "author", "name");    // 删除一列    deleteColumn("blog2", "rowkey1", "author", "nickname");    // 删除所有列    deleteAllColumn("blog2", "rowkey1");    // 删除表    deleteTable("blog2");}}

注意:hbase服务结点注册的zookeeper返回的计算机名而非ip地址,故调用端必须ping通该计算机名。我hbase在virtualbox虚拟机中,调用在宿主win10系统,为了能用计算机名访问linux虚拟机,则修改了win10的host文件,该文件的路径为:C:\Windows\System32\drivers\etc\hosts,在该文件末尾添加一行:10.0.0.110 linmint-VirtualBox,左边为ip,右边为zoo返回的计算机名,保存时可能提示无法保存,右键修改该文件安全属性,给该文件Users组写入权限,保存后即可ping 通计算机名。

接下来粘贴spring hbaseTemplate访问形式,与jdbcTemplate和mongoTemplate类似,先在xml文件中配置该模板:

<!-- 配置hbase连接 --><!-- HDFS配置 --><hdp:configuration id="hadoopConfiguration">fs.default.name=hdfs://10.0.0.110:9000</hdp:configuration><!-- HBase连接配置 --><hdp:hbase-configuration id="hbaseConfiguration" zk-quorum="10.0.0.110" zk-port="2181"/><!-- HbaseTemplate Bean配置--><bean id="hbaseTemplate" class="org.springframework.data.hadoop.hbase.HbaseTemplate">    <property name="configuration" ref="hbaseConfiguration"></property></bean>

因编辑器原因,一些spring头无法粘贴过来,故再来截图的形式:
这里写图片描述

接下来粘贴一个hbaseTemplate操作代码,其它的操作方法见文档:

ApplicationContext context = new ClassPathXmlApplicationContext("spring-hbase.xml");    HbaseTemplate hbTemplate = (HbaseTemplate)context.getBean("hbaseTemplate");    //插入数据    hbTemplate.execute(TABLE_NAME, new TableCallback<Boolean>() {        @Override        public Boolean doInTable(HTableInterface table) throws Throwable {            // TODO Auto-generated method stub            boolean flag = false;              try{                  byte[] rowkey = ROW_KEY.getBytes();                  Put put = new Put(rowkey);                  put.add(Bytes.toBytes(COLUMN_FAMILY),Bytes.toBytes(QUALIFIER), Bytes.toBytes("林"));                  table.put(put);               flag = true;              }catch(Exception e){                  e.printStackTrace();              }              return flag;        }    });

该代码需先在hbase中建立相应列族的表才能正常运行。

整个过程我是正常跑起来了,或者我在写的时候有什么遗漏,如遇问题可留言。